Skip to content

fix: resolve annotations with get_type_hints in attach_settings#20

Merged
dusktreader merged 1 commit intomainfrom
fix/NO-TICKET--string-annotation-compat
Mar 19, 2026
Merged

fix: resolve annotations with get_type_hints in attach_settings#20
dusktreader merged 1 commit intomainfrom
fix/NO-TICKET--string-annotation-compat

Conversation

@dusktreader
Copy link
Copy Markdown
Owner

Summary

  • Fixes a NameError crash when attach_settings decorates a function whose annotations are stored as strings — either because the module uses from __future__ import annotations or because Python 3.14+ (PEP 649) stores annotations as strings by default
  • attach_settings now calls typing.get_type_hints() to resolve annotations before comparing them against settings_model / SettingsManager, so string and evaluated annotations are handled identically
  • Mutations to func.__annotations__ (the cloaking device injection that hides parameters from typer's help output) are preserved as-is

Root cause

The previous implementation read func.__annotations__ directly:

for key in func.__annotations__.keys():
    if func.__annotations__[key] is settings_model:

When annotations are strings (e.g. "CrolTrollSettings" instead of the class), the is comparison always fails silently — settings and manager parameters are never cloaked — and Python 3.14's annotation evaluation machinery can raise NameError: name 'Context' is not defined when it tries to resolve the string "Context" in the wrapper's scope.

Changes

  • src/typerdrive/settings/attach.py: resolve via get_type_hints() before comparing
  • tests/unit/settings/string_annotation_module.py: new helper module defined under from __future__ import annotations to replicate Python 3.14 string-annotation behaviour on all supported versions
  • tests/unit/settings/test_attach.py: added TestStringAnnotations with two tests
  • pyproject.toml: bumped to 0.9.2
  • CHANGELOG.md: added entry for v0.9.2

…tings

Python 3.14 (PEP 649) stores function annotations as unevaluated strings
by default; the same effect occurs on any Python version when a module uses
`from __future__ import annotations`.  The previous implementation read
`func.__annotations__` directly and compared values with `is` against the
target types, so those comparisons always failed for string annotations and
could raise a NameError when Python's machinery tried to resolve the strings.

- Use `typing.get_type_hints()` to resolve annotations before comparing
- Mutations to `func.__annotations__` (cloaking device injection) are kept
  as-is since typer reads them at decoration time
- Added `tests/unit/settings/string_annotation_module.py` to hold helpers
  defined under `from __future__ import annotations` to replicate the
  Python 3.14 string-annotation behaviour on all supported versions
- Added `TestStringAnnotations` class with two tests covering settings and
  manager parameter injection when annotations are strings
- Bumped version to 0.9.2
@dusktreader dusktreader merged commit 58be093 into main Mar 19, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant