Skip to content

Commit 9f4ae13

Browse files
authored
[3.12] gh-117613: Argument Clinic: ensure that defining class params are positional-only (#117939)
1 parent a72c4a9 commit 9f4ae13

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

Lib/test/test_clinic.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,6 +1347,28 @@ def test_unused_param(self):
13471347
parser_decl = p.simple_declaration(in_parser=True)
13481348
self.assertNotIn("Py_UNUSED", parser_decl)
13491349

1350+
def test_kind_defining_class(self):
1351+
function = self.parse_function("""
1352+
module m
1353+
class m.C "PyObject *" ""
1354+
m.C.meth
1355+
cls: defining_class
1356+
""", signatures_in_block=3, function_index=2)
1357+
p = function.parameters['cls']
1358+
self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
1359+
1360+
def test_disallow_defining_class_at_module_level(self):
1361+
expected_error_msg = (
1362+
"Error on line 0:\n"
1363+
"A 'defining_class' parameter cannot be defined at module level.\n"
1364+
)
1365+
out = self.parse_function_should_fail("""
1366+
module m
1367+
m.func
1368+
cls: defining_class
1369+
""")
1370+
self.assertEqual(out, expected_error_msg)
1371+
13501372
def parse(self, text):
13511373
c = FakeClinic()
13521374
parser = DSLParser(c)

Tools/clinic/clinic.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4997,6 +4997,9 @@ def bad_node(self, node):
49974997
fail("A 'defining_class' parameter cannot have a default value.")
49984998
if self.group:
49994999
fail("A 'defining_class' parameter cannot be in an optional group.")
5000+
if self.function.cls is None:
5001+
fail("A 'defining_class' parameter cannot be defined at module level.")
5002+
kind = inspect.Parameter.POSITIONAL_ONLY
50005003
else:
50015004
fail("A 'defining_class' parameter, if specified, must either be the first thing in the parameter block, or come just after 'self'.")
50025005

@@ -5074,7 +5077,10 @@ def parse_special_symbol(self, symbol):
50745077
for p in self.function.parameters.values():
50755078
if p.is_vararg():
50765079
continue
5077-
if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
5080+
if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and
5081+
not isinstance(p.converter, self_converter) and
5082+
not isinstance(p.converter, defining_class_converter)
5083+
):
50785084
fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
50795085
p.kind = inspect.Parameter.POSITIONAL_ONLY
50805086

0 commit comments

Comments
 (0)