]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-114258: Argument Clinic: refactor getset implementation (#116170)
authorErlend E. Aasland <erlend@python.org>
Mon, 4 Mar 2024 12:51:28 +0000 (13:51 +0100)
committerGitHub <noreply@github.com>
Mon, 4 Mar 2024 12:51:28 +0000 (13:51 +0100)
* 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.

Lib/test/clinic.test.c
Lib/test/test_clinic.py
Tools/clinic/clinic.py

index e4dbb70d44ced99e1a06301e74dda7a345b35d2a..58ffc0ad4ab88b39beb88d9af853597109d606b0 100644 (file)
@@ -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
@@ -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
index 0a16f98a5a1f996f8fa35782b43071f4778dc661..02a293e04b21822277c968fa3e5752a0a85c2771 100644 (file)
@@ -2175,7 +2175,7 @@ class ClinicParserTest(TestCase):
                        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):
@@ -2655,7 +2655,6 @@ class ClinicExternalTest(TestCase):
                 bool()
                 double()
                 float()
-                init()
                 int()
                 long()
                 Py_ssize_t()
@@ -3945,7 +3944,7 @@ class ClinicReprTests(unittest.TestCase):
             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
         )
index 80da035131b8177d8abdf5da9d594157699639cd..0a8546247cc326585aac936b301b753d0e62bc62 100755 (executable)
@@ -859,9 +859,6 @@ class CLanguage(Language):
             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:
@@ -1615,12 +1612,9 @@ class CLanguage(Language):
         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)
@@ -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'
@@ -5111,8 +5091,8 @@ class DSLParser:
             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:
@@ -5294,6 +5274,11 @@ class DSLParser:
         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)