fix: resolve annotations with get_type_hints in attach_settings#20
Merged
dusktreader merged 1 commit intomainfrom Mar 19, 2026
Merged
Conversation
…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
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.
Summary
NameErrorcrash whenattach_settingsdecorates a function whose annotations are stored as strings — either because the module usesfrom __future__ import annotationsor because Python 3.14+ (PEP 649) stores annotations as strings by defaultattach_settingsnow callstyping.get_type_hints()to resolve annotations before comparing them againstsettings_model/SettingsManager, so string and evaluated annotations are handled identicallyfunc.__annotations__(the cloaking device injection that hides parameters from typer's help output) are preserved as-isRoot cause
The previous implementation read
func.__annotations__directly:When annotations are strings (e.g.
"CrolTrollSettings"instead of the class), theiscomparison always fails silently — settings and manager parameters are never cloaked — and Python 3.14's annotation evaluation machinery can raiseNameError: name 'Context' is not definedwhen it tries to resolve the string"Context"in the wrapper's scope.Changes
src/typerdrive/settings/attach.py: resolve viaget_type_hints()before comparingtests/unit/settings/string_annotation_module.py: new helper module defined underfrom __future__ import annotationsto replicate Python 3.14 string-annotation behaviour on all supported versionstests/unit/settings/test_attach.py: addedTestStringAnnotationswith two testspyproject.toml: bumped to0.9.2CHANGELOG.md: added entry forv0.9.2