Skip to content

Commit 0afc473

Browse files
gh-104050: Add typing to Argument Clinic converters (#104547)
1 parent b4a9747 commit 0afc473

File tree

1 file changed

+57
-53
lines changed

1 file changed

+57
-53
lines changed

Tools/clinic/clinic.py

+57-53
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def __repr__(self) -> str:
8282

8383
Appender = Callable[[str], None]
8484
Outputter = Callable[[], str]
85+
TemplateDict = dict[str, str]
8586

8687
class _TextAccumulator(NamedTuple):
8788
text: list[str]
@@ -1969,20 +1970,6 @@ def dump(self):
19691970
extensions['py'] = PythonLanguage
19701971

19711972

1972-
# maps strings to callables.
1973-
# these callables must be of the form:
1974-
# def foo(name, default, *, ...)
1975-
# The callable may have any number of keyword-only parameters.
1976-
# The callable must return a CConverter object.
1977-
# The callable should not call builtins.print.
1978-
converters = {}
1979-
1980-
# maps strings to callables.
1981-
# these callables follow the same rules as those for "converters" above.
1982-
# note however that they will never be called with keyword-only parameters.
1983-
legacy_converters = {}
1984-
1985-
19861973
# maps strings to callables.
19871974
# these callables must be of the form:
19881975
# def foo(*, ...)
@@ -2956,7 +2943,7 @@ def parse_arg(self, argname, displayname):
29562943
""".format(argname=argname, paramname=self.parser_name, cast=cast)
29572944
return None
29582945

2959-
def set_template_dict(self, template_dict: dict[str, str]):
2946+
def set_template_dict(self, template_dict: TemplateDict) -> None:
29602947
pass
29612948

29622949
@property
@@ -2979,6 +2966,23 @@ def parser_name(self):
29792966
}
29802967

29812968

2969+
ConverterType = Callable[..., CConverter]
2970+
ConverterDict = dict[str, ConverterType]
2971+
2972+
# maps strings to callables.
2973+
# these callables must be of the form:
2974+
# def foo(name, default, *, ...)
2975+
# The callable may have any number of keyword-only parameters.
2976+
# The callable must return a CConverter object.
2977+
# The callable should not call builtins.print.
2978+
converters: ConverterDict = {}
2979+
2980+
# maps strings to callables.
2981+
# these callables follow the same rules as those for "converters" above.
2982+
# note however that they will never be called with keyword-only parameters.
2983+
legacy_converters: ConverterDict = {}
2984+
2985+
29822986
class bool_converter(CConverter):
29832987
type = 'int'
29842988
default_type = bool
@@ -2994,7 +2998,7 @@ def converter_init(self, *, accept={object}):
29942998
self.default = bool(self.default)
29952999
self.c_default = str(int(self.default))
29963000

2997-
def parse_arg(self, argname, displayname):
3001+
def parse_arg(self, argname: str, displayname: str) -> str:
29983002
if self.format_unit == 'i':
29993003
return """
30003004
{paramname} = _PyLong_AsInt({argname});
@@ -3020,10 +3024,10 @@ class defining_class_converter(CConverter):
30203024
format_unit = ''
30213025
show_in_signature = False
30223026

3023-
def converter_init(self, *, type=None):
3027+
def converter_init(self, *, type=None) -> None:
30243028
self.specified_type = type
30253029

3026-
def render(self, parameter, data):
3030+
def render(self, parameter, data) -> None:
30273031
self._render_self(parameter, data)
30283032

30293033
def set_template_dict(self, template_dict):
@@ -3036,7 +3040,7 @@ class char_converter(CConverter):
30363040
format_unit = 'c'
30373041
c_ignored_default = "'\0'"
30383042

3039-
def converter_init(self):
3043+
def converter_init(self) -> None:
30403044
if isinstance(self.default, self.default_type):
30413045
if len(self.default) != 1:
30423046
fail("char_converter: illegal default value " + repr(self.default))
@@ -3045,7 +3049,7 @@ def converter_init(self):
30453049
if self.c_default == '"\'"':
30463050
self.c_default = r"'\''"
30473051

3048-
def parse_arg(self, argname, displayname):
3052+
def parse_arg(self, argname: str, displayname: str) -> str:
30493053
if self.format_unit == 'c':
30503054
return """
30513055
if (PyBytes_Check({argname}) && PyBytes_GET_SIZE({argname}) == 1) {{{{
@@ -3070,11 +3074,11 @@ class unsigned_char_converter(CConverter):
30703074
format_unit = 'b'
30713075
c_ignored_default = "'\0'"
30723076

3073-
def converter_init(self, *, bitwise=False):
3077+
def converter_init(self, *, bitwise: bool = False) -> None:
30743078
if bitwise:
30753079
self.format_unit = 'B'
30763080

3077-
def parse_arg(self, argname, displayname):
3081+
def parse_arg(self, argname: str, displayname: str) -> str:
30783082
if self.format_unit == 'b':
30793083
return """
30803084
{{{{
@@ -3119,7 +3123,7 @@ class short_converter(CConverter):
31193123
format_unit = 'h'
31203124
c_ignored_default = "0"
31213125

3122-
def parse_arg(self, argname, displayname):
3126+
def parse_arg(self, argname: str, displayname: str) -> str:
31233127
if self.format_unit == 'h':
31243128
return """
31253129
{{{{
@@ -3149,13 +3153,13 @@ class unsigned_short_converter(CConverter):
31493153
default_type = int
31503154
c_ignored_default = "0"
31513155

3152-
def converter_init(self, *, bitwise=False):
3156+
def converter_init(self, *, bitwise: bool = False) -> None:
31533157
if bitwise:
31543158
self.format_unit = 'H'
31553159
else:
31563160
self.converter = '_PyLong_UnsignedShort_Converter'
31573161

3158-
def parse_arg(self, argname, displayname):
3162+
def parse_arg(self, argname: str, displayname: str) -> str:
31593163
if self.format_unit == 'H':
31603164
return """
31613165
{paramname} = (unsigned short)PyLong_AsUnsignedLongMask({argname});
@@ -3172,15 +3176,15 @@ class int_converter(CConverter):
31723176
format_unit = 'i'
31733177
c_ignored_default = "0"
31743178

3175-
def converter_init(self, *, accept={int}, type=None):
3179+
def converter_init(self, *, accept={int}, type=None) -> None:
31763180
if accept == {str}:
31773181
self.format_unit = 'C'
31783182
elif accept != {int}:
31793183
fail("int_converter: illegal 'accept' argument " + repr(accept))
31803184
if type is not None:
31813185
self.type = type
31823186

3183-
def parse_arg(self, argname, displayname):
3187+
def parse_arg(self, argname: str, displayname: str) -> str:
31843188
if self.format_unit == 'i':
31853189
return """
31863190
{paramname} = _PyLong_AsInt({argname});
@@ -3211,13 +3215,13 @@ class unsigned_int_converter(CConverter):
32113215
default_type = int
32123216
c_ignored_default = "0"
32133217

3214-
def converter_init(self, *, bitwise=False):
3218+
def converter_init(self, *, bitwise: bool = False) -> None:
32153219
if bitwise:
32163220
self.format_unit = 'I'
32173221
else:
32183222
self.converter = '_PyLong_UnsignedInt_Converter'
32193223

3220-
def parse_arg(self, argname, displayname):
3224+
def parse_arg(self, argname: str, displayname: str) -> str:
32213225
if self.format_unit == 'I':
32223226
return """
32233227
{paramname} = (unsigned int)PyLong_AsUnsignedLongMask({argname});
@@ -3233,7 +3237,7 @@ class long_converter(CConverter):
32333237
format_unit = 'l'
32343238
c_ignored_default = "0"
32353239

3236-
def parse_arg(self, argname, displayname):
3240+
def parse_arg(self, argname: str, displayname: str) -> str:
32373241
if self.format_unit == 'l':
32383242
return """
32393243
{paramname} = PyLong_AsLong({argname});
@@ -3248,13 +3252,13 @@ class unsigned_long_converter(CConverter):
32483252
default_type = int
32493253
c_ignored_default = "0"
32503254

3251-
def converter_init(self, *, bitwise=False):
3255+
def converter_init(self, *, bitwise: bool = False) -> None:
32523256
if bitwise:
32533257
self.format_unit = 'k'
32543258
else:
32553259
self.converter = '_PyLong_UnsignedLong_Converter'
32563260

3257-
def parse_arg(self, argname, displayname):
3261+
def parse_arg(self, argname: str, displayname: str) -> str:
32583262
if self.format_unit == 'k':
32593263
return """
32603264
if (!PyLong_Check({argname})) {{{{
@@ -3272,7 +3276,7 @@ class long_long_converter(CConverter):
32723276
format_unit = 'L'
32733277
c_ignored_default = "0"
32743278

3275-
def parse_arg(self, argname, displayname):
3279+
def parse_arg(self, argname: str, displayname: str) -> str:
32763280
if self.format_unit == 'L':
32773281
return """
32783282
{paramname} = PyLong_AsLongLong({argname});
@@ -3287,13 +3291,13 @@ class unsigned_long_long_converter(CConverter):
32873291
default_type = int
32883292
c_ignored_default = "0"
32893293

3290-
def converter_init(self, *, bitwise=False):
3294+
def converter_init(self, *, bitwise: bool = False) -> None:
32913295
if bitwise:
32923296
self.format_unit = 'K'
32933297
else:
32943298
self.converter = '_PyLong_UnsignedLongLong_Converter'
32953299

3296-
def parse_arg(self, argname, displayname):
3300+
def parse_arg(self, argname: str, displayname: str) -> str:
32973301
if self.format_unit == 'K':
32983302
return """
32993303
if (!PyLong_Check({argname})) {{{{
@@ -3309,7 +3313,7 @@ class Py_ssize_t_converter(CConverter):
33093313
type = 'Py_ssize_t'
33103314
c_ignored_default = "0"
33113315

3312-
def converter_init(self, *, accept={int}):
3316+
def converter_init(self, *, accept={int}) -> None:
33133317
if accept == {int}:
33143318
self.format_unit = 'n'
33153319
self.default_type = int
@@ -3318,7 +3322,7 @@ def converter_init(self, *, accept={int}):
33183322
else:
33193323
fail("Py_ssize_t_converter: illegal 'accept' argument " + repr(accept))
33203324

3321-
def parse_arg(self, argname, displayname):
3325+
def parse_arg(self, argname: str, displayname: str) -> str:
33223326
if self.format_unit == 'n':
33233327
return """
33243328
{{{{
@@ -3340,7 +3344,7 @@ def parse_arg(self, argname, displayname):
33403344
class slice_index_converter(CConverter):
33413345
type = 'Py_ssize_t'
33423346

3343-
def converter_init(self, *, accept={int, NoneType}):
3347+
def converter_init(self, *, accept={int, NoneType}) -> None:
33443348
if accept == {int}:
33453349
self.converter = '_PyEval_SliceIndexNotNone'
33463350
elif accept == {int, NoneType}:
@@ -3353,7 +3357,7 @@ class size_t_converter(CConverter):
33533357
converter = '_PyLong_Size_t_Converter'
33543358
c_ignored_default = "0"
33553359

3356-
def parse_arg(self, argname, displayname):
3360+
def parse_arg(self, argname: str, displayname: str) -> str:
33573361
if self.format_unit == 'n':
33583362
return """
33593363
{paramname} = PyNumber_AsSsize_t({argname}, PyExc_OverflowError);
@@ -3368,7 +3372,7 @@ class fildes_converter(CConverter):
33683372
type = 'int'
33693373
converter = '_PyLong_FileDescriptor_Converter'
33703374

3371-
def _parse_arg(self, argname, displayname):
3375+
def _parse_arg(self, argname: str, displayname: str) -> str:
33723376
return """
33733377
{paramname} = PyObject_AsFileDescriptor({argname});
33743378
if ({paramname} == -1) {{{{
@@ -3383,7 +3387,7 @@ class float_converter(CConverter):
33833387
format_unit = 'f'
33843388
c_ignored_default = "0.0"
33853389

3386-
def parse_arg(self, argname, displayname):
3390+
def parse_arg(self, argname: str, displayname: str) -> str:
33873391
if self.format_unit == 'f':
33883392
return """
33893393
if (PyFloat_CheckExact({argname})) {{{{
@@ -3405,7 +3409,7 @@ class double_converter(CConverter):
34053409
format_unit = 'd'
34063410
c_ignored_default = "0.0"
34073411

3408-
def parse_arg(self, argname, displayname):
3412+
def parse_arg(self, argname: str, displayname: str) -> str:
34093413
if self.format_unit == 'd':
34103414
return """
34113415
if (PyFloat_CheckExact({argname})) {{{{
@@ -3428,7 +3432,7 @@ class Py_complex_converter(CConverter):
34283432
format_unit = 'D'
34293433
c_ignored_default = "{0.0, 0.0}"
34303434

3431-
def parse_arg(self, argname, displayname):
3435+
def parse_arg(self, argname: str, displayname: str) -> str:
34323436
if self.format_unit == 'D':
34333437
return """
34343438
{paramname} = PyComplex_AsCComplex({argname});
@@ -3504,7 +3508,7 @@ def post_parsing(self):
35043508
name = self.name
35053509
return f"PyMem_FREE({name});\n"
35063510

3507-
def parse_arg(self, argname, displayname):
3511+
def parse_arg(self, argname: str, displayname: str) -> str:
35083512
if self.format_unit == 's':
35093513
return """
35103514
if (!PyUnicode_Check({argname})) {{{{
@@ -3599,7 +3603,7 @@ class PyBytesObject_converter(CConverter):
35993603
format_unit = 'S'
36003604
# accept = {bytes}
36013605

3602-
def parse_arg(self, argname, displayname):
3606+
def parse_arg(self, argname: str, displayname: str) -> str:
36033607
if self.format_unit == 'S':
36043608
return """
36053609
if (!PyBytes_Check({argname})) {{{{
@@ -3616,7 +3620,7 @@ class PyByteArrayObject_converter(CConverter):
36163620
format_unit = 'Y'
36173621
# accept = {bytearray}
36183622

3619-
def parse_arg(self, argname, displayname):
3623+
def parse_arg(self, argname: str, displayname: str) -> str:
36203624
if self.format_unit == 'Y':
36213625
return """
36223626
if (!PyByteArray_Check({argname})) {{{{
@@ -3633,7 +3637,7 @@ class unicode_converter(CConverter):
36333637
default_type = (str, Null, NoneType)
36343638
format_unit = 'U'
36353639

3636-
def parse_arg(self, argname, displayname):
3640+
def parse_arg(self, argname: str, displayname: str) -> str:
36373641
if self.format_unit == 'U':
36383642
return """
36393643
if (!PyUnicode_Check({argname})) {{{{
@@ -3656,7 +3660,7 @@ class Py_UNICODE_converter(CConverter):
36563660
type = 'const Py_UNICODE *'
36573661
default_type = (str, Null, NoneType)
36583662

3659-
def converter_init(self, *, accept={str}, zeroes=False):
3663+
def converter_init(self, *, accept={str}, zeroes: bool = False) -> None:
36603664
format_unit = 'Z' if accept=={str, NoneType} else 'u'
36613665
if zeroes:
36623666
format_unit += '#'
@@ -3678,7 +3682,7 @@ def cleanup(self):
36783682
PyMem_Free((void *){name});
36793683
""".format(name=self.name)
36803684

3681-
def parse_arg(self, argname, argnum):
3685+
def parse_arg(self, argname: str, argnum: str) -> str:
36823686
if not self.length:
36833687
if self.accept == {str}:
36843688
return """
@@ -3718,7 +3722,7 @@ class Py_buffer_converter(CConverter):
37183722
impl_by_reference = True
37193723
c_ignored_default = "{NULL, NULL}"
37203724

3721-
def converter_init(self, *, accept={buffer}):
3725+
def converter_init(self, *, accept={buffer}) -> None:
37223726
if self.default not in (unspecified, None):
37233727
fail("The only legal default value for Py_buffer is None.")
37243728

@@ -3741,7 +3745,7 @@ def cleanup(self):
37413745
name = self.name
37423746
return "".join(["if (", name, ".obj) {\n PyBuffer_Release(&", name, ");\n}\n"])
37433747

3744-
def parse_arg(self, argname, displayname):
3748+
def parse_arg(self, argname: str, displayname: str) -> str:
37453749
if self.format_unit == 'y*':
37463750
return """
37473751
if (PyObject_GetBuffer({argname}, &{paramname}, PyBUF_SIMPLE) != 0) {{{{
@@ -3790,7 +3794,7 @@ def parse_arg(self, argname, displayname):
37903794
return super().parse_arg(argname, displayname)
37913795

37923796

3793-
def correct_name_for_self(f):
3797+
def correct_name_for_self(f) -> tuple[str, str]:
37943798
if f.kind in (CALLABLE, METHOD_INIT):
37953799
if f.cls:
37963800
return "PyObject *", "self"
@@ -3816,7 +3820,7 @@ class self_converter(CConverter):
38163820
type = None
38173821
format_unit = ''
38183822

3819-
def converter_init(self, *, type=None):
3823+
def converter_init(self, *, type=None) -> None:
38203824
self.specified_type = type
38213825

38223826
def pre_render(self):

0 commit comments

Comments
 (0)