Skip to content

Commit 8da84e6

Browse files
committed
gh-108494: AC supports pos-only args in limited C API
AC now checks for "#define Py_LIMITED_API" pattern to use the limited C API.
1 parent 1dd9510 commit 8da84e6

File tree

4 files changed

+82
-5
lines changed

4 files changed

+82
-5
lines changed

Lib/test/test_clinic.py

+11
Original file line numberDiff line numberDiff line change
@@ -3542,6 +3542,17 @@ def test_my_int_func(self):
35423542
with self.assertRaises(TypeError):
35433543
_testclinic_limited.my_int_func("xyz")
35443544

3545+
def test_my_int_sum(self):
3546+
with self.assertRaises(TypeError):
3547+
_testclinic_limited.my_int_sum()
3548+
with self.assertRaises(TypeError):
3549+
_testclinic_limited.my_int_sum(1)
3550+
self.assertEqual(_testclinic_limited.my_int_sum(1, 2), 3)
3551+
with self.assertRaises(TypeError):
3552+
_testclinic_limited.my_int_sum(1.0, 2)
3553+
with self.assertRaises(TypeError):
3554+
_testclinic_limited.my_int_sum(1, "str")
3555+
35453556

35463557

35473558
class PermutationTests(unittest.TestCase):

Modules/_testclinic_limited.c

+18
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,27 @@ my_int_func_impl(PyObject *module, int arg)
4545
}
4646

4747

48+
/*[clinic input]
49+
my_int_sum -> int
50+
51+
x: int
52+
y: int
53+
/
54+
55+
[clinic start generated code]*/
56+
57+
static int
58+
my_int_sum_impl(PyObject *module, int x, int y)
59+
/*[clinic end generated code: output=3e52db9ab5f37e2f input=0edb6796813bf2d3]*/
60+
{
61+
return x + y;
62+
}
63+
64+
4865
static PyMethodDef tester_methods[] = {
4966
TEST_EMPTY_FUNCTION_METHODDEF
5067
MY_INT_FUNC_METHODDEF
68+
MY_INT_SUM_METHODDEF
5169
{NULL, NULL}
5270
};
5371

Modules/clinic/_testclinic_limited.c.h

+33-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/clinic/clinic.py

+20-4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"noptargs",
7979
"return_value",
8080
}
81+
LIMITED_CAPI_REGEX = re.compile(r'#define +Py_LIMITED_API')
8182

8283

8384
class Sentinels(enum.Enum):
@@ -1244,6 +1245,22 @@ def parser_body(
12441245
parser_prototype = self.PARSER_PROTOTYPE_VARARGS
12451246
parser_definition = parser_body(parser_prototype, ' {option_group_parsing}')
12461247

1248+
elif not requires_defining_class and pos_only == len(parameters) - pseudo_args and clinic.limited_capi:
1249+
# positional-only for the limited C API
1250+
flags = "METH_VARARGS"
1251+
1252+
parser_prototype = self.PARSER_PROTOTYPE_VARARGS
1253+
parser_code = [normalize_snippet("""
1254+
if (!PyArg_ParseTuple(args, "{format_units}:{name}",
1255+
{parse_arguments}))
1256+
goto exit;
1257+
""", indent=4)]
1258+
argname_fmt = 'args[%d]'
1259+
declarations = ""
1260+
1261+
parser_definition = parser_body(parser_prototype, *parser_code,
1262+
declarations=declarations)
1263+
12471264
elif not requires_defining_class and pos_only == len(parameters) - pseudo_args:
12481265
if not new_or_init:
12491266
# positional-only, but no option groups
@@ -2563,10 +2580,6 @@ def parse_file(
25632580
) -> None:
25642581
verify = not ns.force
25652582
limited_capi = ns.limited_capi
2566-
# XXX Temporary solution
2567-
if os.path.basename(filename) == '_testclinic_limited.c':
2568-
print(f"{filename} uses limited C API")
2569-
limited_capi = True
25702583
if not output:
25712584
output = filename
25722585

@@ -2587,6 +2600,9 @@ def parse_file(
25872600
if not find_start_re.search(raw):
25882601
return
25892602

2603+
if LIMITED_CAPI_REGEX.search(raw):
2604+
limited_capi = True
2605+
25902606
assert isinstance(language, CLanguage)
25912607
clinic = Clinic(language,
25922608
verify=verify,

0 commit comments

Comments
 (0)