[Python-checkins] gh-104050: Annotate Argument Clinic return converters (#104706)

erlend-aasland webhook-mailer at python.org
Sun May 21 16:23:20 EDT 2023


https://github.com/python/cpython/commit/c482e9a4e6f9c0b88ea248c4a0e0aa97223b5233
commit: c482e9a4e6f9c0b88ea248c4a0e0aa97223b5233
branch: main
author: Erlend E. Aasland <erlend.aasland at protonmail.com>
committer: erlend-aasland <erlend.aasland at protonmail.com>
date: 2023-05-21T20:23:14Z
summary:

gh-104050: Annotate Argument Clinic return converters (#104706)

Co-authored-by: Alex Waygood <Alex.Waygood at Gmail.com>

files:
M Tools/clinic/clinic.py

diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index 863bd66bef75..a1e8947529a0 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -1966,15 +1966,6 @@ def dump(self):
 extensions['py'] = PythonLanguage
 
 
-# maps strings to callables.
-# these callables must be of the form:
-#   def foo(*, ...)
-# The callable may have any number of keyword-only parameters.
-# The callable must return a CConverter object.
-# The callable should not call builtins.print.
-return_converters = {}
-
-
 def file_changed(filename: str, new_contents: str) -> bool:
     """Return true if file contents changed (meaning we must update it)"""
     try:
@@ -3005,6 +2996,16 @@ def parser_name(self):
 # note however that they will never be called with keyword-only parameters.
 legacy_converters: ConverterDict = {}
 
+# maps strings to callables.
+# these callables must be of the form:
+#   def foo(*, ...)
+# The callable may have any number of keyword-only parameters.
+# The callable must return a CReturnConverter object.
+# The callable should not call builtins.print.
+ReturnConverterType = Callable[..., "CReturnConverter"]
+ReturnConverterDict = dict[str, ReturnConverterType]
+return_converters: ReturnConverterDict = {}
+
 TypeSet = set[bltns.type[Any]]
 
 
@@ -3966,8 +3967,10 @@ def set_template_dict(self, template_dict):
             template_dict['base_type_ptr'] = type_ptr
 
 
-
-def add_c_return_converter(f, name=None):
+def add_c_return_converter(
+        f: ReturnConverterType,
+        name: str | None = None
+) -> ReturnConverterType:
     if not name:
         name = f.__name__
         if not name.endswith('_return_converter'):
@@ -3978,9 +3981,15 @@ def add_c_return_converter(f, name=None):
 
 
 class CReturnConverterAutoRegister(type):
-    def __init__(cls, name, bases, classdict):
+    def __init__(
+            cls: ReturnConverterType,
+            name: str,
+            bases: tuple[type, ...],
+            classdict: dict[str, Any]
+    ) -> None:
         add_c_return_converter(cls)
 
+
 class CReturnConverter(metaclass=CReturnConverterAutoRegister):
 
     # The C type to use for this variable.
@@ -3992,7 +4001,12 @@ class CReturnConverter(metaclass=CReturnConverterAutoRegister):
     # Or the magic value "unspecified" if there is no default.
     default: object = None
 
-    def __init__(self, *, py_default=None, **kwargs):
+    def __init__(
+            self,
+            *,
+            py_default: str | None = None,
+            **kwargs
+    ) -> None:
         self.py_default = py_default
         try:
             self.return_converter_init(**kwargs)
@@ -4000,11 +4014,10 @@ def __init__(self, *, py_default=None, **kwargs):
             s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
             sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
 
-    def return_converter_init(self):
-        pass
+    def return_converter_init(self) -> None: ...
 
-    def declare(self, data):
-        line = []
+    def declare(self, data: CRenderData) -> None:
+        line: list[str] = []
         add = line.append
         add(self.type)
         if not self.type.endswith('*'):
@@ -4013,50 +4026,70 @@ def declare(self, data):
         data.declarations.append(''.join(line))
         data.return_value = data.converter_retval
 
-    def err_occurred_if(self, expr, data):
+    def err_occurred_if(
+            self,
+            expr: str,
+            data: CRenderData
+    ) -> None:
         line = f'if (({expr}) && PyErr_Occurred()) {{\n    goto exit;\n}}\n'
         data.return_conversion.append(line)
 
-    def err_occurred_if_null_pointer(self, variable, data):
+    def err_occurred_if_null_pointer(
+            self,
+            variable: str,
+            data: CRenderData
+    ) -> None:
         line = f'if ({variable} == NULL) {{\n    goto exit;\n}}\n'
         data.return_conversion.append(line)
 
-    def render(self, function, data):
-        """
-        function is a clinic.Function instance.
-        data is a CRenderData instance.
-        """
-        pass
+    def render(
+            self,
+            function: Function,
+            data: CRenderData
+    ) -> None: ...
+
 
 add_c_return_converter(CReturnConverter, 'object')
 
+
 class bool_return_converter(CReturnConverter):
     type = 'int'
 
-    def render(self, function, data):
+    def render(
+            self,
+            function: Function,
+            data: CRenderData
+    ) -> None:
         self.declare(data)
         self.err_occurred_if(f"{data.converter_retval} == -1", data)
         data.return_conversion.append(
             f'return_value = PyBool_FromLong((long){data.converter_retval});\n'
         )
 
+
 class long_return_converter(CReturnConverter):
     type = 'long'
     conversion_fn = 'PyLong_FromLong'
     cast = ''
     unsigned_cast = ''
 
-    def render(self, function, data):
+    def render(
+            self,
+            function: Function,
+            data: CRenderData
+    ) -> None:
         self.declare(data)
         self.err_occurred_if(f"{data.converter_retval} == {self.unsigned_cast}-1", data)
         data.return_conversion.append(
             f'return_value = {self.conversion_fn}({self.cast}{data.converter_retval});\n'
         )
 
+
 class int_return_converter(long_return_converter):
     type = 'int'
     cast = '(long)'
 
+
 class init_return_converter(long_return_converter):
     """
     Special return converter for __init__ functions.
@@ -4064,23 +4097,30 @@ class init_return_converter(long_return_converter):
     type = 'int'
     cast = '(long)'
 
-    def render(self, function, data):
-        pass
+    def render(
+            self,
+            function: Function,
+            data: CRenderData
+    ) -> None: ...
+
 
 class unsigned_long_return_converter(long_return_converter):
     type = 'unsigned long'
     conversion_fn = 'PyLong_FromUnsignedLong'
     unsigned_cast = '(unsigned long)'
 
+
 class unsigned_int_return_converter(unsigned_long_return_converter):
     type = 'unsigned int'
     cast = '(unsigned long)'
     unsigned_cast = '(unsigned int)'
 
+
 class Py_ssize_t_return_converter(long_return_converter):
     type = 'Py_ssize_t'
     conversion_fn = 'PyLong_FromSsize_t'
 
+
 class size_t_return_converter(long_return_converter):
     type = 'size_t'
     conversion_fn = 'PyLong_FromSize_t'
@@ -4091,13 +4131,18 @@ class double_return_converter(CReturnConverter):
     type = 'double'
     cast = ''
 
-    def render(self, function, data):
+    def render(
+            self,
+            function: Function,
+            data: CRenderData
+    ) -> None:
         self.declare(data)
         self.err_occurred_if(f"{data.converter_retval} == -1.0", data)
         data.return_conversion.append(
             f'return_value = PyFloat_FromDouble({self.cast}{data.converter_retval});\n'
         )
 
+
 class float_return_converter(double_return_converter):
     type = 'float'
     cast = '(double)'



More information about the Python-checkins mailing list