Skip to content

Commit

Permalink
pythongh-108494: AC supports pos-only args in limited C API
Browse files Browse the repository at this point in the history
AC now checks for "#define Py_LIMITED_API" pattern to use the limited
C API.
  • Loading branch information
vstinner committed Aug 25, 2023
1 parent 73d33c1 commit c38deb5
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 5 deletions.
11 changes: 11 additions & 0 deletions Lib/test/test_clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3542,6 +3542,17 @@ def test_my_int_func(self):
with self.assertRaises(TypeError):
_testclinic_limited.my_int_func("xyz")

def test_my_int_sum(self):
with self.assertRaises(TypeError):
_testclinic_limited.my_int_sum()
with self.assertRaises(TypeError):
_testclinic_limited.my_int_sum(1)
self.assertEqual(_testclinic_limited.my_int_sum(1, 2), 3)
with self.assertRaises(TypeError):
_testclinic_limited.my_int_sum(1.0, 2)
with self.assertRaises(TypeError):
_testclinic_limited.my_int_sum(1, "str")



class PermutationTests(unittest.TestCase):
Expand Down
18 changes: 18 additions & 0 deletions Modules/_testclinic_limited.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,27 @@ my_int_func_impl(PyObject *module, int arg)
}


/*[clinic input]
my_int_sum -> int
x: int
y: int
/
[clinic start generated code]*/

static int
my_int_sum_impl(PyObject *module, int x, int y)
/*[clinic end generated code: output=3e52db9ab5f37e2f input=0edb6796813bf2d3]*/
{
return x + y;
}


static PyMethodDef tester_methods[] = {
TEST_EMPTY_FUNCTION_METHODDEF
MY_INT_FUNC_METHODDEF
MY_INT_SUM_METHODDEF
{NULL, NULL}
};

Expand Down
34 changes: 33 additions & 1 deletion Modules/clinic/_testclinic_limited.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 20 additions & 4 deletions Tools/clinic/clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"noptargs",
"return_value",
}
LIMITED_CAPI_REGEX = re.compile(r'#define +Py_LIMITED_API')


class Sentinels(enum.Enum):
Expand Down Expand Up @@ -1249,6 +1250,22 @@ def parser_body(
parser_prototype = self.PARSER_PROTOTYPE_VARARGS
parser_definition = parser_body(parser_prototype, ' {option_group_parsing}')

elif not requires_defining_class and pos_only == len(parameters) - pseudo_args and clinic.limited_capi:
# positional-only for the limited C API
flags = "METH_VARARGS"

parser_prototype = self.PARSER_PROTOTYPE_VARARGS
parser_code = [normalize_snippet("""
if (!PyArg_ParseTuple(args, "{format_units}:{name}",
{parse_arguments}))
goto exit;
""", indent=4)]
argname_fmt = 'args[%d]'
declarations = ""

parser_definition = parser_body(parser_prototype, *parser_code,
declarations=declarations)

elif not requires_defining_class and pos_only == len(parameters) - pseudo_args:
if not new_or_init:
# positional-only, but no option groups
Expand Down Expand Up @@ -2581,10 +2598,6 @@ def parse_file(
) -> None:
verify = not ns.force
limited_capi = ns.limited_capi
# XXX Temporary solution
if os.path.basename(filename) == '_testclinic_limited.c':
print(f"{filename} uses limited C API")
limited_capi = True
if not output:
output = filename

Expand All @@ -2605,6 +2618,9 @@ def parse_file(
if not find_start_re.search(raw):
return

if LIMITED_CAPI_REGEX.search(raw):
limited_capi = True

assert isinstance(language, CLanguage)
clinic = Clinic(language,
verify=verify,
Expand Down

0 comments on commit c38deb5

Please sign in to comment.