Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-108494: AC supports pos-only args in limited C API #108498

Merged
merged 1 commit into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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]'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not correct. In best case it is unused.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since AC and parsing arguments are complex, I propose to implement incrementally the limited C API. I'm not sure that I get your comment, when is it unused? Do you want to propose a fix?

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