You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[3.14] annotationlib - Union '|' syntax and typing.Union[...] generate different forward references. #132805
Using the union syntax gives a ForwardRef that can't be evaluated as the class that can be evaluated gets converted into its repr via ast.Constant. Using the typing.Union class however gives a proper union object where only the undefined value is a forwardref.
One possible solution to this is to add a create_unions attribute to the _StringifierDict. If this is True then the __or__ and __ror__ methods should create types.UnionType instances instead of calling __make_new. This is False for Format.STRING in order to keep a | b in the reproduction in that case.
I already have a branch with this approach so I can make a PR.
Doing this will break the current test_nonexistent_attribute ForwardRef test as some | obj would evaluate to ForwardRef('some') | ForwardRef('obj') instead of ForwardRef('some | obj') but I think this is probably correct and the test should be changed.
A more general approach to fix this would be to change the case in __convert_to_ast where we currently return ast.Constant(). Instead, we could pick a unique name, emit an ast.Name referring to that name, and make the ForwardRef remember a dictionary mapping such names to the original value. So in this case, we'd get something like ForwardRef("foo[$name1, undefined]", known_values={"$name1": str}). I can look into implementing that.
Ah, yes you're right. Sounds similar to what dataclasses needs to do to handle the values it needs for default values/types in exec. I'd only looked at exists[str, undefined] and not the case where the base object was undefined too.
Activity
JelleZijlstra commentedon Apr 22, 2025
Good catch. I think this is a more general problem though, for example:
A more general approach to fix this would be to change the case in
__convert_to_astwhere we currently returnast.Constant(). Instead, we could pick a unique name, emit anast.Namereferring to that name, and make the ForwardRef remember a dictionary mapping such names to the original value. So in this case, we'd get something likeForwardRef("foo[$name1, undefined]", known_values={"$name1": str}). I can look into implementing that.DavidCEllis commentedon Apr 22, 2025
Ah, yes you're right. Sounds similar to what
dataclassesneeds to do to handle the values it needs for default values/types in exec. I'd only looked atexists[str, undefined]and not the case where the base object was undefined too.gh-132805: annotationlib: Fix handling of non-constant values in FORW…
Merge remote-tracking branch 'origin/main' into call-len
pythongh-132805: annotationlib: Fix handling of non-constant values i…