python / python/mypy

Wrapped methods are not properly resolved until after the class definition

Abierto
#16,397 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

bug
Lenguaje dominante
Python
Estrellas
20.6k
Forks
3.3k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

Context & setup

Consider the following simple protocol:

class Proto(Protocol):
    @property
    def f(self) -> int:
        ...

One can implement this protocol wrongly as follows:

T = TypeVar("T")
P = ParamSpec("P")


def wrapper(f: Callable[P, T]) -> Callable[P, str]:
    def wrapped(*args: P.args, **kwargs: P.kwargs) -> str:
        return 0

    return wrapped

class Impl:
    @wrapper  # converts return type from `bool` to `str`, while the protocol expects `int`
    def f(self) -> bool:
        return False

# error: Incompatible return value type (got "Impl", expected "Proto")  [return-value]
# note: Following member(s) of "Impl" have conflicts:
# note:     Expected:
# note:         def f(self) -> int
# note:     Got:
# note:         def f(self) -> str
def b() -> Proto:
    return Impl()

The bug (false negative)

When this same function b is placed before class Impl, mypy does not report an error. Adding reveal_type(Impl.f) before and after the class definition hints at what is going on:

main.py:21: error: Expression has type "Any"  [misc]
main.py:21: error: Cannot determine type of "f"  [has-type]
main.py:21: note: Revealed type is "Any"
main.py:21: error: Name "Impl" is used before definition  [used-before-def]

main.py:28: note: Revealed type is "def (self: __main__.Impl) -> builtins.str"

If f is not decorated but explicitly returns str, one gets

main.py:21: note: Revealed type is "def (self: __main__.Impl) -> builtins.str"
main.py:21: error: Name "Impl" is used before definition  [used-before-def]

main.py:27: note: Revealed type is "def (self: __main__.Impl) -> builtins.str"

as expected. This indicates that the wrapped decorator is only properly resolved for code after the class definition.

False positive variant

If f is decorated with @property, this can also produce false positives. This is how I encountered the issue in the first place. Playground.

Additional info

Python: 3.11
Mypy: 371219347a6d17e16924bbabf3e693c6874e7138
Flags: --strict --disallow-any-*

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

Reproduce el falso negativo y el falso positivo en main.py usando los ejemplos de mypy-play enlazados, comparando la ubicación de la función, @wrapper y @property. Rastrea cómo se resuelven el decorador y el tipo del método envuelto antes y después de class Impl; se considera terminado cuando ambas variantes informan de forma coherente los diagnósticos esperados de compatibilidad con el protocolo.

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

Evaluación

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

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.