Skip to content

Commit

Permalink
pythongh-114258: Argument Clinic: refactor getset implementation (pyt…
Browse files Browse the repository at this point in the history
…hon#116170)

* Move param guard to param state machine
* Override return converter during parsing
* Don't use a custom type slot return converter; instead
  special case type slot functions during generation.
  • Loading branch information
erlend-aasland authored and woodruffw committed Mar 4, 2024
1 parent feeb816 commit 996316d
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 35 deletions.
13 changes: 6 additions & 7 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 @@ -5327,11 +5331,6 @@ Test__pyarg_parsestackandkeywords_impl(TestObj *self, PyTypeObject *cls,
/*[clinic end generated code: output=4fda8a7f2547137c input=fc72ef4b4cfafabc]*/


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


/*[clinic input]
fn_with_default_binop_expr
arg: object(c_default='CONST_A + CONST_B') = a+b
Expand Down
5 changes: 2 additions & 3 deletions Lib/test/test_clinic.py
Expand Up @@ -2175,7 +2175,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 @@ -2655,7 +2655,6 @@ def test_cli_converters(self):
bool()
double()
float()
init()
int()
long()
Py_ssize_t()
Expand Down Expand Up @@ -3945,7 +3944,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 @@ -5111,8 +5091,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 @@ -5294,6 +5274,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

0 comments on commit 996316d

Please sign in to comment.