python / python/mypy

attrs plugin does not support generic type

オープン
#18,973 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

bug topic-attrs
主要言語
Python
スター
20.6k
フォーク
3.3k
PR マージ指標
PR 指標を取得中

説明

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

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

mypy/plugins/attrs.py の 914 行目付近にある attrs.evolve の処理から始め、提供されている Python 3.12 のジェネリック例を mypy 1.15.0 に対して実行して診断を確認します。attrs.has が Any と未束縛の型パラメーターでそれぞれどのように認識されるかを追跡し、ジェネリック例が変数型エラーなしで受け入れられ、期待される戻り値の型が維持されることを確認して完了とします。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
tooling
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
48/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。