Skip to content

Commit 11b5cbc

Browse files
authored
[red-knot] Restructure attribute-access and descriptor-protocol test suites. (#16664)
## Summary This is a pure restructuring of the `attributes.md` and `descriptor_protocol.md` test suites. They have grown organically and I didn't want to make major structural changes in my recent PR to keep the diff clean.
1 parent 3228545 commit 11b5cbc

File tree

2 files changed

+256
-245
lines changed

2 files changed

+256
-245
lines changed

crates/red_knot_python_semantic/resources/mdtest/attributes.md

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ def _(flag1: bool, flag2: bool):
808808
reveal_type(C5.attr1) # revealed: Unknown | Literal["metaclass value", "class value"]
809809
```
810810

811-
## Union of attributes
811+
## Unions of attributes
812812

813813
If the (meta)class is a union type or if the attribute on the (meta) class has a union type, we
814814
infer those union types accordingly:
@@ -854,43 +854,6 @@ def _(flag: bool):
854854
reveal_type(C4.x) # revealed: Unknown | Literal[7, 8]
855855
```
856856

857-
## Inherited class attributes
858-
859-
### Basic
860-
861-
```py
862-
class A:
863-
X = "foo"
864-
865-
class B(A): ...
866-
class C(B): ...
867-
868-
reveal_type(C.X) # revealed: Unknown | Literal["foo"]
869-
```
870-
871-
### Multiple inheritance
872-
873-
```py
874-
class O: ...
875-
876-
class F(O):
877-
X = 56
878-
879-
class E(O):
880-
X = 42
881-
882-
class D(O): ...
883-
class C(D, F): ...
884-
class B(E, D): ...
885-
class A(B, C): ...
886-
887-
# revealed: tuple[Literal[A], Literal[B], Literal[E], Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]]
888-
reveal_type(A.__mro__)
889-
890-
# `E` is earlier in the MRO than `F`, so we should use the type of `E.X`
891-
reveal_type(A.X) # revealed: Unknown | Literal[42]
892-
```
893-
894857
## Unions with possibly unbound paths
895858

896859
### Definite boundness within a class
@@ -1028,7 +991,58 @@ def _(flag: bool):
1028991
reveal_type(Foo().x) # revealed: Unknown | Literal[1]
1029992
```
1030993

1031-
### Attribute access on `Any`
994+
### Unions with all paths unbound
995+
996+
If the symbol is unbound in all elements of the union, we detect that:
997+
998+
```py
999+
def _(flag: bool):
1000+
class C1: ...
1001+
class C2: ...
1002+
C = C1 if flag else C2
1003+
1004+
# error: [unresolved-attribute] "Type `Literal[C1, C2]` has no attribute `x`"
1005+
reveal_type(C.x) # revealed: Unknown
1006+
```
1007+
1008+
## Inherited class attributes
1009+
1010+
### Basic
1011+
1012+
```py
1013+
class A:
1014+
X = "foo"
1015+
1016+
class B(A): ...
1017+
class C(B): ...
1018+
1019+
reveal_type(C.X) # revealed: Unknown | Literal["foo"]
1020+
```
1021+
1022+
### Multiple inheritance
1023+
1024+
```py
1025+
class O: ...
1026+
1027+
class F(O):
1028+
X = 56
1029+
1030+
class E(O):
1031+
X = 42
1032+
1033+
class D(O): ...
1034+
class C(D, F): ...
1035+
class B(E, D): ...
1036+
class A(B, C): ...
1037+
1038+
# revealed: tuple[Literal[A], Literal[B], Literal[E], Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]]
1039+
reveal_type(A.__mro__)
1040+
1041+
# `E` is earlier in the MRO than `F`, so we should use the type of `E.X`
1042+
reveal_type(A.X) # revealed: Unknown | Literal[42]
1043+
```
1044+
1045+
## Attribute access on `Any`
10321046

10331047
The union of the set of types that `Any` could materialise to is equivalent to `object`. It follows
10341048
from this that attribute access on `Any` resolves to `Any` if the attribute does not exist on
@@ -1059,20 +1073,6 @@ reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[B], Any, Literal[A
10591073
reveal_type(C.x) # revealed: Literal[1] & Any
10601074
```
10611075

1062-
### Unions with all paths unbound
1063-
1064-
If the symbol is unbound in all elements of the union, we detect that:
1065-
1066-
```py
1067-
def _(flag: bool):
1068-
class C1: ...
1069-
class C2: ...
1070-
C = C1 if flag else C2
1071-
1072-
# error: [unresolved-attribute] "Type `Literal[C1, C2]` has no attribute `x`"
1073-
reveal_type(C.x) # revealed: Unknown
1074-
```
1075-
10761076
## Objects of all types have a `__class__` method
10771077

10781078
The type of `x.__class__` is the same as `x`'s meta-type. `x.__class__` is always the same value as
@@ -1125,6 +1125,8 @@ reveal_type(Foo.__class__) # revealed: Literal[type]
11251125

11261126
## Module attributes
11271127

1128+
### Basic
1129+
11281130
`mod.py`:
11291131

11301132
```py
@@ -1159,7 +1161,7 @@ for mod.global_symbol in IntIterable():
11591161
pass
11601162
```
11611163

1162-
## Nested attributes
1164+
### Nested module attributes
11631165

11641166
`outer/__init__.py`:
11651167

0 commit comments

Comments
 (0)