diff options
author | Erlend E. Aasland <erlend.aasland@protonmail.com> | 2023-05-12 08:34:00 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-12 08:34:00 (GMT) |
commit | b2c1b4da1935639cb89fbbad0ce170a1182537bd (patch) | |
tree | 5b68de40c8c0aa71db3157e0653450206d6beb13 | |
parent | 15795b57d92ee6315b5c8263290944b16834b5f2 (diff) | |
download | cpython-b2c1b4da1935639cb89fbbad0ce170a1182537bd.zip cpython-b2c1b4da1935639cb89fbbad0ce170a1182537bd.tar.gz cpython-b2c1b4da1935639cb89fbbad0ce170a1182537bd.tar.bz2 |
gh-104389: Add 'unused' keyword to Argument Clinic C converters (#104390)
Use the unused keyword param in the converter to explicitly
mark an argument as unused:
/*[clinic input]
SomeBaseClass.stubmethod
flag: bool(unused=True)
[clinic start generated code]*/
-rw-r--r-- | Doc/howto/clinic.rst | 3 | ||||
-rw-r--r-- | Lib/test/test_clinic.py | 38 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Tools-Demos/2023-05-11-15-12-11.gh-issue-104389.EiOhB3.rst | 2 | ||||
-rwxr-xr-x | Tools/clinic/clinic.py | 20 |
4 files changed, 62 insertions, 1 deletions
diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst index 6ebc2d9..4620b46 100644 --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -775,6 +775,9 @@ All Argument Clinic converters accept the following arguments: because :pep:`8` mandates that the Python library may not use annotations. + ``unused`` + Wrap the argument with :c:macro:`Py_UNUSED` in the impl function signature. + In addition, some converters accept additional arguments. Here is a list of these arguments, along with their meanings: diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 6aaf4d1..28d9f65 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -774,6 +774,44 @@ Not at column 0! module, function = block.signatures self.assertIsInstance((function.parameters['path']).converter, clinic.str_converter) + def test_unused_param(self): + block = self.parse(""" + module foo + foo.func + fn: object + k: float + i: float(unused=True) + / + * + flag: bool(unused=True) = False + """) + sig = block.signatures[1] # Function index == 1 + params = sig.parameters + conv = lambda fn: params[fn].converter + dataset = ( + {"name": "fn", "unused": False}, + {"name": "k", "unused": False}, + {"name": "i", "unused": True}, + {"name": "flag", "unused": True}, + ) + for param in dataset: + name, unused = param.values() + with self.subTest(name=name, unused=unused): + p = conv(name) + # Verify that the unused flag is parsed correctly. + self.assertEqual(unused, p.unused) + + # Now, check that we'll produce correct code. + decl = p.simple_declaration(in_parser=False) + if unused: + self.assertIn("Py_UNUSED", decl) + else: + self.assertNotIn("Py_UNUSED", decl) + + # Make sure the Py_UNUSED macro is not used in the parser body. + parser_decl = p.simple_declaration(in_parser=True) + self.assertNotIn("Py_UNUSED", parser_decl) + def parse(self, text): c = FakeClinic() parser = DSLParser(c) diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-05-11-15-12-11.gh-issue-104389.EiOhB3.rst b/Misc/NEWS.d/next/Tools-Demos/2023-05-11-15-12-11.gh-issue-104389.EiOhB3.rst new file mode 100644 index 0000000..854e1cc --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2023-05-11-15-12-11.gh-issue-104389.EiOhB3.rst @@ -0,0 +1,2 @@ +Argument Clinic C converters now accept the ``unused`` keyword, for wrapping +a parameter with :c:macro:`Py_UNUSED`. Patch by Erlend E. Aasland. diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 2ae8a02..19c4cd2 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -2599,6 +2599,9 @@ class CConverter(metaclass=CConverterAutoRegister): # Every non-abstract subclass should supply a valid value. c_ignored_default = 'NULL' + # If true, wrap with Py_UNUSED. + unused = False + # The C converter *function* to be used, if any. # (If this is not None, format_unit must be 'O&'.) converter = None @@ -2651,9 +2654,22 @@ class CConverter(metaclass=CConverterAutoRegister): signature_name = None # keep in sync with self_converter.__init__! - def __init__(self, name, py_name, function, default=unspecified, *, c_default=None, py_default=None, annotation=unspecified, **kwargs): + def __init__(self, + # Positional args: + name, + py_name, + function, + default=unspecified, + *, # Keyword only args: + c_default=None, + py_default=None, + annotation=unspecified, + unused=False, + **kwargs + ): self.name = ensure_legal_c_identifier(name) self.py_name = py_name + self.unused = unused if default is not unspecified: if self.default_type and not isinstance(default, (self.default_type, Unknown)): @@ -2800,6 +2816,8 @@ class CConverter(metaclass=CConverterAutoRegister): name = self.parser_name else: name = self.name + if self.unused: + name = f"Py_UNUSED({name})" prototype.append(name) return "".join(prototype) |