mypy infer incorrect types in frozen dataclass with descriptors as attributes.
オープン
まだ誰も着手していません。
bug
- 主要言語
- Python
- スター
- 20.6k
- フォーク
- 3.3k
- PR マージ指標
- PR 指標を取得中
説明
I am having issues with frozen dataclass that inherits from a frozen dataclass with descriptors as attributes. mypy infer incorrect datatypes of the attributes from the base class. If the dataclasses are not frozen, then mypy infer correct datatypes in inherited class.
Below is the minimal code to reproduce the issue.
python=3.11
mypy=1.14.0
To Reproduce
from abc import ABCMeta, abstractmethod
from dataclasses import dataclass
from typing import Self, SupportsFloat, TypeVar, overload, Type, Optional, Generic, Any
T = TypeVar("T")
V = TypeVar("V")
class Base(Generic[T, V], metaclass=ABCMeta):
def __set_name__(self, owner: type, name: str) -> None:
self.public_name = name
self.private_name = "_" + name
@overload
def __get__(self, instance: None, owner: Optional[Type[Any]] = None) -> Self:...
@overload
def __get__(self, instance: Any, owner: Optional[Type[Any]] = None) -> V | None:...
def __get__(self, instance: Any, owner: Optional[Type[Any]] = None) -> Self | V | None:
if instance is None:
return self
return getattr(instance, self.private_name, None)
def __set__(self, instance: Any, value: Optional[T]) -> None:
if value is self or value is None:
return
converted = self._converter(value)
object.__setattr__(instance, self.private_name, converted)
@abstractmethod
def _converter(self, value: T) -> V:
"""
Hook to implement conversion logic
"""
class FloatParameter(Base[SupportsFloat, float]):
def _converter(self, value: SupportsFloat) -> float:
"""Can have more logic here to check if value can be converted to float"""
return float(value)
@dataclass(frozen=True, kw_only=True)
class BaseDataClass:
float_param: FloatParameter = FloatParameter()
@dataclass(frozen=True, kw_only=True)
class DerivedDataClass(BaseDataClass):
boolean: bool = True
reveal_type(BaseDataClass.float_param) # correct FloatParameter
reveal_type(DerivedDataClass.float_param) # Incorrect Union[typing.SupportsFloat, None]
reveal_type(BaseDataClass().float_param) # Correct "Union[builtins.float, None]"
reveal_type(DerivedDataClass().float_param) # Incorrect Union[typing.SupportsFloat, None]
NOTE: Pylance on the other hand on VSCode shows correct datatypes.
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
mypy 1.14.0 を使用した最小限の Python 3.11 再現から始め、BaseDataClass と DerivedDataClass の reveal_type の結果を比較します。descriptor 属性を持つ frozen dataclass の継承を調査します。派生クラスがクラス上では FloatParameter、インスタンス上では float | None を報告し、基底クラスと一致すれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- devtools
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 45/100