| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -968,7 +968,21 @@ def from_funcitem(stub: nodes.FuncItem) -> Signature[nodes.Argument]: | |||
| 968 | 968 | elif stub_arg.kind == nodes.ARG_STAR: | |
| 969 | 969 | stub_sig.varpos = stub_arg | |
| 970 | 970 | elif stub_arg.kind == nodes.ARG_STAR2: | |
| 971 | - stub_sig.varkw = stub_arg | ||
| 971 | + if stub_arg.variable.type is not None and isinstance( | ||
| 972 | + (typed_dict_arg := mypy.types.get_proper_type(stub_arg.variable.type)), | ||
| 973 | + mypy.types.TypedDictType, | ||
| 974 | + ): | ||
| 975 | + for key_name, key_type in typed_dict_arg.items.items(): | ||
| 976 | + optional = key_name not in typed_dict_arg.required_keys | ||
| 977 | + stub_sig.kwonly[key_name] = nodes.Argument( | ||
| 978 | + nodes.Var(key_name, key_type), | ||
| 979 | + type_annotation=key_type, | ||
| 980 | + initializer=nodes.EllipsisExpr() if optional else None, | ||
| 981 | + kind=nodes.ARG_NAMED_OPT if optional else nodes.ARG_NAMED, | ||
| 982 | + pos_only=False, | ||
| 983 | + ) | ||
| 984 | + else: | ||
| 985 | + stub_sig.varkw = stub_arg | ||
| 972 | 986 | else: | |
| 973 | 987 | raise AssertionError | |
| 974 | 988 | return stub_sig | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -61,6 +61,7 @@ def __getitem__(self, typeargs: Any) -> object: ... | |||
| 61 | 61 | Literal = 0 | |
| 62 | 62 | NewType = 0 | |
| 63 | 63 | TypedDict = 0 | |
| 64 | + Unpack = 0 | ||
| 64 | 65 | ||
| 65 | 66 | class TypeVar: | |
| 66 | 67 | def __init__(self, name, covariant: bool = ..., contravariant: bool = ...) -> None: ... | |
@@ -766,6 +767,43 @@ def test_varargs_varkwargs(self) -> Iterator[Case]: | |||
| 766 | 767 | error="k6", | |
| 767 | 768 | ) | |
| 768 | 769 | ||
| 770 | + @collect_cases | ||
| 771 | + def test_kwargs_unpack_typeddict(self) -> Iterator[Case]: | ||
| 772 | + yield Case( | ||
| 773 | + stub=""" | ||
| 774 | + from typing import TypedDict, Unpack, type_check_only | ||
| 775 | + | ||
| 776 | + @type_check_only | ||
| 777 | + class _Args(TypedDict): | ||
| 778 | + a: int | ||
| 779 | + b: int | ||
| 780 | + | ||
| 781 | + def f1(**kwargs: Unpack[_Args]) -> None: ... | ||
| 782 | + """, | ||
| 783 | + runtime="def f1(*, a, b): pass", | ||
| 784 | + error=None, | ||
| 785 | + ) | ||
| 786 | + yield Case( | ||
| 787 | + stub="def f2(**kwargs: Unpack[_Args]) -> None: ...", | ||
| 788 | + runtime="def f2(*, a, c): pass", | ||
| 789 | + error="f2", | ||
| 790 | + ) | ||
| 791 | + yield Case( | ||
| 792 | + stub=""" | ||
| 793 | + @type_check_only | ||
| 794 | + class _OptionalArgs(TypedDict, total=False): | ||
| 795 | + a: int | ||
| 796 | + | ||
| 797 | + def f3(**kwargs: Unpack[_OptionalArgs]) -> None: ... | ||
| 798 | + def f4(**kwargs: Unpack[_OptionalArgs]) -> None: ... | ||
| 799 | + """, | ||
| 800 | + runtime=""" | ||
| 801 | + def f3(*, a): pass | ||
| 802 | + def f4(*, a=0): pass | ||
| 803 | + """, | ||
| 804 | + error="f3", | ||
| 805 | + ) | ||
| 806 | + | ||
| 769 | 807 | @collect_cases | |
| 770 | 808 | def test_overload(self) -> Iterator[Case]: | |
| 771 | 809 | yield Case( | |
| Back | FazBrowse Home | New Git URL |
0 commit comments