python / python/mypy

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

Abierto
#20,522 4 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

feature topic-runtime-semantics
Lenguaje dominante
Python
Estrellas
20.6k
Forks
3.3k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

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:

import asyncio

from collections.abc import Generator
from types import GeneratorType
from typing import Never, reveal_type


class A:
    def __await__(self) -> GeneratorType[Never, Never, bool]:
        return True
        yield  # generator definition


class B:
    def __await__(self) -> Generator[Never, Never, bool]:
        return True
        yield  # generator definition


async def main() -> None:
    reveal_type(await A())  # revealed type is "Any"
    reveal_type(await B())  # 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]

    if isgenerator(x):
        reveal_type(x)  # types.GeneratorType[Any, Any, Any]

    if isinstance(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.

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza con el caso de example.py del issue y compara los diagnósticos actuales de mypy con el comportamiento esperado de pyright. El trabajo estará terminado cuando types.GeneratorType se acepte como tipo de retorno de una función generadora y los tipos mostrados de await y de los atributos del generador se infieran como se espera.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
python
Área
devtools
Tipo de issue
Nueva funcionalidad
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
38/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.