Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
gh-104050: Add typing to Argument Clinic converters#104547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
erlend-aasland merged 6 commits intopython:mainfromerlend-aasland:typed-clinic/convertersMay 16, 2023
Uh oh!
There was an error while loading.Please reload this page.
Merged
Changes fromall commits
Commits
Show all changes
6 commits Select commitHold shift + click to select a range
cce842a gh-104050: Add typing to Argument Clinic converters
erlend-aasland8191183 Update Tools/clinic/clinic.py
erlend-aaslanddd1c773 Also add types to 'default_type'
erlend-aaslandbdc130d Remove annotations of simple assignments
erlend-aasland75cb81e Merge branch 'main' into typed-clinic/converters
AlexWaygood2e5b92c Address reviews
erlend-aaslandFile filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -82,6 +82,7 @@ def __repr__(self) -> str: | ||
| Appender = Callable[[str], None] | ||
| Outputter = Callable[[], str] | ||
| TemplateDict = dict[str, str] | ||
| class _TextAccumulator(NamedTuple): | ||
| text: list[str] | ||
| @@ -1969,20 +1970,6 @@ def dump(self): | ||
| extensions['py'] = PythonLanguage | ||
| # maps strings to callables. | ||
| # these callables must be of the form: | ||
| # def foo(*, ...) | ||
| @@ -2956,7 +2943,7 @@ def parse_arg(self, argname, displayname): | ||
| """.format(argname=argname, paramname=self.parser_name, cast=cast) | ||
| return None | ||
| def set_template_dict(self, template_dict:TemplateDict) -> None: | ||
| pass | ||
| @property | ||
| @@ -2979,6 +2966,23 @@ def parser_name(self): | ||
| } | ||
| ConverterType = Callable[..., CConverter] | ||
| ConverterDict = dict[str, ConverterType] | ||
| # maps strings to callables. | ||
| # these callables must be of the form: | ||
| # def foo(name, default, *, ...) | ||
| # The callable may have any number of keyword-only parameters. | ||
| # The callable must return a CConverter object. | ||
| # The callable should not call builtins.print. | ||
| converters: ConverterDict = {} | ||
| # maps strings to callables. | ||
| # these callables follow the same rules as those for "converters" above. | ||
| # note however that they will never be called with keyword-only parameters. | ||
| legacy_converters: ConverterDict = {} | ||
| class bool_converter(CConverter): | ||
| type = 'int' | ||
| default_type = bool | ||
erlend-aasland marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| @@ -2994,7 +2998,7 @@ def converter_init(self, *, accept={object}): | ||
| self.default = bool(self.default) | ||
| self.c_default = str(int(self.default)) | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'i': | ||
| return """ | ||
| {paramname} = _PyLong_AsInt({argname}); | ||
| @@ -3020,10 +3024,10 @@ class defining_class_converter(CConverter): | ||
| format_unit = '' | ||
| show_in_signature = False | ||
| def converter_init(self, *, type=None) -> None: | ||
| self.specified_type = type | ||
| def render(self, parameter, data) -> None: | ||
| self._render_self(parameter, data) | ||
| def set_template_dict(self, template_dict): | ||
| @@ -3036,7 +3040,7 @@ class char_converter(CConverter): | ||
| format_unit = 'c' | ||
| c_ignored_default = "'\0'" | ||
| def converter_init(self) -> None: | ||
| if isinstance(self.default, self.default_type): | ||
| if len(self.default) != 1: | ||
| fail("char_converter: illegal default value " + repr(self.default)) | ||
| @@ -3045,7 +3049,7 @@ def converter_init(self): | ||
| if self.c_default == '"\'"': | ||
| self.c_default = r"'\''" | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'c': | ||
| return """ | ||
| if (PyBytes_Check({argname}) && PyBytes_GET_SIZE({argname}) == 1) {{{{ | ||
| @@ -3070,11 +3074,11 @@ class unsigned_char_converter(CConverter): | ||
| format_unit = 'b' | ||
| c_ignored_default = "'\0'" | ||
| def converter_init(self, *, bitwise: bool =False) -> None: | ||
| if bitwise: | ||
| self.format_unit = 'B' | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'b': | ||
| return """ | ||
| {{{{ | ||
| @@ -3119,7 +3123,7 @@ class short_converter(CConverter): | ||
| format_unit = 'h' | ||
| c_ignored_default = "0" | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'h': | ||
| return """ | ||
| {{{{ | ||
| @@ -3149,13 +3153,13 @@ class unsigned_short_converter(CConverter): | ||
| default_type = int | ||
| c_ignored_default = "0" | ||
| def converter_init(self, *, bitwise: bool =False) -> None: | ||
| if bitwise: | ||
| self.format_unit = 'H' | ||
| else: | ||
| self.converter = '_PyLong_UnsignedShort_Converter' | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'H': | ||
| return """ | ||
| {paramname} = (unsigned short)PyLong_AsUnsignedLongMask({argname}); | ||
| @@ -3172,15 +3176,15 @@ class int_converter(CConverter): | ||
| format_unit = 'i' | ||
| c_ignored_default = "0" | ||
| def converter_init(self, *, accept={int}, type=None) -> None: | ||
| if accept == {str}: | ||
| self.format_unit = 'C' | ||
| elif accept != {int}: | ||
| fail("int_converter: illegal 'accept' argument " + repr(accept)) | ||
| if type is not None: | ||
| self.type = type | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'i': | ||
| return """ | ||
| {paramname} = _PyLong_AsInt({argname}); | ||
| @@ -3211,13 +3215,13 @@ class unsigned_int_converter(CConverter): | ||
| default_type = int | ||
| c_ignored_default = "0" | ||
| def converter_init(self, *, bitwise: bool =False) -> None: | ||
| if bitwise: | ||
| self.format_unit = 'I' | ||
| else: | ||
| self.converter = '_PyLong_UnsignedInt_Converter' | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'I': | ||
| return """ | ||
| {paramname} = (unsigned int)PyLong_AsUnsignedLongMask({argname}); | ||
| @@ -3233,7 +3237,7 @@ class long_converter(CConverter): | ||
| format_unit = 'l' | ||
| c_ignored_default = "0" | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'l': | ||
| return """ | ||
| {paramname} = PyLong_AsLong({argname}); | ||
| @@ -3248,13 +3252,13 @@ class unsigned_long_converter(CConverter): | ||
| default_type = int | ||
| c_ignored_default = "0" | ||
| def converter_init(self, *, bitwise: bool =False) -> None: | ||
| if bitwise: | ||
| self.format_unit = 'k' | ||
| else: | ||
| self.converter = '_PyLong_UnsignedLong_Converter' | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'k': | ||
| return """ | ||
| if (!PyLong_Check({argname})) {{{{ | ||
| @@ -3272,7 +3276,7 @@ class long_long_converter(CConverter): | ||
| format_unit = 'L' | ||
| c_ignored_default = "0" | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'L': | ||
| return """ | ||
| {paramname} = PyLong_AsLongLong({argname}); | ||
| @@ -3287,13 +3291,13 @@ class unsigned_long_long_converter(CConverter): | ||
| default_type = int | ||
| c_ignored_default = "0" | ||
| def converter_init(self, *, bitwise: bool =False) -> None: | ||
| if bitwise: | ||
| self.format_unit = 'K' | ||
| else: | ||
| self.converter = '_PyLong_UnsignedLongLong_Converter' | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'K': | ||
| return """ | ||
| if (!PyLong_Check({argname})) {{{{ | ||
| @@ -3309,7 +3313,7 @@ class Py_ssize_t_converter(CConverter): | ||
| type = 'Py_ssize_t' | ||
| c_ignored_default = "0" | ||
| def converter_init(self, *, accept={int}) -> None: | ||
| if accept == {int}: | ||
| self.format_unit = 'n' | ||
| self.default_type = int | ||
| @@ -3318,7 +3322,7 @@ def converter_init(self, *, accept={int}): | ||
| else: | ||
| fail("Py_ssize_t_converter: illegal 'accept' argument " + repr(accept)) | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'n': | ||
| return """ | ||
| {{{{ | ||
| @@ -3340,7 +3344,7 @@ def parse_arg(self, argname, displayname): | ||
| class slice_index_converter(CConverter): | ||
| type = 'Py_ssize_t' | ||
| def converter_init(self, *, accept={int, NoneType}) -> None: | ||
| if accept == {int}: | ||
| self.converter = '_PyEval_SliceIndexNotNone' | ||
| elif accept == {int, NoneType}: | ||
| @@ -3353,7 +3357,7 @@ class size_t_converter(CConverter): | ||
| converter = '_PyLong_Size_t_Converter' | ||
| c_ignored_default = "0" | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'n': | ||
| return """ | ||
| {paramname} = PyNumber_AsSsize_t({argname}, PyExc_OverflowError); | ||
| @@ -3368,7 +3372,7 @@ class fildes_converter(CConverter): | ||
| type = 'int' | ||
| converter = '_PyLong_FileDescriptor_Converter' | ||
| def _parse_arg(self, argname: str, displayname: str) -> str: | ||
| return """ | ||
| {paramname} = PyObject_AsFileDescriptor({argname}); | ||
| if ({paramname} == -1) {{{{ | ||
| @@ -3383,7 +3387,7 @@ class float_converter(CConverter): | ||
| format_unit = 'f' | ||
| c_ignored_default = "0.0" | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'f': | ||
| return """ | ||
| if (PyFloat_CheckExact({argname})) {{{{ | ||
| @@ -3405,7 +3409,7 @@ class double_converter(CConverter): | ||
| format_unit = 'd' | ||
| c_ignored_default = "0.0" | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'd': | ||
| return """ | ||
| if (PyFloat_CheckExact({argname})) {{{{ | ||
| @@ -3428,7 +3432,7 @@ class Py_complex_converter(CConverter): | ||
| format_unit = 'D' | ||
| c_ignored_default = "{0.0, 0.0}" | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'D': | ||
| return """ | ||
| {paramname} = PyComplex_AsCComplex({argname}); | ||
| @@ -3504,7 +3508,7 @@ def post_parsing(self): | ||
| name = self.name | ||
| return f"PyMem_FREE({name});\n" | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 's': | ||
| return """ | ||
| if (!PyUnicode_Check({argname})) {{{{ | ||
| @@ -3599,7 +3603,7 @@ class PyBytesObject_converter(CConverter): | ||
| format_unit = 'S' | ||
| # accept = {bytes} | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'S': | ||
| return """ | ||
| if (!PyBytes_Check({argname})) {{{{ | ||
| @@ -3616,7 +3620,7 @@ class PyByteArrayObject_converter(CConverter): | ||
| format_unit = 'Y' | ||
| # accept = {bytearray} | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'Y': | ||
| return """ | ||
| if (!PyByteArray_Check({argname})) {{{{ | ||
| @@ -3633,7 +3637,7 @@ class unicode_converter(CConverter): | ||
| default_type = (str, Null, NoneType) | ||
| format_unit = 'U' | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'U': | ||
| return """ | ||
| if (!PyUnicode_Check({argname})) {{{{ | ||
| @@ -3656,7 +3660,7 @@ class Py_UNICODE_converter(CConverter): | ||
| type = 'const Py_UNICODE *' | ||
| default_type = (str, Null, NoneType) | ||
| def converter_init(self, *, accept={str}, zeroes: bool =False) -> None: | ||
| format_unit = 'Z' if accept=={str, NoneType} else 'u' | ||
| if zeroes: | ||
| format_unit += '#' | ||
| @@ -3678,7 +3682,7 @@ def cleanup(self): | ||
| PyMem_Free((void *){name}); | ||
| """.format(name=self.name) | ||
| def parse_arg(self, argname: str, argnum: str) -> str: | ||
| if not self.length: | ||
| if self.accept == {str}: | ||
| return """ | ||
| @@ -3718,7 +3722,7 @@ class Py_buffer_converter(CConverter): | ||
| impl_by_reference = True | ||
| c_ignored_default = "{NULL, NULL}" | ||
| def converter_init(self, *, accept={buffer}) -> None: | ||
| if self.default not in (unspecified, None): | ||
| fail("The only legal default value for Py_buffer is None.") | ||
| @@ -3741,7 +3745,7 @@ def cleanup(self): | ||
| name = self.name | ||
| return "".join(["if (", name, ".obj) {\n PyBuffer_Release(&", name, ");\n}\n"]) | ||
| def parse_arg(self, argname: str, displayname: str) -> str: | ||
| if self.format_unit == 'y*': | ||
| return """ | ||
| if (PyObject_GetBuffer({argname}, &{paramname}, PyBUF_SIMPLE) != 0) {{{{ | ||
| @@ -3790,7 +3794,7 @@ def parse_arg(self, argname, displayname): | ||
| return super().parse_arg(argname, displayname) | ||
| def correct_name_for_self(f) -> tuple[str, str]: | ||
| if f.kind in (CALLABLE, METHOD_INIT): | ||
| if f.cls: | ||
| return "PyObject *", "self" | ||
| @@ -3816,7 +3820,7 @@ class self_converter(CConverter): | ||
| type = None | ||
| format_unit = '' | ||
| def converter_init(self, *, type=None) -> None: | ||
| self.specified_type = type | ||
| def pre_render(self): | ||
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.