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-114258: Argument Clinic: refactor getset implementation #116170

Merged
merged 6 commits into from Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 8 additions & 9 deletions Lib/test/clinic.test.c
Expand Up @@ -5004,12 +5004,16 @@ Test_property_set_impl(TestObj *self, PyObject *value);
static int
Test_property_set(TestObj *self, PyObject *value, void *Py_UNUSED(context))
{
return Test_property_set_impl(self, value);
int return_value;

return_value = Test_property_set_impl(self, value);

return return_value;
}

static int
Test_property_set_impl(TestObj *self, PyObject *value)
/*[clinic end generated code: output=9797cd03c5204ddb input=3bc3f46a23c83a88]*/
/*[clinic end generated code: output=d51023f17c4ac3a1 input=3bc3f46a23c83a88]*/

/*[clinic input]
output push
Expand Down Expand Up @@ -5346,7 +5350,6 @@ Test___init__(PyObject *self, PyObject *args, PyObject *kwargs)
{
int return_value = -1;
PyTypeObject *base_tp = TestType;
long _return_value;

if ((Py_IS_TYPE(self, base_tp) ||
Py_TYPE(self)->tp_new == base_tp->tp_new) &&
Expand All @@ -5358,19 +5361,15 @@ Test___init__(PyObject *self, PyObject *args, PyObject *kwargs)
!_PyArg_NoKeywords("Test", kwargs)) {
goto exit;
}
_return_value = Test___init___impl((TestObj *)self);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromLong(_return_value);
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
return_value = Test___init___impl((TestObj *)self);

exit:
return return_value;
}

static long
Test___init___impl(TestObj *self)
/*[clinic end generated code: output=daf6ee12c4e443fb input=311af0dc7f17e8e9]*/
/*[clinic end generated code: output=9f3704989ab1f6eb input=311af0dc7f17e8e9]*/


/*[clinic input]
Expand Down
5 changes: 2 additions & 3 deletions Lib/test/test_clinic.py
Expand Up @@ -2167,7 +2167,7 @@ class Foo "" ""
obj: int
/
"""
expected_error = f"{annotation} method cannot define parameters"
expected_error = f"{annotation} methods cannot define parameters"
self.expect_failure(block, expected_error)

def test_setter_docstring(self):
Expand Down Expand Up @@ -2647,7 +2647,6 @@ def test_cli_converters(self):
bool()
double()
float()
init()
int()
long()
Py_ssize_t()
Expand Down Expand Up @@ -3937,7 +3936,7 @@ def test_Function_and_Parameter_reprs(self):
cls=None,
c_basename=None,
full_name='foofoo',
return_converter=clinic.init_return_converter(),
return_converter=clinic.int_return_converter(),
kind=clinic.FunctionKind.METHOD_INIT,
coexist=False
)
Expand Down
35 changes: 10 additions & 25 deletions Tools/clinic/clinic.py
Expand Up @@ -859,9 +859,6 @@ def parser_body(
limited_capi = False

parsearg: str | None
if f.kind in {GETTER, SETTER} and parameters:
fail(f"@{f.kind.name.lower()} method cannot define parameters")

if not parameters:
parser_code: list[str] | None
if f.kind is GETTER:
Expand Down Expand Up @@ -1615,12 +1612,9 @@ def render_function(
for converter in converters:
converter.set_template_dict(template_dict)

f.return_converter.render(f, data)
if f.kind is SETTER:
# All setters return an int.
template_dict['impl_return_type'] = 'int'
else:
template_dict['impl_return_type'] = f.return_converter.type
if f.kind not in {SETTER, METHOD_INIT}:
f.return_converter.render(f, data)
template_dict['impl_return_type'] = f.return_converter.type

template_dict['declarations'] = libclinic.format_escape("\n".join(data.declarations))
template_dict['initializers'] = "\n\n".join(data.initializers)
Expand Down Expand Up @@ -4565,20 +4559,6 @@ class int_return_converter(long_return_converter):
cast = '(long)'


class init_return_converter(long_return_converter):
"""
Special return converter for __init__ functions.
"""
type = 'int'
cast = '(long)'

def render(
self,
function: Function,
data: CRenderData
) -> None: ...


class unsigned_long_return_converter(long_return_converter):
type = 'unsigned long'
conversion_fn = 'PyLong_FromUnsignedLong'
Expand Down Expand Up @@ -5109,8 +5089,8 @@ def resolve_return_converter(
except ValueError:
fail(f"Badly formed annotation for {full_name!r}: {forced_converter!r}")

if self.kind is METHOD_INIT:
return init_return_converter()
if self.kind in {METHOD_INIT, SETTER}:
return int_return_converter()
return CReturnConverter()

def parse_cloned_function(self, names: FunctionNames, existing: str) -> None:
Expand Down Expand Up @@ -5292,6 +5272,11 @@ def state_parameters_start(self, line: str) -> None:
if not self.indent.infer(line):
return self.next(self.state_function_docstring, line)

assert self.function is not None
if self.function.kind in {GETTER, SETTER}:
getset = self.function.kind.name.lower()
fail(f"@{getset} methods cannot define parameters")

self.parameter_continuation = ''
return self.next(self.state_parameter, line)

Expand Down