Type inference on `owner` argument to `__set_name__`
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 20.6k
- フォーク
- 3.3k
- PR マージ指標
- PR 指標を取得中
説明
Because of the circumstances under which __set_name__ is invoked, it should be possible to perform type inference on its owner argument, in a way which could be used to statically typecheck other components of a descriptor.
As a brief motivating example, below is a sketch of descriptor for a validated mutable attribute of integer type:
from __future__ import annotations
from typing import Any, Generic, Protocol, Self, Type, TypeVar, cast, overload
InstanceT = TypeVar("InstanceT")
InstanceT_contra = TypeVar("InstanceT_contra", contravariant=True)
class Validator(Protocol[InstanceT_contra]):
def __call__(self, instance: InstanceT_contra, value: int, /) -> bool:
...
class IntAttr(Generic[InstanceT]):
__validator: Validator[InstanceT]
__name: str
def __init__(self, validator: Validator[InstanceT]) -> None:
self.__validator = validator
def __set_name__(self, owner: Type[InstanceT], name: str) -> None:
self.__name = name
@overload
def __get__(self, instance: None, _: Type[Any]) -> Self:
...
@overload
def __get__(self, instance: InstanceT, _: Type[Any]) -> int:
...
def __get__(self, instance: InstanceT|None, _: Type[Any]) -> int | Self:
if instance is None:
return self
return cast(int, getattr(instance, f"__{self.__name}"))
def __set__(self, instance: InstanceT, value: int) -> None:
if not self.__validator(instance, value):
raise ValueError()
setattr(instance, f"__{self.__name}", value)
class C:
x = IntAttr(lambda self, value: self.validate(value)) # Pylance error
def validate(self, value: int) -> bool:
return value >= 10
In Pylance with strict typechecking rules, the definition of the x descriptor raises the following errors:
reportUnknownMemberType
Type of "validate" is unknown
reportUnknownLambdaType
Return type of lambda is unknown
reportGeneralTypeIssues
Cannot access member "validate" for type "object*"
Member "validate" is unknown
Currently, Mypy doesn't raise any errors about the lack of lambda typing (not even for incorrect implementations, such as self.validatez(value) or self.validate(str(value))). Mypy also doesn't raise errors about incorrect lambda implementations once an explicit type hint is provided (see below), while Pylance does.
I opened a separate issue about this: https://github.com/python/mypy/issues/16797
Explicitly providing a hint for the InstanceT type removes the errors for Pylance:
class C:
x = IntAttr["C"](lambda self, value: self.validate(value)) # Errors
def validate(self, value: int) -> bool:
return value >= 10
Performing inference on the owner argument to IntAttr.__set_name__ in the context of class C would ideally result in C being inferred as a value for InstanceT, allowing for static typecheking of the validator lambda function without the need for an explicit type hint.
Related issues for Mypy:
- https://github.com/python/mypy/issues/10246
- https://github.com/python/mypy/issues/8057
- issues about typing of lambdas
Sister issue for Pylance/Pyright: https://github.com/microsoft/pyright/issues/7039
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
descriptor の例と、set_name への owner 引数に対して要求されている推論から始めてください。issue では実装ファイルやテストは特定されていません。次に、関連する Mypy issue 10246 と 8057 を確認し、クラス本体での推論によって validator lambda をどのように型付けすべきか、また誤った実装をどのように拒否すべきかを判断してください。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- devtools
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 30/100