-
Notifications
You must be signed in to change notification settings - Fork 304
Update unpack TypedDict kwargs forwarding spec + add conformance tests #2338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,29 +1,39 @@ | ||
| conformant = "Partial" | ||
| notes = """ | ||
| Allows callable without kwargs to be assigned to callable with unpacked kwargs. | ||
| Does not support the `closed` and `extra_items` TypedDict class arguments. | ||
| Does not reject passing unpacked kwargs typed with a non-closed TypedDict to a callable that has no `**kwargs`. | ||
| Does not reject passing unpacked kwargs typed with a TypedDict that has `extra_items` to a callable that has no `**kwargs`. | ||
| Does not check the `extra_items` type of unpacked kwargs against the target callable's `**kwargs` annotation. | ||
| """ | ||
| output = """ | ||
| callables_kwargs.py:46: error: Missing named argument "v1" for "func1" [call-arg] | ||
| callables_kwargs.py:46: error: Missing named argument "v3" for "func1" [call-arg] | ||
| callables_kwargs.py:51: error: Unexpected keyword argument "v4" for "func1" [call-arg] | ||
| callables_kwargs.py:52: error: Too many positional arguments for "func1" [misc] | ||
| callables_kwargs.py:58: error: Argument 1 to "func1" has incompatible type "**dict[str, str]"; expected "int" [arg-type] | ||
| callables_kwargs.py:61: error: Argument 1 to "func1" has incompatible type "**dict[str, object]"; expected "int" [arg-type] | ||
| callables_kwargs.py:61: error: Argument 1 to "func1" has incompatible type "**dict[str, object]"; expected "str" [arg-type] | ||
| callables_kwargs.py:63: error: "func1" gets multiple values for keyword argument "v1" [misc] | ||
| callables_kwargs.py:64: error: "func2" gets multiple values for keyword argument "v3" [misc] | ||
| callables_kwargs.py:64: error: Argument 1 to "func2" has incompatible type "int"; expected "str" [arg-type] | ||
| callables_kwargs.py:65: error: "func2" gets multiple values for keyword argument "v1" [misc] | ||
| callables_kwargs.py:101: error: Incompatible types in assignment (expression has type "def func1(**kwargs: **TD2) -> None", variable has type "TDProtocol3") [assignment] | ||
| callables_kwargs.py:101: note: "TDProtocol3.__call__" has type "def __call__(self, *, v1: int, v2: int, v3: str) -> None" | ||
| callables_kwargs.py:102: error: Incompatible types in assignment (expression has type "def func1(**kwargs: **TD2) -> None", variable has type "TDProtocol4") [assignment] | ||
| callables_kwargs.py:102: note: "TDProtocol4.__call__" has type "def __call__(self, *, v1: int) -> None" | ||
| callables_kwargs.py:103: error: Incompatible types in assignment (expression has type "def func1(**kwargs: **TD2) -> None", variable has type "TDProtocol5") [assignment] | ||
| callables_kwargs.py:103: note: "TDProtocol5.__call__" has type "def __call__(self, v1: int, v3: str) -> None" | ||
| callables_kwargs.py:111: error: Overlap between parameter names and ** TypedDict items: "v1" [misc] | ||
| callables_kwargs.py:122: error: Unpack item in ** parameter must be a TypedDict [misc] | ||
| callables_kwargs.py:47: error: Missing named argument "v1" for "func1" [call-arg] | ||
| callables_kwargs.py:47: error: Missing named argument "v3" for "func1" [call-arg] | ||
| callables_kwargs.py:52: error: Unexpected keyword argument "v4" for "func1" [call-arg] | ||
| callables_kwargs.py:53: error: Too many positional arguments for "func1" [misc] | ||
| callables_kwargs.py:59: error: Argument 1 to "func1" has incompatible type "**dict[str, str]"; expected "int" [arg-type] | ||
| callables_kwargs.py:62: error: Argument 1 to "func1" has incompatible type "**dict[str, object]"; expected "int" [arg-type] | ||
| callables_kwargs.py:62: error: Argument 1 to "func1" has incompatible type "**dict[str, object]"; expected "str" [arg-type] | ||
| callables_kwargs.py:64: error: "func1" gets multiple values for keyword argument "v1" [misc] | ||
| callables_kwargs.py:65: error: "func2" gets multiple values for keyword argument "v3" [misc] | ||
| callables_kwargs.py:65: error: Argument 1 to "func2" has incompatible type "int"; expected "str" [arg-type] | ||
| callables_kwargs.py:66: error: "func2" gets multiple values for keyword argument "v1" [misc] | ||
| callables_kwargs.py:102: error: Incompatible types in assignment (expression has type "def func1(**kwargs: **TD2) -> None", variable has type "TDProtocol3") [assignment] | ||
| callables_kwargs.py:102: note: "TDProtocol3.__call__" has type "def __call__(self, *, v1: int, v2: int, v3: str) -> None" | ||
| callables_kwargs.py:103: error: Incompatible types in assignment (expression has type "def func1(**kwargs: **TD2) -> None", variable has type "TDProtocol4") [assignment] | ||
| callables_kwargs.py:103: note: "TDProtocol4.__call__" has type "def __call__(self, *, v1: int) -> None" | ||
| callables_kwargs.py:104: error: Incompatible types in assignment (expression has type "def func1(**kwargs: **TD2) -> None", variable has type "TDProtocol5") [assignment] | ||
| callables_kwargs.py:104: note: "TDProtocol5.__call__" has type "def __call__(self, v1: int, v3: str) -> None" | ||
| callables_kwargs.py:112: error: Overlap between parameter names and ** TypedDict items: "v1" [misc] | ||
| callables_kwargs.py:123: error: Unpack item in ** parameter must be a TypedDict [misc] | ||
| callables_kwargs.py:145: error: Unexpected keyword argument "closed" for "__init_subclass__" of "TypedDict" [call-arg] | ||
| callables_kwargs.py:149: error: Unexpected keyword argument "extra_items" for "__init_subclass__" of "TypedDict" [call-arg] | ||
| """ | ||
| conformance_automated = "Fail" | ||
| errors_diff = """ | ||
| Line 134: Expected 1 errors | ||
| Line 135: Expected 1 errors | ||
| Line 184: Expected 1 errors | ||
| Line 185: Expected 1 errors | ||
| Line 145: Unexpected errors ['callables_kwargs.py:145: error: Unexpected keyword argument "closed" for "__init_subclass__" of "TypedDict" [call-arg]'] | ||
| Line 149: Unexpected errors ['callables_kwargs.py:149: error: Unexpected keyword argument "extra_items" for "__init_subclass__" of "TypedDict" [call-arg]'] | ||
| """ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,27 @@ | ||
| conformance_automated = "Pass" | ||
| conformant = "Partial" | ||
| notes = """ | ||
| Does not reject passing unpacked kwargs typed with a non-closed TypedDict to a callable that has no `**kwargs`. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove |
||
| Does not reject passing unpacked kwargs typed with a TypedDict that has `extra_items` to a callable that has no `**kwargs`. | ||
| Does not check the `extra_items` type of unpacked kwargs against the target callable's `**kwargs` annotation. | ||
| """ | ||
| conformance_automated = "Fail" | ||
| errors_diff = """ | ||
| Line 184: Expected 1 errors | ||
| Line 185: Expected 1 errors | ||
| """ | ||
| output = """ | ||
| ./callables_kwargs.py:46:4: In call to callables_kwargs.func1: Missing required argument 'v1' [incompatible_call] | ||
| ./callables_kwargs.py:51:4: In call to callables_kwargs.func1: Got an unexpected keyword argument 'v4' [incompatible_call] | ||
| ./callables_kwargs.py:52:4: In call to callables_kwargs.func1: Missing required argument 'v1' [incompatible_call] | ||
| ./callables_kwargs.py:58:4: Incompatible argument type for v1: expected int but got str [incompatible_argument] | ||
| ./callables_kwargs.py:61:4: In call to callables_kwargs.func1: Got an unexpected keyword argument 'v4' [incompatible_call] | ||
| ./callables_kwargs.py:63:4: Multiple values provided for argument 'v1' [incompatible_call] | ||
| ./callables_kwargs.py:64:4: In call to callables_kwargs.func2: Parameter 'v3' provided as both a positional and a keyword argument [incompatible_call] | ||
| ./callables_kwargs.py:65:4: Multiple values provided for argument 'v1' [incompatible_call] | ||
| ./callables_kwargs.py:101:0: Incompatible assignment: expected callables_kwargs.TDProtocol3, got function 'callables_kwargs.func1' [incompatible_assignment] | ||
| ./callables_kwargs.py:102:0: Incompatible assignment: expected callables_kwargs.TDProtocol4, got function 'callables_kwargs.func1' [incompatible_assignment] | ||
| ./callables_kwargs.py:103:0: Incompatible assignment: expected callables_kwargs.TDProtocol5, got function 'callables_kwargs.func1' [incompatible_assignment] | ||
| ./callables_kwargs.py:111:21: Parameter v1 overlaps with TypedDict key in **kwargs [invalid_annotation] | ||
| ./callables_kwargs.py:122:12: Expected TypedDict type inside Unpack[] for **kwargs [invalid_annotation] | ||
| ./callables_kwargs.py:134:0: Incompatible assignment: expected callables_kwargs.TDProtocol6, got function 'callables_kwargs.func7' [incompatible_assignment] | ||
| ./callables_kwargs.py:47:4: In call to callables_kwargs.func1: Missing required argument 'v1' [incompatible_call] | ||
| ./callables_kwargs.py:52:4: In call to callables_kwargs.func1: Got an unexpected keyword argument 'v4' [incompatible_call] | ||
| ./callables_kwargs.py:53:4: In call to callables_kwargs.func1: Missing required argument 'v1' [incompatible_call] | ||
| ./callables_kwargs.py:59:4: Incompatible argument type for v1: expected int but got str [incompatible_argument] | ||
| ./callables_kwargs.py:62:4: In call to callables_kwargs.func1: Got an unexpected keyword argument 'v4' [incompatible_call] | ||
| ./callables_kwargs.py:64:4: Multiple values provided for argument 'v1' [incompatible_call] | ||
| ./callables_kwargs.py:65:4: In call to callables_kwargs.func2: Parameter 'v3' provided as both a positional and a keyword argument [incompatible_call] | ||
| ./callables_kwargs.py:66:4: Multiple values provided for argument 'v1' [incompatible_call] | ||
| ./callables_kwargs.py:102:0: Incompatible assignment: expected callables_kwargs.TDProtocol3, got function 'callables_kwargs.func1' [incompatible_assignment] | ||
| ./callables_kwargs.py:103:0: Incompatible assignment: expected callables_kwargs.TDProtocol4, got function 'callables_kwargs.func1' [incompatible_assignment] | ||
| ./callables_kwargs.py:104:0: Incompatible assignment: expected callables_kwargs.TDProtocol5, got function 'callables_kwargs.func1' [incompatible_assignment] | ||
| ./callables_kwargs.py:112:21: Parameter v1 overlaps with TypedDict key in **kwargs [invalid_annotation] | ||
| ./callables_kwargs.py:123:12: Expected TypedDict type inside Unpack[] for **kwargs [invalid_annotation] | ||
| ./callables_kwargs.py:135:0: Incompatible assignment: expected callables_kwargs.TDProtocol6, got function 'callables_kwargs.func7' [incompatible_assignment] | ||
| """ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,30 @@ | ||
| conformant = "Pass" | ||
| conformance_automated = "Pass" | ||
| conformant = "Partial" | ||
| notes = """ | ||
| Does not reject passing unpacked kwargs typed with a non-closed TypedDict to a callable that has no `**kwargs`. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove |
||
| Does not reject passing unpacked kwargs typed with a TypedDict that has `extra_items` to a callable that has no `**kwargs`. | ||
| Does not check the `extra_items` type of unpacked kwargs against the target callable's `**kwargs` annotation. | ||
| """ | ||
| conformance_automated = "Fail" | ||
| errors_diff = """ | ||
| Line 184: Expected 1 errors | ||
| Line 185: Expected 1 errors | ||
| """ | ||
| output = """ | ||
| ERROR callables_kwargs.py:46:10-12: Missing argument `v1` in function `func1` [missing-argument] | ||
| ERROR callables_kwargs.py:46:10-12: Missing argument `v3` in function `func1` [missing-argument] | ||
| ERROR callables_kwargs.py:51:32-34: Unexpected keyword argument `v4` in function `func1` [unexpected-keyword] | ||
| ERROR callables_kwargs.py:52:11-12: Expected argument `v1` to be passed by name in function `func1` [unexpected-positional-argument] | ||
| ERROR callables_kwargs.py:52:11-12: Expected 0 positional arguments, got 3 in function `func1` [bad-argument-count] | ||
| ERROR callables_kwargs.py:52:14-16: Expected argument `v3` to be passed by name in function `func1` [unexpected-positional-argument] | ||
| ERROR callables_kwargs.py:58:11-20: Unpacked keyword argument `str` is not assignable to parameter `v1` with type `int` in function `func1` [bad-argument-type] | ||
| ERROR callables_kwargs.py:63:17-22: Multiple values for argument `v1` in function `func1` [bad-keyword-argument] | ||
| ERROR callables_kwargs.py:64:11-12: Argument `Literal[1]` is not assignable to parameter `v3` with type `str` in function `func2` [bad-argument-type] | ||
| ERROR callables_kwargs.py:64:14-19: Multiple values for argument `v3` in function `func2` [bad-keyword-argument] | ||
| ERROR callables_kwargs.py:65:17-22: Multiple values for argument `v1` in function `func2` [bad-keyword-argument] | ||
| ERROR callables_kwargs.py:101:19-24: `(**kwargs: Unpack[TD2]) -> None` is not assignable to `TDProtocol3` [bad-assignment] | ||
| ERROR callables_kwargs.py:102:19-24: `(**kwargs: Unpack[TD2]) -> None` is not assignable to `TDProtocol4` [bad-assignment] | ||
| ERROR callables_kwargs.py:103:19-24: `(**kwargs: Unpack[TD2]) -> None` is not assignable to `TDProtocol5` [bad-assignment] | ||
| ERROR callables_kwargs.py:111:20-41: TypedDict key 'v1' in **kwargs overlaps with parameter 'v1' [bad-function-definition] | ||
| ERROR callables_kwargs.py:122:21-30: `Unpack` in **kwargs annotation must be used only with a `TypedDict` [invalid-annotation] | ||
| ERROR callables_kwargs.py:134:19-24: `(*, v1: int, v3: str, v2: str = '') -> None` is not assignable to `TDProtocol6` [bad-assignment] | ||
| ERROR callables_kwargs.py:47:10-12: Missing argument `v1` in function `func1` [missing-argument] | ||
| ERROR callables_kwargs.py:47:10-12: Missing argument `v3` in function `func1` [missing-argument] | ||
| ERROR callables_kwargs.py:52:32-34: Unexpected keyword argument `v4` in function `func1` [unexpected-keyword] | ||
| ERROR callables_kwargs.py:53:11-12: Expected argument `v1` to be passed by name in function `func1` [unexpected-positional-argument] | ||
| ERROR callables_kwargs.py:53:11-12: Expected 0 positional arguments, got 3 in function `func1` [bad-argument-count] | ||
| ERROR callables_kwargs.py:53:14-16: Expected argument `v3` to be passed by name in function `func1` [unexpected-positional-argument] | ||
| ERROR callables_kwargs.py:59:11-20: Unpacked keyword argument `str` is not assignable to parameter `v1` with type `int` in function `func1` [bad-argument-type] | ||
| ERROR callables_kwargs.py:64:17-22: Multiple values for argument `v1` in function `func1` [bad-keyword-argument] | ||
| ERROR callables_kwargs.py:65:11-12: Argument `Literal[1]` is not assignable to parameter `v3` with type `str` in function `func2` [bad-argument-type] | ||
| ERROR callables_kwargs.py:65:14-19: Multiple values for argument `v3` in function `func2` [bad-keyword-argument] | ||
| ERROR callables_kwargs.py:66:17-22: Multiple values for argument `v1` in function `func2` [bad-keyword-argument] | ||
| ERROR callables_kwargs.py:102:19-24: `(**kwargs: Unpack[TD2]) -> None` is not assignable to `TDProtocol3` [bad-assignment] | ||
| ERROR callables_kwargs.py:103:19-24: `(**kwargs: Unpack[TD2]) -> None` is not assignable to `TDProtocol4` [bad-assignment] | ||
| ERROR callables_kwargs.py:104:19-24: `(**kwargs: Unpack[TD2]) -> None` is not assignable to `TDProtocol5` [bad-assignment] | ||
| ERROR callables_kwargs.py:112:20-41: TypedDict key 'v1' in **kwargs overlaps with parameter 'v1' [bad-function-definition] | ||
| ERROR callables_kwargs.py:123:21-30: `Unpack` in **kwargs annotation must be used only with a `TypedDict` [invalid-annotation] | ||
| ERROR callables_kwargs.py:135:19-24: `(*, v1: int, v3: str, v2: str = '') -> None` is not assignable to `TDProtocol6` [bad-assignment] | ||
| """ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,36 +1,43 @@ | ||
| conformant = "Pass" | ||
| conformant = "Partial" | ||
| notes = """ | ||
| Does not reject passing unpacked kwargs typed with a non-closed TypedDict to a callable that has no `**kwargs`. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we remove this note here and from the other checker results? The updated spec explicitly allows an open TypedDict to be forwarded without an error, and the corresponding test is marked |
||
| Does not reject passing unpacked kwargs typed with a TypedDict that has `extra_items` to a callable that has no `**kwargs`. | ||
| """ | ||
| output = """ | ||
| callables_kwargs.py:28:5 - error: Could not access item in TypedDict | ||
| callables_kwargs.py:29:5 - error: Could not access item in TypedDict | ||
| "v2" is not a required key in "TD2", so access may result in runtime exception (reportTypedDictNotRequiredAccess) | ||
| callables_kwargs.py:46:5 - error: Arguments missing for parameters "v1", "v3" (reportCallIssue) | ||
| callables_kwargs.py:51:32 - error: No parameter named "v4" (reportCallIssue) | ||
| callables_kwargs.py:52:11 - error: Expected 0 positional arguments (reportCallIssue) | ||
| callables_kwargs.py:58:13 - error: Argument of type "str" cannot be assigned to parameter "v1" of type "int" in function "func1" | ||
| callables_kwargs.py:47:5 - error: Arguments missing for parameters "v1", "v3" (reportCallIssue) | ||
| callables_kwargs.py:52:32 - error: No parameter named "v4" (reportCallIssue) | ||
| callables_kwargs.py:53:11 - error: Expected 0 positional arguments (reportCallIssue) | ||
| callables_kwargs.py:59:13 - error: Argument of type "str" cannot be assigned to parameter "v1" of type "int" in function "func1" | ||
| "str" is not assignable to "int" (reportArgumentType) | ||
| callables_kwargs.py:63:19 - error: Unable to match unpacked TypedDict argument to parameters | ||
| callables_kwargs.py:64:19 - error: Unable to match unpacked TypedDict argument to parameters | ||
| Parameter "v1" is already assigned (reportCallIssue) | ||
| callables_kwargs.py:64:16 - error: Unable to match unpacked TypedDict argument to parameters | ||
| callables_kwargs.py:65:16 - error: Unable to match unpacked TypedDict argument to parameters | ||
| Parameter "v3" is already assigned (reportCallIssue) | ||
| callables_kwargs.py:65:19 - error: Unable to match unpacked TypedDict argument to parameters | ||
| callables_kwargs.py:66:19 - error: Unable to match unpacked TypedDict argument to parameters | ||
| Parameter "v1" is already assigned (reportCallIssue) | ||
| callables_kwargs.py:101:19 - error: Type "(**kwargs: **TD2) -> None" is not assignable to declared type "TDProtocol3" | ||
| callables_kwargs.py:102:19 - error: Type "(**kwargs: **TD2) -> None" is not assignable to declared type "TDProtocol3" | ||
| Type "(**kwargs: **TD2) -> None" is not assignable to type "(*, v1: int, v2: int, v3: str) -> None" | ||
| Keyword parameter "v2" of type "int" is incompatible with type "str" | ||
| "int" is not assignable to "str" (reportAssignmentType) | ||
| callables_kwargs.py:102:19 - error: Type "(**kwargs: **TD2) -> None" is not assignable to declared type "TDProtocol4" | ||
| callables_kwargs.py:103:19 - error: Type "(**kwargs: **TD2) -> None" is not assignable to declared type "TDProtocol4" | ||
| Type "(**kwargs: **TD2) -> None" is not assignable to type "(*, v1: int) -> None" | ||
| Extra parameter "v3" (reportAssignmentType) | ||
| callables_kwargs.py:103:19 - error: Type "(**kwargs: **TD2) -> None" is not assignable to declared type "TDProtocol5" | ||
| callables_kwargs.py:104:19 - error: Type "(**kwargs: **TD2) -> None" is not assignable to declared type "TDProtocol5" | ||
| Type "(**kwargs: **TD2) -> None" is not assignable to type "(v1: int, v3: str) -> None" | ||
| Function accepts too many positional parameters; expected 0 but received 2 | ||
| Extra parameter "v1" | ||
| Extra parameter "v3" (reportAssignmentType) | ||
| callables_kwargs.py:111:30 - error: Typed dictionary overlaps with keyword parameter: v1 (reportGeneralTypeIssues) | ||
| callables_kwargs.py:122:21 - error: Expected TypedDict type argument for Unpack (reportGeneralTypeIssues) | ||
| callables_kwargs.py:134:19 - error: Type "(*, v1: int, v3: str, v2: str = "") -> None" is not assignable to declared type "TDProtocol6" | ||
| callables_kwargs.py:112:30 - error: Typed dictionary overlaps with keyword parameter: v1 (reportGeneralTypeIssues) | ||
| callables_kwargs.py:123:21 - error: Expected TypedDict type argument for Unpack (reportGeneralTypeIssues) | ||
| callables_kwargs.py:135:19 - error: Type "(*, v1: int, v3: str, v2: str = "") -> None" is not assignable to declared type "TDProtocol6" | ||
| Type "(*, v1: int, v3: str, v2: str = "") -> None" is not assignable to type "(**kwargs: **TD2) -> None" | ||
| Parameter "**kwargs" has no corresponding parameter (reportAssignmentType) | ||
| callables_kwargs.py:185:29 - error: Argument of type "int" cannot be assigned to parameter "kwargs" of type "str" in function "takes_name_str_kwargs" | ||
| "int" is not assignable to "str" (reportArgumentType) | ||
| """ | ||
| conformance_automated = "Pass" | ||
| conformance_automated = "Fail" | ||
| errors_diff = """ | ||
| Line 184: Expected 1 errors | ||
| """ | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this note? Accepting an open TypedDict here is explicitly permitted by the updated spec, and the corresponding test is marked
E?. The separateextra_itemsnote is the actual conformance issue.