@@ -1685,6 +1685,103 @@ date.year = 2025
16851685date.tz = " UTC"
16861686```
16871687
1688+ ### Setting attributes on unions
1689+
1690+ Setting attributes on unions where all elements of the union have the attribute is acceptable
1691+
1692+ ``` py
1693+ from typing import Union
1694+
1695+ class A :
1696+ x: int
1697+
1698+ class B :
1699+ x: int
1700+
1701+ C = Union[A, B]
1702+
1703+ a: C = A()
1704+ a.x = 42
1705+ ```
1706+
1707+ Setting attributes on unions where any element of the union does not have the attribute reports
1708+ possibly unbound
1709+
1710+ ``` py
1711+ from typing import Union, Sequence
1712+
1713+ class A :
1714+ pass
1715+
1716+ class B :
1717+ x: int
1718+
1719+ C = Union[A, B]
1720+
1721+ def _ (a : C):
1722+ a.x = 42 # TODO : error: [possibly-unbound-attribute]
1723+ ```
1724+
1725+ The same goes for
1726+
1727+ ``` py
1728+ from dataclasses import dataclass
1729+ from typing import Union, Sequence
1730+ from abc import ABC
1731+
1732+ class Base (ABC ):
1733+ x: Sequence[bytes ] = ()
1734+
1735+ class Derived (Base ):
1736+ pass
1737+
1738+ class Other :
1739+ pass
1740+
1741+ D = Union[Derived, Other]
1742+
1743+ d: D = Other()
1744+
1745+ # TODO : error: [possibly-unbound-attribute]
1746+ # error: [unresolved-attribute]
1747+ d.x = None
1748+ ```
1749+
1750+ Setting attributes on a generic where the upper bound is a union, and not all elements of the union
1751+ have the attribute, also reports possibly unbound:
1752+
1753+ ``` py
1754+ from typing import Union, TypeVar
1755+
1756+ class A :
1757+ pass
1758+
1759+ class B :
1760+ x: int
1761+
1762+ C = TypeVar(" C" , bound = Union[A, B])
1763+
1764+ def _ (a : C):
1765+ a.x = 42 # error: [possibly-unbound-attribute]
1766+ ```
1767+
1768+ ### Assigning to a data descriptor attribute
1769+
1770+ This is invalid
1771+
1772+ ``` py
1773+ class A :
1774+ def __init__ (self , x : int ):
1775+ self .x = x
1776+
1777+ @ property
1778+ def y (self ) -> int :
1779+ return self .x
1780+
1781+ a = A(42 )
1782+ a.y = 1 # error: [invalid-assignment] "Invalid assignment to data descriptor attribute `y` on type `A` with custom `__set__` method"
1783+ ```
1784+
16881785### ` argparse.Namespace `
16891786
16901787A standard library example of a class with a custom ` __setattr__ ` method is ` argparse.Namespace ` :
0 commit comments