[Python-checkins] gh-104683: Argument Clinic: Extract parse function name helper (#107964)

erlend-aasland webhook-mailer at python.org
Wed Aug 16 09:47:19 EDT 2023


https://github.com/python/cpython/commit/42429d3b9adb8af1eadcfa155f6e8422a254ec67
commit: 42429d3b9adb8af1eadcfa155f6e8422a254ec67
branch: main
author: Erlend E. Aasland <erlend at python.org>
committer: erlend-aasland <erlend.aasland at protonmail.com>
date: 2023-08-16T13:47:15Z
summary:

gh-104683: Argument Clinic: Extract parse function name helper (#107964)

Co-authored-by: Alex Waygood <Alex.Waygood at Gmail.com>

files:
M Lib/test/test_clinic.py
M Tools/clinic/clinic.py

diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py
index 32aac407a028c..38eabd2f7f21d 100644
--- a/Lib/test/test_clinic.py
+++ b/Lib/test/test_clinic.py
@@ -682,7 +682,7 @@ class C "void *" ""
             foo2 as .illegal. = foo1
             [clinic start generated code]*/
         """
-        err = "Illegal C basename: '.illegal. = foo1'"
+        err = "Illegal C basename: '.illegal.'"
         self.expect_failure(block, err, lineno=7)
 
 
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index 6ff2622d33b38..9f7c47430772f 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -1674,18 +1674,8 @@ def render_function(
         full_name = f.full_name
         template_dict = {'full_name': full_name}
         template_dict['name'] = f.displayname
-
-        if f.c_basename:
-            c_basename = f.c_basename
-        else:
-            fields = full_name.split(".")
-            if fields[-1] == '__new__':
-                fields.pop()
-            c_basename = "_".join(fields)
-
-        template_dict['c_basename'] = c_basename
-
-        template_dict['methoddef_name'] = c_basename.upper() + "_METHODDEF"
+        template_dict['c_basename'] = f.c_basename
+        template_dict['methoddef_name'] = f.c_basename.upper() + "_METHODDEF"
 
         template_dict['docstring'] = self.docstring_for_c_string(f)
 
@@ -2653,7 +2643,7 @@ class Function:
     name: str
     module: Module | Clinic
     cls: Class | None
-    c_basename: str | None
+    c_basename: str
     full_name: str
     return_converter: CReturnConverter
     kind: FunctionKind
@@ -4577,6 +4567,11 @@ class ParamState(enum.IntEnum):
     RIGHT_SQUARE_AFTER = 6
 
 
+class FunctionNames(NamedTuple):
+    full_name: str
+    c_basename: str
+
+
 class DSLParser:
     function: Function | None
     state: StateKeeper
@@ -4840,6 +4835,24 @@ def state_dsl_start(self, line: str) -> None:
 
         self.next(self.state_modulename_name, line)
 
+    @staticmethod
+    def parse_function_names(line: str) -> FunctionNames:
+        left, as_, right = line.partition(' as ')
+        full_name = left.strip()
+        c_basename = right.strip()
+        if as_ and not c_basename:
+            fail("No C basename provided after 'as' keyword")
+        if not c_basename:
+            fields = full_name.split(".")
+            if fields[-1] == '__new__':
+                fields.pop()
+            c_basename = "_".join(fields)
+        if not is_legal_py_identifier(full_name):
+            fail(f"Illegal function name: {full_name!r}")
+        if not is_legal_c_identifier(c_basename):
+            fail(f"Illegal C basename: {c_basename!r}")
+        return FunctionNames(full_name=full_name, c_basename=c_basename)
+
     def update_function_kind(self, fullname: str) -> None:
         fields = fullname.split('.')
         name = fields.pop()
@@ -4877,17 +4890,10 @@ def state_modulename_name(self, line: str) -> None:
 
         # are we cloning?
         before, equals, existing = line.rpartition('=')
-        c_basename: str | None
         if equals:
-            full_name, as_, c_basename = before.partition(' as ')
-            full_name = full_name.strip()
-            c_basename = c_basename.strip()
-            if as_ and not c_basename:
-                fail("No C basename provided after 'as' keyword")
+            full_name, c_basename = self.parse_function_names(before)
             existing = existing.strip()
-            if (is_legal_py_identifier(full_name) and
-                (not c_basename or is_legal_c_identifier(c_basename)) and
-                is_legal_py_identifier(existing)):
+            if is_legal_py_identifier(existing):
                 # we're cloning!
                 fields = [x.strip() for x in existing.split('.')]
                 function_name = fields.pop()
@@ -4933,16 +4939,7 @@ def state_modulename_name(self, line: str) -> None:
 
         line, _, returns = line.partition('->')
         returns = returns.strip()
-
-        full_name, as_, c_basename = line.partition(' as ')
-        full_name = full_name.strip()
-        c_basename = c_basename.strip() or None
-        if as_ and not c_basename:
-            fail("No C basename provided after 'as' keyword")
-        if not is_legal_py_identifier(full_name):
-            fail(f"Illegal function name: {full_name!r}")
-        if c_basename and not is_legal_c_identifier(c_basename):
-            fail(f"Illegal C basename: {c_basename!r}")
+        full_name, c_basename = self.parse_function_names(line)
 
         return_converter = None
         if returns:



More information about the Python-checkins mailing list