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

Commiteb144ce

Browse files
authored
Allow literals as kwargs dict keys (#20416)
Fixes#10023 ,fixes#13674 ,closes#10237
1 parente089abc commiteb144ce

File tree

4 files changed

+25
-7
lines changed

4 files changed

+25
-7
lines changed

‎mypy/checkexpr.py‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6142,8 +6142,17 @@ def is_valid_var_arg(self, typ: Type) -> bool:
61426142

61436143
defis_valid_keyword_var_arg(self,typ:Type)->bool:
61446144
"""Is a type valid as a **kwargs argument?"""
6145+
typ=get_proper_type(typ)
61456146
return (
6146-
is_subtype(
6147+
(
6148+
# This is a little ad hoc, ideally we would have a map_instance_to_supertype
6149+
# that worked for protocols
6150+
isinstance(typ,Instance)
6151+
andtyp.type.fullname=="builtins.dict"
6152+
andis_subtype(typ.args[0],self.named_type("builtins.str"))
6153+
)
6154+
orisinstance(typ,ParamSpecType)
6155+
oris_subtype(
61476156
typ,
61486157
self.chk.named_generic_type(
61496158
"_typeshed.SupportsKeysAndGetItem",
@@ -6156,7 +6165,6 @@ def is_valid_keyword_var_arg(self, typ: Type) -> bool:
61566165
"_typeshed.SupportsKeysAndGetItem", [UninhabitedType(),UninhabitedType()]
61576166
),
61586167
)
6159-
orisinstance(typ,ParamSpecType)
61606168
)
61616169

61626170
defnot_ready_callback(self,name:str,context:Context)->None:

‎mypy/messages.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1401,7 +1401,7 @@ def invalid_var_arg(self, typ: Type, context: Context) -> None:
14011401
definvalid_keyword_var_arg(self,typ:Type,is_mapping:bool,context:Context)->None:
14021402
typ=get_proper_type(typ)
14031403
ifisinstance(typ,Instance)andis_mapping:
1404-
self.fail("Keywordsmustbe strings",context)
1404+
self.fail("Argument after **musthave string keys",context,code=codes.ARG_TYPE)
14051405
else:
14061406
self.fail(
14071407
f"Argument after ** must be a mapping, not{format_type(typ,self.options)}",

‎test-data/unit/check-generic-subtyping.test‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1014,7 +1014,7 @@ func_with_kwargs(**x1)
10141014
[out]
10151015
main:12: note: Revealed type is "typing.Iterator[builtins.int]"
10161016
main:13: note: Revealed type is "builtins.dict[builtins.int, builtins.str]"
1017-
main:14: error:Keywordsmustbe strings
1017+
main:14: error:Argument after **musthave string keys
10181018
main:14: error: Argument 1 to "func_with_kwargs" has incompatible type "**X1[str, int]"; expected "int"
10191019
[builtins fixtures/dict.pyi]
10201020
[typing fixtures/typing-medium.pyi]

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ def f(**kwargs: 'A') -> None: pass
334334
b: Mapping
335335
d: Mapping[A, A]
336336
m: Mapping[str, A]
337-
f(**d) # E:Keywordsmustbe strings
337+
f(**d) # E:Argument after **musthave string keys
338338
f(**m)
339339
f(**b)
340340
class A: pass
@@ -354,7 +354,7 @@ from typing import Dict, Any, Optional
354354
class A: pass
355355
def f(**kwargs: 'A') -> None: pass
356356
d = {} # type: Dict[A, A]
357-
f(**d) # E:Keywordsmustbe strings
357+
f(**d) # E:Argument after **musthave string keys
358358
f(**A()) # E: Argument after ** must be a mapping, not "A"
359359
kwargs: Optional[Any]
360360
f(**kwargs) # E: Argument after ** must be a mapping, not "Any | None"
@@ -452,7 +452,7 @@ f(b) # E: Argument 1 to "f" has incompatible type "dict[str, str]"; expected "in
452452
f(**b) # E: Argument 1 to "f" has incompatible type "**dict[str, str]"; expected "int"
453453

454454
c = {0: 0}
455-
f(**c) # E:Keywordsmustbe strings
455+
f(**c) # E:Argument after **musthave string keys
456456
[builtins fixtures/dict.pyi]
457457

458458
[case testCallStar2WithStar]
@@ -570,3 +570,13 @@ main:38: error: Argument after ** must be a mapping, not "C[str, float]"
570570
main:39: error: Argument after ** must be a mapping, not "D"
571571
main:41: error: Argument 1 to "foo" has incompatible type "**dict[str, str]"; expected "float"
572572
[builtins fixtures/dict.pyi]
573+
574+
[case testLiteralKwargs]
575+
from typing import Any, Literal
576+
kw: dict[Literal["a", "b"], Any]
577+
def func(a, b): ...
578+
func(**kw)
579+
580+
badkw: dict[Literal["one", 1], Any]
581+
func(**badkw) # E: Argument after ** must have string keys
582+
[builtins fixtures/dict.pyi]

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp