You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
attrs.evolve: support generics and unions (#15050)
Fixes `attrs.evolve` signature generation to support the `inst`
parameter being
- a generic attrs class
- a union of attrs classes
- a mix of the two
In the case of unions, we "meet" the fields of the potential attrs
classes, so that the resulting signature is the lower bound.
Fixes#15088.
a2 = attrs.evolve(a_or_b, x=42, y=True, z='42') # E: Argument "z" to "evolve" of "Union[A[int], B]" has incompatible type "str"; expected <nothing>
2019
+
a2 = attrs.evolve(a_or_b, x=42, y=True, w={}) # E: Argument "w" to "evolve" of "Union[A[int], B]" has incompatible type "Dict[<nothing>, <nothing>]"; expected <nothing>
2020
+
2021
+
[builtins fixtures/attr.pyi]
2022
+
2023
+
[case testEvolveUnionOfTypeVar]
2024
+
# flags: --python-version 3.10
2025
+
import attrs
2026
+
from typing import TypeVar
2027
+
2028
+
@attrs.define
2029
+
class A:
2030
+
x: int
2031
+
y: int
2032
+
z: str
2033
+
w: dict
2034
+
2035
+
2036
+
class B:
2037
+
pass
2038
+
2039
+
TA = TypeVar('TA', bound=A)
2040
+
TB = TypeVar('TB', bound=B)
2041
+
2042
+
def f(b_or_t: TA | TB | int) -> None:
2043
+
a2 = attrs.evolve(b_or_t) # E: Argument 1 to "evolve" has type "Union[TA, TB, int]" whose item "TB" is not bound to an attrs class # E: Argument 1 to "evolve" has incompatible type "Union[TA, TB, int]" whose item "int" is not an attrs class
2044
+
2045
+
2046
+
[builtins fixtures/attr.pyi]
2047
+
1973
2048
[case testEvolveTypeVarBound]
1974
2049
import attrs
1975
2050
from typing import TypeVar
@@ -1997,11 +2072,12 @@ f(B(x=42))
1997
2072
1998
2073
[case testEvolveTypeVarBoundNonAttrs]
1999
2074
import attrs
2000
-
from typing import TypeVar
2075
+
from typing import Union, TypeVar
2001
2076
2002
2077
TInt = TypeVar('TInt', bound=int)
2003
2078
TAny = TypeVar('TAny')
2004
2079
TNone = TypeVar('TNone', bound=None)
2080
+
TUnion = TypeVar('TUnion', bound=Union[str, int])
2005
2081
2006
2082
def f(t: TInt) -> None:
2007
2083
_ = attrs.evolve(t, x=42) # E: Argument 1 to "evolve" has a variable type "TInt" not bound to an attrs class
@@ -2012,6 +2088,9 @@ def g(t: TAny) -> None:
2012
2088
def h(t: TNone) -> None:
2013
2089
_ = attrs.evolve(t, x=42) # E: Argument 1 to "evolve" has a variable type "TNone" not bound to an attrs class
2014
2090
2091
+
def x(t: TUnion) -> None:
2092
+
_ = attrs.evolve(t, x=42) # E: Argument 1 to "evolve" has incompatible type "TUnion" whose item "str" is not an attrs class # E: Argument 1 to "evolve" has incompatible type "TUnion" whose item "int" is not an attrs class
0 commit comments