Files
simple-nanoshare/tests/test_python_features.py
daniel156161 73fdeacbfe
Build and Push Docker Container / build-and-push (push) Successful in 2m25s
feat!: adopt Python 3.14 and 3.15 language features
- Require Python 3.15 for the server and Python 3.14 for the CLI.
- Match the server requirement to quart_common's Python 3.15 features.
- Replace future annotations with native deferred evaluation.
- Defer CLI command dependencies and QR imports on Python 3.15.
- Enable argparse suggestions for mistyped CLI commands.
- Remove the obsolete tomllib import fallback.
- Update my_helpers and quart_common submodule references.
- Lock test dependencies and exclude them from Docker installations.
- Add regression coverage for lazy imports and deferred annotations.
- Document runtime requirements and standalone CLI validation.
- Validate 276 tests on Python 3.15 and 18 CLI tests on Python 3.14.

BREAKING CHANGE: The server now requires Python 3.15+ and the standalone CLI requires Python 3.14+.
2026-10-26 14:47:29 +01:00

64 lines
2.0 KiB
Python

"""Exercise version-specific behavior in clean interpreters, not import stubs."""
import os
from pathlib import Path
import subprocess
import sys
import pytest
ROOT = Path(__file__).resolve().parents[1]
def run_python(code):
env = os.environ.copy()
env['PYTHONPATH'] = os.pathsep.join([str(ROOT / 'cli'), str(ROOT)])
# Test the module opt-ins, independently of global import/color settings.
env.pop('PYTHON_LAZY_IMPORTS', None)
env['NO_COLOR'] = '1'
return subprocess.run(
[sys.executable, '-c', code], cwd=ROOT, env=env,
capture_output=True, text=True, check=True,
)
def test_cli_typo_suggests_command():
result = run_python("""
from nanoshare_client.cli import main
try:
main(['uplod'])
except SystemExit as exc:
assert exc.code == 2
""")
assert "maybe you meant 'upload'" in result.stderr
@pytest.mark.skipif(sys.version_info < (3, 15), reason='PEP 810 requires Python 3.15')
def test_help_and_completion_do_not_load_network_or_watch_modules():
run_python("""
import sys
from nanoshare_client.cli import main
try:
main(['--help'])
except SystemExit as exc:
assert exc.code == 0
assert main(['completion', 'bash']) == 0
for name in ('httpx', 'nanoshare_client.auth', 'nanoshare_client.sync', 'nanoshare_client.watch'):
assert name not in sys.modules, name
""")
@pytest.mark.skipif(sys.version_info < (3, 15), reason='PEP 810 requires Python 3.15')
def test_qr_import_is_lazy_but_rendering_still_works():
run_python("""
import sys
from link_composer.qr import make_qr_png
assert 'qrcode' not in sys.modules
assert make_qr_png('https://example.com').startswith(b'\\x89PNG')
assert 'qrcode' in sys.modules
""")
def test_deferred_annotations_resolve_to_types():
run_python("""
from typing import get_type_hints
from my_modules.upload_content import MultipartUploadParts, parse_multipart_upload_body
assert not isinstance(parse_multipart_upload_body.__annotations__['return'], str)
assert get_type_hints(parse_multipart_upload_body)['return'] is MultipartUploadParts
""")