Skip to content

Commit cfbdce7

Browse files
gh-114258: Argument Clinic: refactor getset implementation (#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.
1 parent 45a9243 commit cfbdce7

File tree

3 files changed

+18
-35
lines changed

3 files changed

+18
-35
lines changed

Lib/test/clinic.test.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5004,12 +5004,16 @@ Test_property_set_impl(TestObj *self, PyObject *value);
50045004
static int
50055005
Test_property_set(TestObj *self, PyObject *value, void *Py_UNUSED(context))
50065006
{
5007-
return Test_property_set_impl(self, value);
5007+
int return_value;
5008+
5009+
return_value = Test_property_set_impl(self, value);
5010+
5011+
return return_value;
50085012
}
50095013

50105014
static int
50115015
Test_property_set_impl(TestObj *self, PyObject *value)
5012-
/*[clinic end generated code: output=9797cd03c5204ddb input=3bc3f46a23c83a88]*/
5016+
/*[clinic end generated code: output=d51023f17c4ac3a1 input=3bc3f46a23c83a88]*/
50135017

50145018
/*[clinic input]
50155019
output push
@@ -5327,11 +5331,6 @@ Test__pyarg_parsestackandkeywords_impl(TestObj *self, PyTypeObject *cls,
53275331
/*[clinic end generated code: output=4fda8a7f2547137c input=fc72ef4b4cfafabc]*/
53285332

53295333

5330-
static long
5331-
Test___init___impl(TestObj *self)
5332-
/*[clinic end generated code: output=daf6ee12c4e443fb input=311af0dc7f17e8e9]*/
5333-
5334-
53355334
/*[clinic input]
53365335
fn_with_default_binop_expr
53375336
arg: object(c_default='CONST_A + CONST_B') = a+b

Lib/test/test_clinic.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,7 +2175,7 @@ class Foo "" ""
21752175
obj: int
21762176
/
21772177
"""
2178-
expected_error = f"{annotation} method cannot define parameters"
2178+
expected_error = f"{annotation} methods cannot define parameters"
21792179
self.expect_failure(block, expected_error)
21802180

21812181
def test_setter_docstring(self):
@@ -2655,7 +2655,6 @@ def test_cli_converters(self):
26552655
bool()
26562656
double()
26572657
float()
2658-
init()
26592658
int()
26602659
long()
26612660
Py_ssize_t()
@@ -3945,7 +3944,7 @@ def test_Function_and_Parameter_reprs(self):
39453944
cls=None,
39463945
c_basename=None,
39473946
full_name='foofoo',
3948-
return_converter=clinic.init_return_converter(),
3947+
return_converter=clinic.int_return_converter(),
39493948
kind=clinic.FunctionKind.METHOD_INIT,
39503949
coexist=False
39513950
)

Tools/clinic/clinic.py

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -859,9 +859,6 @@ def parser_body(
859859
limited_capi = False
860860

861861
parsearg: str | None
862-
if f.kind in {GETTER, SETTER} and parameters:
863-
fail(f"@{f.kind.name.lower()} method cannot define parameters")
864-
865862
if not parameters:
866863
parser_code: list[str] | None
867864
if f.kind is GETTER:
@@ -1615,12 +1612,9 @@ def render_function(
16151612
for converter in converters:
16161613
converter.set_template_dict(template_dict)
16171614

1618-
f.return_converter.render(f, data)
1619-
if f.kind is SETTER:
1620-
# All setters return an int.
1621-
template_dict['impl_return_type'] = 'int'
1622-
else:
1623-
template_dict['impl_return_type'] = f.return_converter.type
1615+
if f.kind not in {SETTER, METHOD_INIT}:
1616+
f.return_converter.render(f, data)
1617+
template_dict['impl_return_type'] = f.return_converter.type
16241618

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

45674561

4568-
class init_return_converter(long_return_converter):
4569-
"""
4570-
Special return converter for __init__ functions.
4571-
"""
4572-
type = 'int'
4573-
cast = '(long)'
4574-
4575-
def render(
4576-
self,
4577-
function: Function,
4578-
data: CRenderData
4579-
) -> None: ...
4580-
4581-
45824562
class unsigned_long_return_converter(long_return_converter):
45834563
type = 'unsigned long'
45844564
conversion_fn = 'PyLong_FromUnsignedLong'
@@ -5111,8 +5091,8 @@ def resolve_return_converter(
51115091
except ValueError:
51125092
fail(f"Badly formed annotation for {full_name!r}: {forced_converter!r}")
51135093

5114-
if self.kind is METHOD_INIT:
5115-
return init_return_converter()
5094+
if self.kind in {METHOD_INIT, SETTER}:
5095+
return int_return_converter()
51165096
return CReturnConverter()
51175097

51185098
def parse_cloned_function(self, names: FunctionNames, existing: str) -> None:
@@ -5294,6 +5274,11 @@ def state_parameters_start(self, line: str) -> None:
52945274
if not self.indent.infer(line):
52955275
return self.next(self.state_function_docstring, line)
52965276

5277+
assert self.function is not None
5278+
if self.function.kind in {GETTER, SETTER}:
5279+
getset = self.function.kind.name.lower()
5280+
fail(f"@{getset} methods cannot define parameters")
5281+
52975282
self.parameter_continuation = ''
52985283
return self.next(self.state_parameter, line)
52995284

0 commit comments

Comments
 (0)