[ty] Improve protocol member type checking and relation handling (#18847)

Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
This commit is contained in:
Shunsuke Shibayama 2025-06-29 19:46:33 +09:00 committed by GitHub
parent 9218bf72ad
commit de1f8177be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 519 additions and 132 deletions

View file

@ -371,14 +371,23 @@ class MyCallable:
f_wrong(MyCallable()) # raises `AttributeError` at runtime
```
If users want to write to attributes such as `__qualname__`, they need to check the existence of the
attribute first:
If users want to read/write to attributes such as `__qualname__`, they need to check the existence
of the attribute first:
```py
from inspect import getattr_static
def f_okay(c: Callable[[], None]):
if hasattr(c, "__qualname__"):
c.__qualname__ # okay
c.__qualname__ = "my_callable" # also okay
# `hasattr` only guarantees that an attribute is readable.
# error: [invalid-assignment] "Object of type `Literal["my_callable"]` is not assignable to attribute `__qualname__` on type `(() -> None) & <Protocol with members '__qualname__'>`"
c.__qualname__ = "my_callable"
result = getattr_static(c, "__qualname__")
reveal_type(result) # revealed: Never
if isinstance(result, property) and result.fset:
c.__qualname__ = "my_callable" # okay
```
[gradual form]: https://typing.python.org/en/latest/spec/glossary.html#term-gradual-form