Skip to content

Allow types.GeneratorType to be used instead of collections.abc.Generator as the return type of generator functions #20522

Description

@x42005e1f

Feature

Currently, mypy only allows collections.abc.Generator and its supertypes as the return type of generator functions, and as a result, it cannot infer the correct return type for awaitable objects that define the __await__() method via types.GeneratorType:

importasynciofromcollections.abcimportGeneratorfromtypesimportGeneratorTypefromtypingimportNever, reveal_typeclassA:
def__await__(self) ->GeneratorType[Never, Never, bool]:
returnTrueyield# generator definitionclassB:
def__await__(self) ->Generator[Never, Never, bool]:
returnTrueyield# generator definitionasyncdefmain() ->None:
reveal_type(awaitA()) # revealed type is "Any"reveal_type(awaitB()) # revealed type is "builtins.bool"reveal_type(A().__await__().gi_running) # revealed type is "builtins.bool"reveal_type(B().__await__().gi_running) # has no attribute "gi_running"if__name__=="__main__":
asyncio.run(main())
example.py:9: error: The return type of a generator function should be "Generator" or one of its supertypes [misc]
example.py:21: note: Revealed type is "Any"
example.py:22: note: Revealed type is "builtins.bool"
example.py:24: note: Revealed type is "builtins.bool"
example.py:25: error: "Generator[Never, Never, bool]" has no attribute "gi_running" [attr-defined]
example.py:25: note: Revealed type is "Any"
Found 2 errors in 1 file (checked 1 source file)

I propose allowing the use of types.GeneratorType with subsequent inference of the correct return type.

Pitch

First, pyright already has the expected behavior:

/home/user/workspace/example.py
/home/user/workspace/example.py:21:17 - information: Type of "await A()" is "bool"
/home/user/workspace/example.py:22:17 - information: Type of "await B()" is "bool"
/home/user/workspace/example.py:24:17 - information: Type of "A().__await__().gi_running" is "bool"
/home/user/workspace/example.py:25:17 - information: Type of "B().__await__().gi_running" is "Unknown"
/home/user/workspace/example.py:25:33 - error: Cannot access attribute "gi_running" for class "Generator[Never, Never, bool]"
Attribute "gi_running" is unknown (reportAttributeAccessIssue)
1 error, 0 warnings, 4 informations

Second, this relates to the eternally controversial python/typing#1480. In python/typeshed#10816, false properties related to native objects were removed in favor of the types module. You could say that we can use isinstance/inspect.isgenerator to narrow collections.abc.Generator down to types.GeneratorType, but... it is not that simple:

x=B().__await__()
reveal_type(x) # typing.Generator[Never, Never, builtins.bool]ifisgenerator(x):
reveal_type(x) # types.GeneratorType[Any, Any, Any]ifisinstance(x, GeneratorType):
reveal_type(x) # types.GeneratorType[Any, Any, Any]

I think that allowing the use of types.GeneratorType would make it easier to inspect native generator objects. Especially since collections.abc.Generator can also be used to define custom generator types.

Related: #18635.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions