mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
gh-108494: AC supports pos-only args in limited C API (#108498)
AC now checks for "#define Py_LIMITED_API" pattern to use the limited C API.
This commit is contained in:
parent
73d33c1a30
commit
86bc9e35c4
4 changed files with 82 additions and 5 deletions
|
@ -3542,6 +3542,17 @@ class LimitedCAPIFunctionalTest(unittest.TestCase):
|
|||
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):
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
||||
|
|
34
Modules/clinic/_testclinic_limited.c.h
generated
34
Modules/clinic/_testclinic_limited.c.h
generated
|
@ -50,4 +50,36 @@ my_int_func(PyObject *module, PyObject *arg_)
|
|||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=07e2e8ed6923cd16 input=a9049054013a1b77]*/
|
||||
|
||||
PyDoc_STRVAR(my_int_sum__doc__,
|
||||
"my_int_sum($module, x, y, /)\n"
|
||||
"--\n"
|
||||
"\n");
|
||||
|
||||
#define MY_INT_SUM_METHODDEF \
|
||||
{"my_int_sum", (PyCFunction)my_int_sum, METH_VARARGS, my_int_sum__doc__},
|
||||
|
||||
static int
|
||||
my_int_sum_impl(PyObject *module, int x, int y);
|
||||
|
||||
static PyObject *
|
||||
my_int_sum(PyObject *module, PyObject *args)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
int x;
|
||||
int y;
|
||||
int _return_value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii:my_int_sum",
|
||||
&x, &y))
|
||||
goto exit;
|
||||
_return_value = my_int_sum_impl(module, x, y);
|
||||
if ((_return_value == -1) && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
return_value = PyLong_FromLong((long)_return_value);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=f9f7209255bb969e input=a9049054013a1b77]*/
|
||||
|
|
|
@ -78,6 +78,7 @@ CLINIC_PREFIXED_ARGS = {
|
|||
"noptargs",
|
||||
"return_value",
|
||||
}
|
||||
LIMITED_CAPI_REGEX = re.compile(r'#define +Py_LIMITED_API')
|
||||
|
||||
|
||||
class Sentinels(enum.Enum):
|
||||
|
@ -1249,6 +1250,22 @@ class CLanguage(Language):
|
|||
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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue