# Class attributes ## Union of attributes ```py def bool_instance() -> bool: return True flag = bool_instance() if flag: class C1: x = 1 else: class C1: x = 2 class C2: if flag: x = 3 else: x = 4 reveal_type(C1.x) # revealed: Literal[1, 2] reveal_type(C2.x) # revealed: Literal[3, 4] ``` ## Inherited attributes ```py class A: X = "foo" class B(A): ... class C(B): ... reveal_type(C.X) # revealed: Literal["foo"] ``` ## Inherited attributes (multiple inheritance) ```py class O: ... class F(O): X = 56 class E(O): X = 42 class D(O): ... class C(D, F): ... class B(E, D): ... class A(B, C): ... # revealed: tuple[Literal[A], Literal[B], Literal[E], Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]] reveal_type(A.__mro__) # `E` is earlier in the MRO than `F`, so we should use the type of `E.X` reveal_type(A.X) # revealed: Literal[42] ``` ## Unions with possibly unbound paths ### Definite boundness within a class In this example, the `x` attribute is not defined in the `C2` element of the union: ```py def bool_instance() -> bool: return True class C1: x = 1 class C2: ... class C3: x = 3 flag1 = bool_instance() flag2 = bool_instance() C = C1 if flag1 else C2 if flag2 else C3 # error: [possibly-unbound-attribute] "Attribute `x` on type `Literal[C1, C2, C3]` is possibly unbound" reveal_type(C.x) # revealed: Literal[1, 3] ``` ### Possibly-unbound within a class We raise the same diagnostic if the attribute is possibly-unbound in at least one element of the union: ```py def bool_instance() -> bool: return True class C1: x = 1 class C2: if bool_instance(): x = 2 class C3: x = 3 flag1 = bool_instance() flag2 = bool_instance() C = C1 if flag1 else C2 if flag2 else C3 # error: [possibly-unbound-attribute] "Attribute `x` on type `Literal[C1, C2, C3]` is possibly unbound" reveal_type(C.x) # revealed: Literal[1, 2, 3] ``` ## Unions with all paths unbound If the symbol is unbound in all elements of the union, we detect that: ```py def bool_instance() -> bool: return True class C1: ... class C2: ... flag = bool_instance() C = C1 if flag else C2 # error: [unresolved-attribute] "Type `Literal[C1, C2]` has no attribute `x`" reveal_type(C.x) # revealed: Unknown ```