python / python/mypy

`@overload` incorrectly reports error if overload param would go to different params of implementation depending on positional vs keyword calling style

Abierto
#16,626 0 comentarios 3 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

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

Descripción

Bug Report

Type-checking on the @overload decorator incorrectly reports an error in the implementation function's signature when an argument would go to different parameters of an implementation function depending on whether that argument is passed as a positional or keyword argument, even if both outcomes are still valid.

To Reproduce

Here's a minimal possible example:

from typing import overload

@overload
def func(value: int):
    ...

def func(positional_only: int | None = None, /, value: int | None = None):
    pass

func can be correctly called with either of these signatures:

func(1)  # results in call with parameters(1, None)
func(value=1)  # results in call with parameters (None, 1)

Either of these calls is valid.

Expected Behavior

The type-checker considers the code valid. (Excluding the error that there's only one overload, which is expected in this minimal example).

Actual Behavior

type_test.py:8: error: Overloaded function implementation does not accept all possible arguments of signature 1  [misc]

Your Environment

  • Mypy version used: mypy 1.7.1 (compiled: yes)
  • Mypy command-line flags: python3 -m mypy ./type_test_2.py
  • Mypy configuration options from mypy.ini (and other config files): Not changed from the default
  • Python version used: Python 3.11.6

A motivating example

I wanted to define a lookup function that can lookup an object by id (an int) or name (a str), something like this:

from typing import overload

@overload
def lookup(id: int):
    ...

@overload
def lookup(name: str):
    ...

def lookup(id_or_name: int | str | None = None, /, id: int | None = None, name: str | None = None):
    if id is None and name is None:
        if isinstance(id_or_name, int): id = id_or_name
        else: name = id_or_name  # name is str

    if id is not None:
        return _lookup_by_id(id)
    else:
        return _lookup_by_name(name)


## Possible calls:

lookup(1)  # integer positional
lookup(id=1)  # integer keyword

lookup("foo")  # string positional
lookup(name="foo")  # string keyword

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

Empieza ejecutando el comando indicado python3 -m mypy ./type_test_2.py con el ejemplo mínimo de overload y confirma el error de firma de implementación. Sigue la comprobación de compatibilidad de la implementación del overload y añade cobertura para llamadas posicionales y por palabra clave que alcancen distintos parámetros de implementación. La tarea estará terminada cuando las llamadas válidas ya no produzcan el error indicado, mientras que las implementaciones de overload no válidas sigan siendo rechazadas.

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

Evaluación

Stack tecnológico
python
Área
devtools
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bien especificado
Aptitud para principiantes
45/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.