summaryrefslogtreecommitdiffstats
path: root/Tools
diff options
context:
space:
mode:
authorErlend E. Aasland <erlend.aasland@protonmail.com>2023-05-21 20:23:14 (GMT)
committerGitHub <noreply@github.com>2023-05-21 20:23:14 (GMT)
commitc482e9a4e6f9c0b88ea248c4a0e0aa97223b5233 (patch)
treef4f118847a206c9993988743f28103aa90e8fd97 /Tools
parent5841fbc1a2aa5dd9e1c3d8d369f2bba8a99b285b (diff)
downloadcpython-c482e9a4e6f9c0b88ea248c4a0e0aa97223b5233.zip
cpython-c482e9a4e6f9c0b88ea248c4a0e0aa97223b5233.tar.gz
cpython-c482e9a4e6f9c0b88ea248c4a0e0aa97223b5233.tar.bz2
gh-104050: Annotate Argument Clinic return converters (#104706)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Diffstat (limited to 'Tools')
-rwxr-xr-xTools/clinic/clinic.py105
1 files changed, 75 insertions, 30 deletions
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index 863bd66..a1e8947 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -1966,15 +1966,6 @@ extensions: LangDict = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx"
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 @@ converters: ConverterDict = {}
# 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 @@ class self_converter(CConverter):
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 @@ class CReturnConverter(metaclass=CReturnConverterAutoRegister):
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 @@ class CReturnConverter(metaclass=CReturnConverterAutoRegister):
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)'