diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index a6ce9c2570cb62..fab2d2bb0bdbe4 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -813,6 +813,22 @@ def test_other_bizarre_things_in_annotations_fail(self): ) self.assertEqual(s, expected_failure_message) + def test_kwarg_splats_disallowed_in_function_call_annotations(self): + expected_error_msg = ( + "Error on line 0:\n" + "Cannot use a kwarg splat in a function-call annotation\n" + ) + dataset = ( + 'module fo\nfo.barbaz\n o: bool(**{None: "bang!"})', + 'module fo\nfo.barbaz -> bool(**{None: "bang!"})', + 'module fo\nfo.barbaz -> bool(**{"bang": 42})', + 'module fo\nfo.barbaz\n o: bool(**{"bang": None})', + ) + for fn in dataset: + with self.subTest(fn=fn): + out = self.parse_function_should_fail(fn) + self.assertEqual(out, expected_error_msg) + def test_unused_param(self): block = self.parse(""" module foo diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-07-03-14-06-19.gh-issue-106359.RfJuR0.rst b/Misc/NEWS.d/next/Tools-Demos/2023-07-03-14-06-19.gh-issue-106359.RfJuR0.rst new file mode 100644 index 00000000000000..600c265391ec5b --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2023-07-03-14-06-19.gh-issue-106359.RfJuR0.rst @@ -0,0 +1,2 @@ +Argument Clinic now explicitly forbids "kwarg splats" in function calls used as +annotations. diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 2e46131d4e336a..47038f98aabd75 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -4291,6 +4291,7 @@ def dedent(self, line): StateKeeper = Callable[[str | None], None] +ConverterArgs = dict[str, Any] class DSLParser: function: Function | None @@ -5033,10 +5034,10 @@ def bad_node(self, node): key = f"{parameter_name}_as_{c_name}" if c_name else parameter_name self.function.parameters[key] = p - KwargDict = dict[str | None, Any] - @staticmethod - def parse_converter(annotation: ast.expr | None) -> tuple[str, bool, KwargDict]: + def parse_converter( + annotation: ast.expr | None + ) -> tuple[str, bool, ConverterArgs]: match annotation: case ast.Constant(value=str() as value): return value, True, {} @@ -5044,10 +5045,11 @@ def parse_converter(annotation: ast.expr | None) -> tuple[str, bool, KwargDict]: return name, False, {} case ast.Call(func=ast.Name(name)): symbols = globals() - kwargs = { - node.arg: eval_ast_expr(node.value, symbols) - for node in annotation.keywords - } + kwargs: ConverterArgs = {} + for node in annotation.keywords: + if not isinstance(node.arg, str): + fail("Cannot use a kwarg splat in a function-call annotation") + kwargs[node.arg] = eval_ast_expr(node.value, symbols) return name, False, kwargs case _: fail( pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy