Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita2f3780

Browse files
committed
dataclasses.replace: fall through to typeshed sig
1 parent7f65cc7 commita2f3780

File tree

4 files changed

+51
-36
lines changed

4 files changed

+51
-36
lines changed

‎mypy/plugins/dataclasses.py‎

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -966,25 +966,6 @@ def _has_direct_dataclass_transform_metaclass(info: TypeInfo) -> bool:
966966
)
967967

968968

969-
def_fail_not_dataclass(ctx:FunctionSigContext,t:Type,parent_t:Type)->None:
970-
t_name=format_type_bare(t,ctx.api.options)
971-
ifparent_tist:
972-
msg= (
973-
f'Argument 1 to "replace" has a variable type "{t_name}" not bound to a dataclass'
974-
ifisinstance(t,TypeVarType)
975-
elsef'Argument 1 to "replace" has incompatible type "{t_name}"; expected a dataclass'
976-
)
977-
else:
978-
pt_name=format_type_bare(parent_t,ctx.api.options)
979-
msg= (
980-
f'Argument 1 to "replace" has type "{pt_name}" whose item "{t_name}" is not bound to a dataclass'
981-
ifisinstance(t,TypeVarType)
982-
elsef'Argument 1 to "replace" has incompatible type "{pt_name}" whose item "{t_name}" is not a dataclass'
983-
)
984-
985-
ctx.api.fail(msg,ctx.context)
986-
987-
988969
def_get_expanded_dataclasses_fields(
989970
ctx:FunctionSigContext,typ:ProperType,display_typ:ProperType,parent_typ:ProperType
990971
)->list[CallableType]|None:
@@ -993,9 +974,7 @@ def _get_expanded_dataclasses_fields(
993974
For generic classes, the field types are expanded.
994975
If the type contains Any or a non-dataclass, returns None; in the latter case, also reports an error.
995976
"""
996-
ifisinstance(typ,AnyType):
997-
returnNone
998-
elifisinstance(typ,UnionType):
977+
ifisinstance(typ,UnionType):
999978
ret:list[CallableType]|None= []
1000979
foritemintyp.relevant_items():
1001980
item=get_proper_type(item)
@@ -1012,14 +991,12 @@ def _get_expanded_dataclasses_fields(
1012991
elifisinstance(typ,Instance):
1013992
replace_sym=typ.type.get_method(_INTERNAL_REPLACE_SYM_NAME)
1014993
ifreplace_symisNone:
1015-
_fail_not_dataclass(ctx,display_typ,parent_typ)
1016994
returnNone
1017995
replace_sig=replace_sym.type
1018996
assertisinstance(replace_sig,ProperType)
1019997
assertisinstance(replace_sig,CallableType)
1020998
return [expand_type_by_instance(replace_sig,typ)]
1021999
else:
1022-
_fail_not_dataclass(ctx,display_typ,parent_typ)
10231000
returnNone
10241001

10251002

‎test-data/unit/check-dataclasses.test‎

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,6 +2106,8 @@ a2 = replace(a, x='42', q=42) # E: Argument "x" to "replace" of "A" has incompa
21062106
a2 = replace(a, q='42') # E: Argument "q" to "replace" of "A" has incompatible type "str"; expected "int"
21072107
reveal_type(a2) # N: Revealed type is "__main__.A"
21082108

2109+
[builtins fixtures/tuple.pyi]
2110+
21092111
[case testReplaceUnion]
21102112
from typing import Generic, Union, TypeVar
21112113
from dataclasses import dataclass, replace, InitVar
@@ -2135,7 +2137,7 @@ _ = replace(a_or_b, x=42, y=True, z='42', init_var=42) # E: Argument "z" to "re
21352137
_ = replace(a_or_b, x=42, y=True, w={}, init_var=42) # E: Argument "w" to "replace" of "Union[A[int], B]" has incompatible type "Dict[<nothing>, <nothing>]"; expected <nothing>
21362138
_ = replace(a_or_b, y=42, init_var=42) # E: Argument "y" to "replace" of "Union[A[int], B]" has incompatible type "int"; expected "bool"
21372139

2138-
[builtins fixtures/dataclasses.pyi]
2140+
[builtins fixtures/tuple.pyi]
21392141

21402142
[case testReplaceUnionOfTypeVar]
21412143
from typing import Generic, Union, TypeVar
@@ -2155,7 +2157,9 @@ TA = TypeVar('TA', bound=A)
21552157
TB = TypeVar('TB', bound=B)
21562158

21572159
def f(b_or_t: Union[TA, TB, int]) -> None:
2158-
a2 = replace(b_or_t) # E: Argument 1 to "replace" has type "Union[TA, TB, int]" whose item "TB" is not bound to a dataclass # E: Argument 1 to "replace" has incompatible type "Union[TA, TB, int]" whose item "int" is not a dataclass
2160+
a2 = replace(b_or_t) # E: Value of type variable "_DataclassT" of "replace" cannot be "Union[TA, TB, int]"
2161+
2162+
[builtins fixtures/tuple.pyi]
21592163

21602164
[case testReplaceTypeVarBoundNotDataclass]
21612165
from dataclasses import dataclass, replace
@@ -2167,16 +2171,18 @@ TNone = TypeVar('TNone', bound=None)
21672171
TUnion = TypeVar('TUnion', bound=Union[str, int])
21682172

21692173
def f1(t: TInt) -> None:
2170-
_ = replace(t, x=42) # E:Argument 1 to "replace" has a variable type "TInt" not bound to a dataclass
2174+
_ = replace(t, x=42) # E:Value of type variable "_DataclassT" of "replace" cannot be "TInt"
21712175

21722176
def f2(t: TAny) -> TAny:
2173-
return replace(t, x='spam') # E:Argument 1 to "replace" has a variable type "TAny" not bound to a dataclass
2177+
return replace(t, x='spam') # E:Value of type variable "_DataclassT" of "replace" cannot be "TAny"
21742178

21752179
def f3(t: TNone) -> TNone:
2176-
return replace(t, x='spam') # E:Argument 1 to "replace" has a variable type "TNone" not bound to a dataclass
2180+
return replace(t, x='spam') # E:Value of type variable "_DataclassT" of "replace" cannot be "TNone"
21772181

21782182
def f4(t: TUnion) -> TUnion:
2179-
return replace(t, x='spam') # E: Argument 1 to "replace" has incompatible type "TUnion" whose item "str" is not a dataclass # E: Argument 1 to "replace" has incompatible type "TUnion" whose item "int" is not a dataclass
2183+
return replace(t, x='spam') # E: Value of type variable "_DataclassT" of "replace" cannot be "TUnion"
2184+
2185+
[builtins fixtures/tuple.pyi]
21802186

21812187
[case testReplaceTypeVarBound]
21822188
from dataclasses import dataclass, replace
@@ -2201,6 +2207,8 @@ def f(t: TA) -> TA:
22012207
f(A(x=42))
22022208
f(B(x=42))
22032209

2210+
[builtins fixtures/tuple.pyi]
2211+
22042212
[case testReplaceAny]
22052213
from dataclasses import replace
22062214
from typing import Any
@@ -2209,17 +2217,30 @@ a: Any
22092217
a2 = replace(a)
22102218
reveal_type(a2) # N: Revealed type is "Any"
22112219

2220+
[builtins fixtures/tuple.pyi]
2221+
22122222
[case testReplaceNotDataclass]
22132223
from dataclasses import replace
22142224

2215-
replace(5) # E:Argument 1 to "replace" has incompatible type "int"; expected a dataclass
2225+
replace(5) # E:Value of type variable "_DataclassT" of "replace" cannot be "int"
22162226

22172227
class C:
22182228
pass
22192229

2220-
replace(C()) # E:Argument 1 to "replace" has incompatible type "C"; expected a dataclass
2230+
replace(C()) # E:Value of type variable "_DataclassT" of "replace" cannot be "C"
22212231

2222-
replace(None) # E: Argument 1 to "replace" has incompatible type "None"; expected a dataclass
2232+
replace(None) # E: Value of type variable "_DataclassT" of "replace" cannot be "None"
2233+
2234+
[builtins fixtures/tuple.pyi]
2235+
2236+
[case testReplaceIsDataclass]
2237+
from dataclasses import is_dataclass, replace
2238+
2239+
def f(x: object) -> None:
2240+
if is_dataclass(x) and not isinstance(x, type):
2241+
y = replace(x)
2242+
2243+
[builtins fixtures/tuple.pyi]
22232244

22242245
[case testReplaceGeneric]
22252246
from dataclasses import dataclass, replace, InitVar
@@ -2238,6 +2259,8 @@ reveal_type(a2) # N: Revealed type is "__main__.A[builtins.int]"
22382259
a2 = replace(a, x='42') # E: Argument "x" to "replace" of "A[int]" has incompatible type "str"; expected "int"
22392260
reveal_type(a2) # N: Revealed type is "__main__.A[builtins.int]"
22402261

2262+
[builtins fixtures/tuple.pyi]
2263+
22412264
[case testPostInitCorrectSignature]
22422265
from typing import Any, Generic, TypeVar, Callable, Self
22432266
from dataclasses import dataclass, InitVar
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
fromtypingimportProtocol,TypeVar,Iterable
1+
fromdataclassesimportField
2+
fromtypingimportAny,ClassVar,Protocol,TypeVar,Iterable
23

34
_KT=TypeVar("_KT")
45
_VT_co=TypeVar("_VT_co",covariant=True)
56

67
classSupportsKeysAndGetItem(Protocol[_KT,_VT_co]):
78
defkeys(self)->Iterable[_KT]:pass
89
def__getitem__(self,__key:_KT)->_VT_co:pass
10+
11+
classDataclassInstance(Protocol):
12+
__dataclass_fields__:ClassVar[dict[str,Field[Any]]]

‎test-data/unit/lib-stub/dataclasses.pyi‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
fromtypingimportAny,Callable,Generic,Mapping,Optional,TypeVar,overload,Type
1+
from_typeshedimportDataclassInstance
2+
fromtypingimportAny,Callable,Generic,Literal,Mapping,Optional,TypeVar,overload,Type
3+
fromtyping_extensionsimportTypeGuard
24

35
_T=TypeVar('_T')
6+
_DataclassT=TypeVar("_DataclassT",bound=DataclassInstance)
47

58
classInitVar(Generic[_T]):
69
...
@@ -33,4 +36,12 @@ def field(*,
3336

3437
classField(Generic[_T]):pass
3538

36-
defreplace(__obj:_T,**changes:Any)->_T: ...
39+
@overload
40+
defis_dataclass(obj:DataclassInstance)->Literal[True]: ...
41+
@overload
42+
defis_dataclass(obj:type)->TypeGuard[type[DataclassInstance]]: ...
43+
@overload
44+
defis_dataclass(obj:object)->TypeGuard[DataclassInstance|type[DataclassInstance]]: ...
45+
46+
47+
defreplace(__obj:_DataclassT,**changes:Any)->_DataclassT: ...

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp