sorted() loses information about namedtuple elements
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 20.6k
- フォーク
- 3.3k
- 平均マージ
- 1日 18時間
- マージ済み PR(30日)
- 54
説明
Bug Report
it seems that running sorted() on an union of iterables of named tuple, create some missing information
To Reproduce
from typing import NamedTuple
from typing import reveal_type
class NamedTupleA(NamedTuple):
field_a: str
class NamedTupleB(NamedTuple):
field_b: str
def my_fun(my_list: list[NamedTupleA] | list[NamedTupleB]) -> None:
reveal_type(my_list)
# Revealed type is "Union[builtins.list[tuple[builtins.str, fallback=__main__.NamedTupleA]], builtins.list[tuple[builtins.str, fallback=__main__.NamedTupleB]]]"
for nt in my_list:
if isinstance(nt, NamedTupleA):
print(nt.field_a)
else:
# here nt is recognized of `NamedTupleB` type, I can access field_b
print(nt.field_b)
reveal_type(sorted(my_list))
# Revealed type is "builtins.list[tuple[builtins.str]]"
for sorted_nt in sorted(my_list):
if isinstance(sorted_nt, NamedTupleA):
print(sorted_nt.field_a)
else:
# here I expected nt to be recognized of `NamedTupleB` type
print(sorted_nt.field_b)
if __name__ == '__main__':
my_fun([NamedTupleA('value_1')])
my_fun([NamedTupleB('value_2')])
# this error is expected: I cannot mix NamedTupleA and NamedTupleB
my_fun([NamedTupleA('value_1'), NamedTupleB('value_2')])
basically I have 2 list of NamedTuples.
my_fun must accept either one.
Ideally I could write a User-Defined Type Guards, but let's say that I'm just checking (with isinstance) each element type.
If I loop directly over the list, the check works for both the if and the else branch (there shouldn't be any other case, the union is between two types)
If I loop directly over the sorted list, the type of the element is different, so in the else branch mypy gives me an error
Expected Behavior
I expect no errors on print(sorted_nt.field_b)
Actual Behavior
main.py:32: error: "tuple[str]" has no attribute "field_b" [attr-defined]
Your Environment
linux, python3.12, mypy 1.10.1
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
Python 3.12 と mypy 1.10.1 を使用して、リンクされた mypy playground の再現例から始め、main.py の sorted() の前後で表示される型を比較します。sorted() の結果が NamedTuple の各候補を保持し、isinstance 分岐で sorted_nt.field_a と sorted_nt.field_b が attr-defined エラーなしに受け入れられるようになれば、修正は完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- devtools
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 48/100