summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_clinic.py11
-rw-r--r--Modules/_testclinic_limited.c18
-rw-r--r--Modules/clinic/_testclinic_limited.c.h34
-rwxr-xr-xTools/clinic/clinic.py24
4 files changed, 82 insertions, 5 deletions
diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py
index 9ee8f9c..e7039d5 100644
--- a/Lib/test/test_clinic.py
+++ b/Lib/test/test_clinic.py
@@ -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):
diff --git a/Modules/_testclinic_limited.c b/Modules/_testclinic_limited.c
index 6dd2745..0b606c9 100644
--- a/Modules/_testclinic_limited.c
+++ b/Modules/_testclinic_limited.c
@@ -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}
};
diff --git a/Modules/clinic/_testclinic_limited.c.h b/Modules/clinic/_testclinic_limited.c.h
index 730e967..9b00325 100644
--- a/Modules/clinic/_testclinic_limited.c.h
+++ b/Modules/clinic/_testclinic_limited.c.h
@@ -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]*/
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index 3d3ab4b..a6974bd 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -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,