fix: Keep quotes on string members of unresolved Literal annotations#466
fix: Keep quotes on string members of unresolved Literal annotations#466gaoflow wants to merge 1 commit into
Conversation
A `Literal[...]` whose name could not be resolved (e.g. used without an import) kept its bare name "Literal" as canonical path, so the guard in `_build_subscript` that enables `literal_strings` only matched the resolved `typing.Literal`/`typing_extensions.Literal` spellings. String members of an unresolved `Literal` were then treated as forward references: `Literal['a-b']` was mis-parsed as `Literal[a - b]` and `Literal['a', 'b']` as `Literal[a, b]`. Add the bare "Literal" spelling to the set. A user-defined `Literal` resolves to a dotted path (e.g. `mod.Literal`), so it is not over-matched, and forward references elsewhere (e.g. `list['Foo']`) are unaffected.
|
Thanks for the PR @gaoflow. Can you tell me why this is useful? In what case would someone use |
|
Thanks. I agree that valid code should normally import it; I am not trying to encourage using The useful part here is mostly defensive/lossless parsing for source that Griffe can parse but cannot resolve completely. For example, with The current behavior changes meaning quite a bit: x: Literal['a-b']is rendered as The change is intentionally narrow: it only handles the bare unresolved canonical path |
For reviewers
Description of the change
A
Literal[...]whose name could not be resolved (for example used withoutfrom typing import Literal) keeps its bare name"Literal"as its canonical path. The guard in_build_subscriptthat enablesliteral_stringsonly matched the resolved spellingstyping.Literal/typing_extensions.Literal, so for an unresolvedLiteralthe string members were treated as forward references and re-parsed:A resolved
Literalkeeps the quotes (Literal['a-b']), and value-position strings always keep theirs, so the two paths were inconsistent.This adds the bare
"Literal"spelling to that set. A genuinely user-definedLiteralresolves to a dotted path (e.g.mod.Literal), so it is not over-matched, and forward references elsewhere (e.g.list['Foo']→list[Foo]) are unaffected.Verified:
Literal['a-b'],Literal['a', 'b'],Literal['hello world'](unresolved) now round-trip with quotes intact.Literal,typing.Literal[...], aliased import, int literals, andlist['Foo']still resolving its forward reference.tests/test_expressions.py(it fails before the change, passes after).test_expressions.py: 146 passed.ruff checkclean (zero new warnings).Relevant resources