mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
hanzoai 2.1.2 declares requires-python >= 3.9, yet `import hanzoai` raises TypeError on 3.9. grpo/enhanced_api_model_adapter.py annotates four returns as `str | Tuple[str, Optional[str]]`, which 3.9 evaluates at class-body time, and hanzoai/__init__.py imports grpo eagerly. grpo/enhanced_semantic_extractor.py has the same shape once, behind it. Postpone annotation evaluation in both modules. They are the only two in the package whose PEP 604 unions reach the interpreter. Their dataclasses never resolve annotations, so nothing else changes. tests/test_imports.py imports every module under hanzoai. A new CI job runs it after `pip install .` on 3.9 and 3.13, because the test job only runs .python-version (3.12), where the annotation is valid. Co-authored-by: Claude Opus 5 <[email protected]>
46 lines
1.7 KiB
Python
46 lines
1.7 KiB
Python
"""Every module in ``hanzoai`` imports on every Python that requires-python admits.
|
|
|
|
2.1.2 declared ``requires-python >= 3.9`` and could not be imported on 3.9 at all:
|
|
``grpo/enhanced_api_model_adapter.py`` annotated a return as ``str | Tuple[...]``,
|
|
which 3.9 evaluates at class-body time and rejects with ``TypeError``, and
|
|
``hanzoai/__init__.py`` imports ``grpo`` eagerly. The test job runs only
|
|
``.python-version`` (3.12), where that line is valid, so nothing could see it.
|
|
|
|
The module list comes from the filesystem rather than from importing the package,
|
|
so a package that fails to import shows up as a failing module instead of an
|
|
empty list.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
import importlib.util
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
def _module_names() -> list[str]:
|
|
spec = importlib.util.find_spec("hanzoai")
|
|
assert spec is not None and spec.submodule_search_locations
|
|
root = Path(next(iter(spec.submodule_search_locations)))
|
|
names = []
|
|
for path in sorted(root.rglob("*.py")):
|
|
parts = path.relative_to(root.parent).with_suffix("").parts
|
|
if parts[-1] == "__init__":
|
|
parts = parts[:-1]
|
|
names.append(".".join(parts))
|
|
return names
|
|
|
|
|
|
@pytest.mark.parametrize("name", _module_names())
|
|
def test_module_imports(name: str) -> None:
|
|
try:
|
|
importlib.import_module(name)
|
|
except ModuleNotFoundError as exc:
|
|
# An optional dependency that is not installed says nothing about this
|
|
# interpreter; a missing hanzoai module does.
|
|
if exc.name and exc.name.split(".")[0] != "hanzoai":
|
|
pytest.skip(f"optional dependency {exc.name} is not installed")
|
|
raise
|