From 6d2ed0dc73344605d83abb6ae13fde3fd3c59fe2 Mon Sep 17 00:00:00 2001 From: Divyam Talwar Date: Sat, 4 Jul 2026 02:25:04 +0530 Subject: [PATCH] Preserve SDK imports on supported Python versions Constraint: The Python SDK metadata declares >=3.8, while Python 3.9 import failed on runtime-evaluated newer annotation syntax. Rejected: Raise the SDK Python floor to >=3.10 | This keeps the existing published support contract and only changes annotation syntax. Confidence: high Scope-risk: narrow Directive: Add a minimum-version SDK import or collection CI job before relying on future syntax changes. Tested: Python 3.9 import smoke; Python 3.9 SDK live-test collection with SKIP_LIVE_TESTS=1; SDK tests with live tests skipped (74 passed, 26 skipped); py_compile on changed Python files; Python 3.8 grammar parse and annotation compatibility scan; changelog markdown render; git diff --check. Not-tested: Python 3.8 runtime import because uv interpreter download did not complete locally; ty has existing unrelated SDK diagnostics; ruff is unavailable locally. --- sdks/python/CHANGELOG.md | 3 +++ sdks/python/morphik/_internal.py | 2 +- sdks/python/morphik/async_.py | 4 ++-- sdks/python/morphik/sync.py | 4 ++-- sdks/python/morphik/tests/test_async.py | 3 ++- sdks/python/morphik/tests/test_sync.py | 3 ++- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/sdks/python/CHANGELOG.md b/sdks/python/CHANGELOG.md index 2a536af6..d052407d 100644 --- a/sdks/python/CHANGELOG.md +++ b/sdks/python/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- Restored SDK import and test collection compatibility on Python 3.9 by avoiding newer runtime annotation syntax. + ## [1.2.6] - 2026-06-19 ### Changed diff --git a/sdks/python/morphik/_internal.py b/sdks/python/morphik/_internal.py index ede461bc..be7426a8 100644 --- a/sdks/python/morphik/_internal.py +++ b/sdks/python/morphik/_internal.py @@ -26,7 +26,7 @@ class FinalChunkResult(BaseModel): - content: str | PILImage = Field(..., description="Chunk content") + content: Union[str, PILImage] = Field(..., description="Chunk content") score: float = Field(..., description="Relevance score") document_id: str = Field(..., description="Parent document ID") chunk_number: int = Field(..., description="Chunk sequence number") diff --git a/sdks/python/morphik/async_.py b/sdks/python/morphik/async_.py index 3223593c..425e2508 100644 --- a/sdks/python/morphik/async_.py +++ b/sdks/python/morphik/async_.py @@ -4,7 +4,7 @@ import warnings from io import BytesIO from pathlib import Path -from typing import Any, BinaryIO, Callable, Dict, List, Literal, Optional, Type, Union +from typing import Any, BinaryIO, Callable, Dict, List, Literal, Optional, Tuple, Type, Union from urllib.parse import quote import httpx @@ -1441,7 +1441,7 @@ async def _ingest_migrated_document( end_user_id: Optional[str], use_colpali: bool, on_conflict: Literal["skip", "fail"], - ) -> tuple[str, Document]: + ) -> Tuple[str, Document]: serialized_metadata, inferred_types = self._logic._serialize_metadata_map(metadata) metadata_type_payload = {**inferred_types, **(metadata_types or {})} metadata_type_payload = { diff --git a/sdks/python/morphik/sync.py b/sdks/python/morphik/sync.py index f0c3e756..bab77e22 100644 --- a/sdks/python/morphik/sync.py +++ b/sdks/python/morphik/sync.py @@ -3,7 +3,7 @@ import warnings from io import BytesIO from pathlib import Path -from typing import Any, BinaryIO, Callable, Dict, List, Literal, Optional, Type, Union +from typing import Any, BinaryIO, Callable, Dict, List, Literal, Optional, Tuple, Type, Union from urllib.parse import quote import httpx @@ -1483,7 +1483,7 @@ def _ingest_migrated_document( end_user_id: Optional[str], use_colpali: bool, on_conflict: Literal["skip", "fail"], - ) -> tuple[str, Document]: + ) -> Tuple[str, Document]: serialized_metadata, inferred_types = self._logic._serialize_metadata_map(metadata) metadata_type_payload = {**inferred_types, **(metadata_types or {})} metadata_type_payload = { diff --git a/sdks/python/morphik/tests/test_async.py b/sdks/python/morphik/tests/test_async.py index 006fb7ba..5ac6c425 100644 --- a/sdks/python/morphik/tests/test_async.py +++ b/sdks/python/morphik/tests/test_async.py @@ -2,6 +2,7 @@ import os import uuid from pathlib import Path +from typing import List import pytest from morphik.async_ import AsyncMorphik @@ -22,7 +23,7 @@ class StructuredOutputSchema(BaseModel): summary: str = Field(..., description="A short summary of the input text") - key_points: list[str] = Field(..., description="A list of key points from the text") + key_points: List[str] = Field(..., description="A list of key points from the text") class TestAsyncMorphik: diff --git a/sdks/python/morphik/tests/test_sync.py b/sdks/python/morphik/tests/test_sync.py index 29d91e40..4f319c0e 100644 --- a/sdks/python/morphik/tests/test_sync.py +++ b/sdks/python/morphik/tests/test_sync.py @@ -2,6 +2,7 @@ import time import uuid from pathlib import Path +from typing import List import pytest from morphik.sync import Morphik @@ -22,7 +23,7 @@ class StructuredOutputSchema(BaseModel): summary: str = Field(..., description="A short summary of the input text") - key_points: list[str] = Field(..., description="A list of key points from the text") + key_points: List[str] = Field(..., description="A list of key points from the text") class TestMorphik: