Skip to content

Commit 420d705

Browse files
committed
Fix test failures, refactor to dedup
1 parent 446bce5 commit 420d705

2 files changed

Lines changed: 49 additions & 57 deletions

File tree

Lib/test/test_clinic.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2720,7 +2720,7 @@ class Foo "FooObject *" "Foo_Type"
27202720
func = self.parse_function(block, signatures_in_block=3,
27212721
function_index=2)
27222722
self.assertTrue(func.vectorcall)
2723-
self.assertFalse(func.vectorcall_exact_only)
2723+
self.assertFalse(func.vectorcall.exact_only)
27242724

27252725
def test_vectorcall_on_new(self):
27262726
block = """
@@ -2735,7 +2735,7 @@ class Foo "FooObject *" "Foo_Type"
27352735
func = self.parse_function(block, signatures_in_block=3,
27362736
function_index=2)
27372737
self.assertTrue(func.vectorcall)
2738-
self.assertFalse(func.vectorcall_exact_only)
2738+
self.assertFalse(func.vectorcall.exact_only)
27392739

27402740
def test_vectorcall_exact_only(self):
27412741
block = """
@@ -2749,7 +2749,7 @@ class Foo "FooObject *" "Foo_Type"
27492749
func = self.parse_function(block, signatures_in_block=3,
27502750
function_index=2)
27512751
self.assertTrue(func.vectorcall)
2752-
self.assertTrue(func.vectorcall_exact_only)
2752+
self.assertTrue(func.vectorcall.exact_only)
27532753

27542754
def test_vectorcall_invalid_kwarg(self):
27552755
err = "unknown argument"

Tools/clinic/libclinic/parse_args.py

Lines changed: 46 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,22 +1075,7 @@ def _generate_vc_parsing_code(self) -> list[str]:
10751075
def emit(text: str, indent: int = 4) -> None:
10761076
parser_code.append(snippet(text, indent=indent))
10771077

1078-
if no_params:
1079-
self.codegen.add_include('pycore_modsupport.h',
1080-
'_PyArg_NoKwnames()')
1081-
emit("""
1082-
if (!_PyArg_NoKwnames("{name}", kwnames)) {{
1083-
goto exit;
1084-
}}
1085-
if (nargs != 0) {{
1086-
PyErr_Format(PyExc_TypeError,
1087-
"{name}() takes no arguments (%zd given)",
1088-
nargs);
1089-
goto exit;
1090-
}}
1091-
""")
1092-
return parser_code
1093-
elif all_pos_only:
1078+
if no_params or all_pos_only:
10941079
self.codegen.add_include('pycore_modsupport.h',
10951080
'_PyArg_NoKwnames()')
10961081
emit("""
@@ -1099,21 +1084,30 @@ def emit(text: str, indent: int = 4) -> None:
10991084
}}
11001085
""")
11011086

1087+
if no_params:
1088+
emit("""
1089+
if (nargs != 0) {{
1090+
PyErr_Format(PyExc_TypeError,
1091+
"{name}() takes no arguments (%zd given)",
1092+
nargs);
1093+
goto exit;
1094+
}}
1095+
""")
1096+
return parser_code
1097+
11021098
pos_code, success = self._generate_vc_pos_only_code()
11031099
if not success:
11041100
for parameter in self.parameters:
11051101
parameter.converter.use_converter()
11061102
self.codegen.add_include('pycore_modsupport.h',
11071103
'_PyArg_ParseStack()')
1108-
return [snippet("""
1109-
if (!_PyArg_NoKwnames("{name}", kwnames)) {{
1110-
goto exit;
1111-
}}
1104+
emit("""
11121105
if (!_PyArg_ParseStack(args, nargs, "{format_units}:{name}",
11131106
{parse_arguments})) {{
11141107
goto exit;
11151108
}}
1116-
""", indent=4)]
1109+
""")
1110+
return parser_code
11171111
parser_code.extend(pos_code)
11181112
return parser_code
11191113
else:
@@ -1203,47 +1197,40 @@ def emit(text: str, indent: int = 4) -> None:
12031197

12041198
return parser_code
12051199

1206-
def generate_vectorcall(self) -> str:
1207-
"""Generate a vectorcall function for __init__ or __new__."""
1208-
func = self.func
1200+
def _vc_prototype(self) -> str:
12091201
vc_basename = self._vc_basename()
1210-
1211-
# Generate argument parsing code (FASTCALL-style)
1212-
parsing_code = self._generate_vc_parsing_code()
1213-
1214-
# Build the function prototype
1215-
prototype = libclinic.normalize_snippet(f"""
1202+
return libclinic.normalize_snippet(f"""
12161203
static PyObject *
12171204
{vc_basename}(PyObject *type, PyObject *const *args,
12181205
size_t nargsf, PyObject *kwnames)
12191206
""")
12201207

1221-
# Build the preamble
1222-
preamble = libclinic.normalize_snippet("""
1208+
def _vc_preamble(self) -> str:
1209+
return libclinic.normalize_snippet("""
12231210
{{
12241211
PyObject *return_value = NULL;
12251212
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
12261213
{declarations}
12271214
{initializers}
12281215
""") + "\n"
12291216

1230-
# Exact type check (if vectorcall_exact_only)
1231-
exact_check = ""
1232-
if func.vectorcall and func.vectorcall.exact_only and func.cls:
1233-
type_obj = func.cls.type_object
1234-
self.codegen.add_include('pycore_call.h',
1235-
'_PyObject_MakeTpCall()')
1236-
exact_check = libclinic.normalize_snippet(f"""
1237-
if (_PyType_CAST(type) != {type_obj}) {{{{
1238-
PyThreadState *tstate = _PyThreadState_GET();
1239-
return _PyObject_MakeTpCall(tstate, type, args,
1240-
nargs, kwnames);
1241-
}}}}
1242-
""", indent=4)
1243-
1244-
# Build the finale (impl call + return)
1245-
if func.kind is METHOD_INIT:
1246-
finale = libclinic.normalize_snippet("""
1217+
def _vc_exact_check(self) -> str:
1218+
func = self.func
1219+
if not (func.vectorcall and func.vectorcall.exact_only and func.cls):
1220+
return ""
1221+
type_obj = func.cls.type_object
1222+
self.codegen.add_include('pycore_call.h', '_PyObject_MakeTpCall()')
1223+
return libclinic.normalize_snippet(f"""
1224+
if (_PyType_CAST(type) != {type_obj}) {{{{
1225+
PyThreadState *tstate = _PyThreadState_GET();
1226+
return _PyObject_MakeTpCall(tstate, type, args,
1227+
nargs, kwnames);
1228+
}}}}
1229+
""", indent=4)
1230+
1231+
def _vc_finale(self) -> str:
1232+
if self.func.kind is METHOD_INIT:
1233+
return libclinic.normalize_snippet("""
12471234
{modifications}
12481235
{lock}
12491236
{{
@@ -1269,7 +1256,7 @@ def generate_vectorcall(self) -> str:
12691256
""")
12701257
else:
12711258
# METHOD_NEW
1272-
finale = libclinic.normalize_snippet("""
1259+
return libclinic.normalize_snippet("""
12731260
{modifications}
12741261
{lock}
12751262
return_value = {c_basename}_impl({vc_impl_arguments});
@@ -1283,13 +1270,18 @@ def generate_vectorcall(self) -> str:
12831270
}}
12841271
""")
12851272

1286-
# Assemble the full function
1287-
lines = [prototype]
1288-
lines.append(preamble)
1273+
def generate_vectorcall(self) -> str:
1274+
"""Generate a vectorcall function for __init__ or __new__."""
1275+
parsing_code = self._generate_vc_parsing_code()
1276+
1277+
lines = [self._vc_prototype(), self._vc_preamble()]
1278+
1279+
exact_check = self._vc_exact_check()
12891280
if exact_check:
12901281
lines.append(exact_check)
1282+
12911283
lines.extend(parsing_code)
1292-
lines.append(finale)
1284+
lines.append(self._vc_finale())
12931285

12941286
code = libclinic.linear_format(
12951287
"\n".join(lines),

0 commit comments

Comments
 (0)