sphinx-autodoc-pytest-fixtures: Resolve TypeAlias names in fixture return types#9
Merged
sphinx-autodoc-pytest-fixtures: Resolve TypeAlias names in fixture return types#9
Conversation
fdabadf to
0fb9de2
Compare
…E_CHECKING blocks why: _qualify_forward_ref only resolved ImportFrom nodes inside TYPE_CHECKING guards, leaving TypeAlias definitions (AnnAssign with TypeAlias annotation) unqualified — fixture tables showed bare unlinked alias names. what: - _metadata.py: add _is_type_alias_annotation() helper; extend the TYPE_CHECKING AST walk in _qualify_forward_ref to also match AnnAssign nodes whose annotation is TypeAlias (bare or t.TypeAlias attribute form) - tests: new test_type_checking_alias.py with 10 unit + 1 integration test covering both `t.TypeAlias` and bare `TypeAlias` annotation forms, the non-alias AnnAssign guard, import-wins-over-alias priority, and full Sphinx build verification of return_display qualification
…s in fixture table why: Fixtures annotated with a TypeAlias (e.g. ``-> UnihanTestOptions``) showed the expanded union (``Options | Mapping[str, Any]``) instead of the alias name, because get_type_hints() resolved the alias away. what: - _detection.py: after get_type_hints, if raw annotation is a bare identifier but the resolved type's name doesn't match, return the raw string to preserve the alias name for cross-reference resolution - _metadata.py: _qualify_forward_ref now scans tree.body (module-level) for TypeAlias AnnAssign nodes in addition to TYPE_CHECKING blocks - tests: 6 new TDD tests covering module-level TypeAlias resolution and _get_return_annotation alias preservation
…lias values why: _qualify_forward_ref fast path used the alias VALUE's __module__/ __qualname__ (e.g. "typing.Union") when a module-level TypeAlias was accessible at runtime, returning "typing.Union" instead of the alias name. what: - fast path: only accept obj when obj.__qualname__ == name (the requested identifier), so TypeAlias union values don't steal the cross-reference - test: test_qualify_forward_ref_fast_path_skips_typealias_value verifies module-level TypeAlias values do not trigger the fast path
…ypeAlias expansions why: Previous guard (resolved_name != raw_ann) falsely classified import-aliased classes (e.g. UnihanOptions = Options) as TypeAlias expansions because Options.__qualname__ != "UnihanOptions". This caused the fixture to show the raw string instead of resolving to the class. what: - _detection.py: replace qualname-mismatch guard with isinstance(ret, type) — real classes return True (use resolved), union/generic TypeAlias expansions return False (preserve raw alias name) - test: test_get_return_annotation_class_import_alias_resolves_to_class verifies that import-aliased classes are still resolved to the class
0fb9de2 to
3728a8c
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #9 +/- ##
==========================================
+ Coverage 88.59% 88.87% +0.27%
==========================================
Files 71 72 +1
Lines 6955 7107 +152
==========================================
+ Hits 6162 6316 +154
+ Misses 793 791 -2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
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.
Problem
Fixtures whose return type is a
TypeAliasshowed the expanded underlying type in the fixture summary table rather than the alias name. For example, a fixture annotated-> UnihanTestOptions(whereUnihanTestOptions: TypeAlias = Options | Mapping[str, Any]) rendered asOptions | Mapping[str, Any]instead ofUnihanTestOptions.Three bugs compounded.
get_type_hints()silently expands TypeAlias names._get_return_annotationcallsget_type_hints(), which resolves the annotation string"UnihanTestOptions"against the module namespace and returns the underlying union type — losing the alias name entirely before_qualify_forward_refever runs.Fast path in
_qualify_forward_refreturns the alias value's identity, not the alias name. When a TypeAlias is defined at module level,getattr(mod, name)returns the alias value (e.g. the union type, whose__qualname__is"Union"). The fast path then returned"typing.Union"instead of"module.AliasName"._qualify_forward_refonly scannedif TYPE_CHECKING:blocks forImportFromnodes. TypeAlias definitions — whether inside a TYPE_CHECKING guard (Name: TypeAlias = ...) or at module level — were not handled.Solution
_get_return_annotation: afterget_type_hints()succeeds, check whether the raw annotation was a bare identifier that resolved to a non-class type (union, generic alias). If so, return the raw string instead of the expanded type. The discriminator isisinstance(ret, type): real classes (including import-aliased ones) returnTrue; union/generic TypeAlias expansions returnFalse._qualify_forward_reffast path: guard the fast path so it only fires whenobj.__qualname__ == name. TypeAlias values have__qualname__ == "Union", so they no longer steal the cross-reference._qualify_forward_refslow path: add_is_type_alias_annotation()to recogniseTypeAliasandt.TypeAlias/typing.TypeAliasannotation forms. Extend the AST scan to handle two new cases:Name: TypeAlias = ...inside a TYPE_CHECKING block (Case 2), andName: TypeAlias = ...at module level (Case 3). TYPE_CHECKING ImportFrom still takes priority when the same name appears in both locations.Test plan
test_type_checking_alias.pypass, covering: bare vs attributeTypeAliasform, TYPE_CHECKING vs module-level placement, non-alias AnnAssign ignored, import-wins-over-alias priority, fast-path TypeAlias value guard, import-aliased class still resolves to the class