]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-113317: Argument Clinic: move C/Py identifier helpers into libclinic (#115520)
authorErlend E. Aasland <erlend@python.org>
Fri, 16 Feb 2024 06:42:15 +0000 (07:42 +0100)
committerGitHub <noreply@github.com>
Fri, 16 Feb 2024 06:42:15 +0000 (07:42 +0100)
Tools/clinic/clinic.py
Tools/clinic/libclinic/__init__.py
Tools/clinic/libclinic/identifiers.py [new file with mode: 0644]

index 4925f27b2937b195bd07aef680e6911da0e0189b..5d2617b3bd579fce56aa551333b9cea7e67246ac 100755 (executable)
@@ -138,31 +138,6 @@ def fail(
     warn_or_fail(*args, filename=filename, line_number=line_number, fail=True)
 
 
-is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
-
-def is_legal_py_identifier(s: str) -> bool:
-    return all(is_legal_c_identifier(field) for field in s.split('.'))
-
-# identifiers that are okay in Python but aren't a good idea in C.
-# so if they're used Argument Clinic will add "_value" to the end
-# of the name in C.
-c_keywords = set("""
-asm auto break case char const continue default do double
-else enum extern float for goto if inline int long
-register return short signed sizeof static struct switch
-typedef typeof union unsigned void volatile while
-""".strip().split())
-
-def ensure_legal_c_identifier(s: str) -> str:
-    # for now, just complain if what we're given isn't legal
-    if not is_legal_c_identifier(s):
-        fail("Illegal C identifier:", s)
-    # but if we picked a C keyword, pick something else
-    if s in c_keywords:
-        return s + "_value"
-    return s
-
-
 class CRenderData:
     def __init__(self) -> None:
 
@@ -2954,7 +2929,7 @@ class CConverter(metaclass=CConverterAutoRegister):
              unused: bool = False,
              **kwargs: Any
     ) -> None:
-        self.name = ensure_legal_c_identifier(name)
+        self.name = libclinic.ensure_legal_c_identifier(name)
         self.py_name = py_name
         self.unused = unused
         self.includes: list[Include] = []
@@ -5083,9 +5058,9 @@ class DSLParser:
             if fields[-1] == '__new__':
                 fields.pop()
             c_basename = "_".join(fields)
-        if not is_legal_py_identifier(full_name):
+        if not libclinic.is_legal_py_identifier(full_name):
             fail(f"Illegal function name: {full_name!r}")
-        if not is_legal_c_identifier(c_basename):
+        if not libclinic.is_legal_c_identifier(c_basename):
             fail(f"Illegal C basename: {c_basename!r}")
         names = FunctionNames(full_name=full_name, c_basename=c_basename)
         self.normalize_function_kind(names.full_name)
@@ -5207,7 +5182,7 @@ class DSLParser:
         before, equals, existing = line.rpartition('=')
         if equals:
             existing = existing.strip()
-            if is_legal_py_identifier(existing):
+            if libclinic.is_legal_py_identifier(existing):
                 # we're cloning!
                 names = self.parse_function_names(before)
                 return self.parse_cloned_function(names, existing)
index 6237809764d9e1f67ee9cbb25e231dbe6ec00a52..738864a48c08d3f7e901739353073fba86e5bd9d 100644 (file)
@@ -16,6 +16,11 @@ from .formatting import (
     wrap_declarations,
     wrapped_c_string_literal,
 )
+from .identifiers import (
+    ensure_legal_c_identifier,
+    is_legal_c_identifier,
+    is_legal_py_identifier,
+)
 from .utils import (
     FormatCounterFormatter,
     compute_checksum,
@@ -41,6 +46,11 @@ __all__ = [
     "wrap_declarations",
     "wrapped_c_string_literal",
 
+    # Identifier helpers
+    "ensure_legal_c_identifier",
+    "is_legal_c_identifier",
+    "is_legal_py_identifier",
+
     # Utility functions
     "FormatCounterFormatter",
     "compute_checksum",
diff --git a/Tools/clinic/libclinic/identifiers.py b/Tools/clinic/libclinic/identifiers.py
new file mode 100644 (file)
index 0000000..d3b80bb
--- /dev/null
@@ -0,0 +1,31 @@
+import re
+from .errors import ClinicError
+
+
+is_legal_c_identifier = re.compile("^[A-Za-z_][A-Za-z0-9_]*$").match
+
+
+def is_legal_py_identifier(identifier: str) -> bool:
+    return all(is_legal_c_identifier(field) for field in identifier.split("."))
+
+
+# Identifiers that are okay in Python but aren't a good idea in C.
+# So if they're used Argument Clinic will add "_value" to the end
+# of the name in C.
+_c_keywords = frozenset("""
+asm auto break case char const continue default do double
+else enum extern float for goto if inline int long
+register return short signed sizeof static struct switch
+typedef typeof union unsigned void volatile while
+""".strip().split()
+)
+
+
+def ensure_legal_c_identifier(identifier: str) -> str:
+    # For now, just complain if what we're given isn't legal.
+    if not is_legal_c_identifier(identifier):
+        raise ClinicError(f"Illegal C identifier: {identifier}")
+    # But if we picked a C keyword, pick something else.
+    if identifier in _c_keywords:
+        return identifier + "_value"
+    return identifier