Open
Conversation
…, and dev environment file
Added unit and integration tests to ensure that 'TemplateLanguage' (bool) and 'Variables' (dict) are correctly serialized into JSON and successfully accepted by the Mailjet Send API v3.1.
- client: add secret redaction (__repr__/__str__), strict timeout validation, and urllib3 Retry adapter for 5xx errors. - tests: fix TypeError in integration tests by sourcing credentials directly from os.environ. - tests: add unit tests for OWASP mitigations and adapter mounting.
…radation This commit introduces significant Developer Experience (DX) improvements while preserving 100% backward compatibility for a seamless 1.x upgrade path. Key additions & changes: - Resource Management: Implemented Context Managers (with Client(...)) for automatic TCP connection pooling and socket cleanup. - Smart Telemetry: Automatically extract Mailjet Trace IDs (CustomID, Campaign, TemplateID) and inject them into debug logs. - Advanced Timeouts: Upgraded the timeout parameter to accept tuple[float, float] and float, increasing the default to 60s to better handle heavy API operations (e.g., CSV imports, Content API). - Graceful Degradation: Llegacy exceptions (AuthorizationError, etc.), kwargs (ensure_ascii, data_encoding), and utility functions (parse_response), wrapping them in standard DeprecationWarnings. - Poka-Yoke Guardrails: Decoupled Magic Method Trap prevention into a pure utility function (validate_attribute_access). - Executable Documentation: Consolidated legacy smoke tests into smoke_readme_runner.py to dynamically test all README examples. - Documentation: Refactored README.md to follow DRY principles and highlight modern DX configurations. - CI/CD: Updated Dependabot groups and aligned GH Actions with master. - Testing: Added comprehensive unit tests for deprecations and context managers. Refs: #125
This commit finalizes the migration to Ruff by completely removing legacy linters and formatters (Black, Flake8, Pylint, Pydocstyle) from the development environments and project configurations. It also expands the testing matrix to ensure forward compatibility. Key changes: Tooling Consolidation: Removed obsolete dependencies from environment-dev.yaml and pyproject.toml, establishing Ruff as the single source of truth. Config Cleanup: Purged dead configuration sections (tool.black, tool.flake8, tool.autopep8, tool.pydocstyle) from pyproject.toml. Ruff Alignment: Updated the Ruff ignore list to strictly preserve architectural constraints and prevent formatter conflicts (e.g., ISC001, COM812). Forward Compatibility: Added Python 3.14 to the GitHub Actions matrix and PyPI classifiers. Runtime Dependencies: Added typing-extensions to environment.yaml and environment-dev.yaml for robust cross-version type hinting support. Code Quality: Formatted code, removed unused imports (suppress), and stripped legacy migration comments from the smoke_readme_runner.py script. Refs: #125
…ience Major restructuring of the SDK to implement Zero-Trust principles and mitigate several CWE-class vulnerabilities. Core Architectural Changes: Decoupled validation and routing logic into a dedicated mailjet_rest.utils.guardrails module (System Decomposition). Extracted payload preparation (_prepare_payload) and centralized logging (_log_response) from api_call to ensure Single Responsibility. Updated Smart Telemetry to include automatic log sanitization. Security Mitigations (Shift-Left): CWE-113 (CRLF Injection): Strict header validation to block HTTP Request Smuggling. CWE-117 (Log Forging): Mandatory telemetry sanitization via sanitize_log_trace. CWE-918 (SSRF): Hostname allow-listing in Config initialization to prevent credential exfiltration. CWE-601 (Open Redirect): Hard-disabled automatic redirects for all API calls. CWE-316 (Secret Leakage): Enhanced redaction in repr and str to prevent sensitive data in traces. Testing and Resilience: Modernized test suite to use pytest.warns for auditing security warnings instead of brittle log interception. Upgraded smoke_readme_runner with a safe_cleanup pattern to handle environmental 401 (permissions) and 404 (eventual consistency) errors. Fixed path traversal assertions to align with standard urllib.parse.quote behavior. Updated CHANGELOG.md with explicit CWE mapping for security auditing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Links:
Jira
Actions:
Core SDK & Client:
requests.Sessionfor connection pooling, drastically improving performance for sequential requests.Configinto a@dataclassfor cleaner configuration state management.Decompose
Endpoint._build_urlandClient.api_callto resolve cyclomatic complexity (C901), extracting_check_dx_guardrails,_build_csv_url, and telemetry extraction into pure@staticmethods.__all__in__init__.pyto prevent namespace pollution.logging, and deprecating legacy custom logging handlers.Implement Graceful Degradation for legacy kwargs (
ensure_ascii,data_encoding) and utility functions (parse_response), wrapping them in standardDeprecationWarningsinstead of breaking the API.Upgrade the
timeoutparameter to accepttuple[float, float]andfloat, increasing the default to60sto better handle heavy API operations.Security & Developer Experience (DX):
urllib.parse.quoteto dynamically injectedidandaction_idpath parameters.httpsscheme and requiring a valid hostname duringConfiginitialization.logger.warningevents when detecting ambiguous routing (e.g., using singular/templatein Content APIv1or routing Send API outside ofv3/v3.1).Implement Graceful Degradation for legacy HTTP exceptions (
AuthorizationError,ActionDeniedError, etc.), restoring them to preserve 100% backward compatibility for existingtry/exceptblocks.Integrate Smart Telemetry to automatically extract Mailjet Trace IDs (
CustomID,Campaign,TemplateID) from payloads and inject them into debug logs.Unit & Integration Tests:
test.pyand segregate tests intotests/unit/(offline mocked tests) andtests/integration/(live network tests).unittestclasses to modernpytestfixtures, refactoring assertions into the AAA (Arrange, Act, Assert) pattern.v3) and Content API (v1), ensuring clean teardown viatry/finally.test_legacy_deprecations.py) and context manager lifecycle.CI/CD, Linting & Repository Management:
Consolidate tooling by migrating completely to Ruff as the single source of truth for formatting and linting, purging legacy tools (Black, Flake8, Pylint, Pydocstyle) from
pyproject.tomland environments.Update GitHub Actions to utilize pip caching, verify compiled
.whlartifacts usingtwinecheck, and expand the testing matrix to include Python 3.14..github/dependabot.ymlto group minor/patch updates and scan GitHub Actions.Makefile.environment-dev.yamlstrictly withpyproject.tomland addtyping-extensionsfor robust cross-version type hinting (<3.11).Documentation & Samples:
README.mdwith newLogging & Debuggingguides, updated Python compatibility (3.10-3.14), and modern Content API multipart upload examples.samples/to safely fetch credentials usingos.environ.get().CHANGELOG.mdsamples/smoke_readme_runner.pyto dynamically test allREADMEexamples.