This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author med2277
Recipients gvanrossum, kj, med2277
Date 2021-12-29.18:38:47
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1640803127.78.0.466747350347.issue46195@roundup.psfhosted.org>
In-reply-to
Content
This is two closely related issues with get_type_hints on an optional annotated member. I'm testing with Annotated/get_type_hints from typing extensions on 3.8 and assuming they're backport equivalent to current behavior.

The first issue is get_type_hints has inconsistent behavior depending on whether annotation comes from a function with a None default or an attribute with a None default.

class Foo:
    def __init__(
        self,
        x: 
            Annotated[Optional[str], "doc string"] = None,
    ):
        ...

class Foo2:
    x: Annotated[Optional[str], "doc string"] = None

get_type_hints(Foo.__init__) 
# {'x': typing.Union[typing_extensions.Annotated[typing.Union[str, NoneType], 'doc string'], NoneType]}

get_type_hints(Foo2)
# {'x': typing_extensions.Annotated[typing.Union[str, NoneType], 'doc string']}

Attributes with a None default are not wrapped by get_type_hints, but function parameters. Which of the two behaviors is correct I don't know, but I'd expect the two to be equivalent annotations.

The second issue is for function arguments with a None default the optional wrapper happens even if the type inside annotated already has optional. Example,

from typing_extensions import Annotated, get_type_hints

class Foo:
    def __init__(
        self,
        x: 
            Annotated[Optional[str], "doc string"] = None,
    ):
        ...

get_type_hints(Foo.__init__, include_extras=True)
# {'x': typing.Union[typing_extensions.Annotated[typing.Union[str, NoneType], 'doc string'], NoneType]}


For Annotated types I would expect any type rules like wrapping to apply only to the first argument and not the entire annotation. I mainly ran into this for a runtime type introspection library (similar in spirit to pydantic).

As a note include_extras being True or False while it changes type is an issue in either case. With include_extras as False the Annotated goes away, but the type still gets double wrapped as an Optional.
History
Date User Action Args
2021-12-29 18:38:47med2277setrecipients: + med2277, gvanrossum, kj
2021-12-29 18:38:47med2277setmessageid: <1640803127.78.0.466747350347.issue46195@roundup.psfhosted.org>
2021-12-29 18:38:47med2277linkissue46195 messages
2021-12-29 18:38:47med2277create