python / python/mypy

attrs plugin does not support generic type

Abierto
#18,973 1 comentario 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

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

Descripción

Bug Report

The mypy attrs plugin has custom support for attrs.evolve, which has different code branches for regular and generic types (starting here).

It admits attrs.has as a type guard for attrs.evolve if the original type is Any, but not if it's a generic type parameter T with no type bound.

To Reproduce

On python 3.12 (so lacking copy.replace):

def replace[T](value: T, **kwargs: Any) -> T:
    if attrs.has(type(value)):
        return attrs.evolve(value, **kwargs)
    else:
        raise NotImplementedError(f"replace is not implemented for {type(value)}")

Mypy reports, error: Argument 1 to "evolve" has a variable type "T" not bound to an attrs class [misc]

(In the actual code I'd do something else in other branches; this is intended as a replacement for copy.replace on python < 3.13, supporting different types besides attrs classes.)

Using the attr.AttrInstance protocol also doesn't work, which means I can't define my own type guard wrapping attrs.has. This code results in the same mypy error:

def replace[T: attrs.AttrsInstance](value: T, **kwargs: Any) -> T:
    return attrs.evolve(value, **kwargs)

However, this code works (and is a viable workaround):

def replace[T](value: T, **kwargs: Any) -> T:
    val2: Any = value
    if attrs.has(type(val2)):
        return attrs.evolve(val2, **kwargs)
    else:
        raise NotImplementedError(f"replace is not implemented for {type(value)}")

Expected Behavior

Mypy should honor attrs.has as a type guard for attrs.evolve, whether the original type is generic or any other kind.

  • Mypy version used: 1.15.0
  • Python version used: 3.12.10

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 en mypy/plugins/attrs.py, alrededor del manejo de attrs.evolve en la línea 914, y luego ejecuta el ejemplo genérico proporcionado de Python 3.12 con mypy 1.15.0 para observar el diagnóstico. Rastrea cómo se reconoce attrs.has para Any frente a un parámetro de tipo no vinculado, y confirma la finalización cuando el ejemplo genérico se acepta sin el error de tipo de variable, manteniendo el tipo de retorno esperado.

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
Bien especificado
Aptitud para principiantes
48/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.