Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[3.14] annotationlib - Union '|' syntax and typing.Union[...] generate different forward references. #132805

Copy link
Copy link
Closed
@DavidCEllis

Description

@DavidCEllis
Issue body actions

Bug report

Bug description:

While looking into #125618 I ran into this case.

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.

  • str | undefined -> ForwardRef("<class 'str'> | undefined")
  • Union[str, undefined] -> str | ForwardRef("undefined")

Example:

from annotationlib import get_annotations, Format
from typing import Union

class DifferentUnions:
    attrib: str | undefined
    other_attrib: Union[str, undefined]

different_unions = get_annotations(DifferentUnions, format=Format.FORWARDREF)

print(different_unions)

Formatted Output:

{
    'attrib': ForwardRef("<class 'str'> | undefined", is_class=True, owner=<class '__main__.DifferentUnions'>), 
    'other_attrib': str | ForwardRef('undefined', is_class=True, owner=<class '__main__.DifferentUnions'>)
}

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.

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.14bugs and security fixesbugs and security fixesstdlibPython modules in the Lib dirPython modules in the Lib dirtopic-typingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.