[Python-checkins] gh-104389: Add 'unused' keyword to Argument Clinic C converters (#104390)

erlend-aasland webhook-mailer at python.org
Fri May 12 04:34:13 EDT 2023


https://github.com/python/cpython/commit/b2c1b4da1935639cb89fbbad0ce170a1182537bd
commit: b2c1b4da1935639cb89fbbad0ce170a1182537bd
branch: main
author: Erlend E. Aasland <erlend.aasland at protonmail.com>
committer: erlend-aasland <erlend.aasland at protonmail.com>
date: 2023-05-12T10:34:00+02:00
summary:

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]*/

files:
A Misc/NEWS.d/next/Tools-Demos/2023-05-11-15-12-11.gh-issue-104389.EiOhB3.rst
M Doc/howto/clinic.rst
M Lib/test/test_clinic.py
M Tools/clinic/clinic.py

diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst
index 6ebc2d9b0a71..4620b4617e34 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 6aaf4d1ed8d5..28d9f6509264 100644
--- a/Lib/test/test_clinic.py
+++ b/Lib/test/test_clinic.py
@@ -774,6 +774,44 @@ def test_legacy_converters(self):
         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 000000000000..854e1cca967c
--- /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 2ae8a02aa6d2..19c4cd299f0b 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 @@ def simple_declaration(self, by_reference=False, *, in_parser=False):
             name = self.parser_name
         else:
             name = self.name
+            if self.unused:
+                name = f"Py_UNUSED({name})"
         prototype.append(name)
         return "".join(prototype)
 



More information about the Python-checkins mailing list