[Python-checkins] [3.12] gh-106359: Fix corner case bugs in Argument Clinic converter parser (GH-106361) (#106364)
AlexWaygood
webhook-mailer at python.org
Mon Jul 3 09:42:24 EDT 2023
https://github.com/python/cpython/commit/5f20152f01febf4ffd9572a8ab3e980a4660ef69
commit: 5f20152f01febf4ffd9572a8ab3e980a4660ef69
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: AlexWaygood <Alex.Waygood at Gmail.com>
date: 2023-07-03T13:42:20Z
summary:
[3.12] gh-106359: Fix corner case bugs in Argument Clinic converter parser (GH-106361) (#106364)
gh-106359: Fix corner case bugs in Argument Clinic converter parser (GH-106361)
DSLParser.parse_converter() could return unusable kwdicts in some rare cases
(cherry picked from commit 0da4c883cf4185efe27b711c3e0a1e6e94397610)
Co-authored-by: Erlend E. Aasland <erlend at python.org>
Co-authored-by: Alex Waygood <Alex.Waygood at Gmail.com>
files:
A Misc/NEWS.d/next/Tools-Demos/2023-07-03-14-06-19.gh-issue-106359.RfJuR0.rst
M Lib/test/test_clinic.py
M Tools/clinic/clinic.py
diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py
index bea7303805567..76a06df5fe2e5 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 0000000000000..600c265391ec5
--- /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 d182e5e7764e4..d67479c7f8ab8 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -4289,6 +4289,7 @@ def dedent(self, line):
StateKeeper = Callable[[str | None], None]
+ConverterArgs = dict[str, Any]
class DSLParser:
def __init__(self, clinic: Clinic) -> None:
@@ -5016,10 +5017,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, {}
@@ -5027,10 +5028,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(
More information about the Python-checkins
mailing list