mirror of https://github.com/python/cpython
gh-113317: Argument Clinic: move C/Py identifier helpers into libclinic (#115520)
This commit is contained in:
parent
20eaf4d5df
commit
351c103134
|
@ -138,31 +138,6 @@ def fail(
|
||||||
warn_or_fail(*args, filename=filename, line_number=line_number, fail=True)
|
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:
|
class CRenderData:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
|
||||||
|
@ -2954,7 +2929,7 @@ class CConverter(metaclass=CConverterAutoRegister):
|
||||||
unused: bool = False,
|
unused: bool = False,
|
||||||
**kwargs: Any
|
**kwargs: Any
|
||||||
) -> None:
|
) -> None:
|
||||||
self.name = ensure_legal_c_identifier(name)
|
self.name = libclinic.ensure_legal_c_identifier(name)
|
||||||
self.py_name = py_name
|
self.py_name = py_name
|
||||||
self.unused = unused
|
self.unused = unused
|
||||||
self.includes: list[Include] = []
|
self.includes: list[Include] = []
|
||||||
|
@ -5083,9 +5058,9 @@ class DSLParser:
|
||||||
if fields[-1] == '__new__':
|
if fields[-1] == '__new__':
|
||||||
fields.pop()
|
fields.pop()
|
||||||
c_basename = "_".join(fields)
|
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}")
|
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}")
|
fail(f"Illegal C basename: {c_basename!r}")
|
||||||
names = FunctionNames(full_name=full_name, c_basename=c_basename)
|
names = FunctionNames(full_name=full_name, c_basename=c_basename)
|
||||||
self.normalize_function_kind(names.full_name)
|
self.normalize_function_kind(names.full_name)
|
||||||
|
@ -5207,7 +5182,7 @@ class DSLParser:
|
||||||
before, equals, existing = line.rpartition('=')
|
before, equals, existing = line.rpartition('=')
|
||||||
if equals:
|
if equals:
|
||||||
existing = existing.strip()
|
existing = existing.strip()
|
||||||
if is_legal_py_identifier(existing):
|
if libclinic.is_legal_py_identifier(existing):
|
||||||
# we're cloning!
|
# we're cloning!
|
||||||
names = self.parse_function_names(before)
|
names = self.parse_function_names(before)
|
||||||
return self.parse_cloned_function(names, existing)
|
return self.parse_cloned_function(names, existing)
|
||||||
|
|
|
@ -16,6 +16,11 @@ from .formatting import (
|
||||||
wrap_declarations,
|
wrap_declarations,
|
||||||
wrapped_c_string_literal,
|
wrapped_c_string_literal,
|
||||||
)
|
)
|
||||||
|
from .identifiers import (
|
||||||
|
ensure_legal_c_identifier,
|
||||||
|
is_legal_c_identifier,
|
||||||
|
is_legal_py_identifier,
|
||||||
|
)
|
||||||
from .utils import (
|
from .utils import (
|
||||||
FormatCounterFormatter,
|
FormatCounterFormatter,
|
||||||
compute_checksum,
|
compute_checksum,
|
||||||
|
@ -41,6 +46,11 @@ __all__ = [
|
||||||
"wrap_declarations",
|
"wrap_declarations",
|
||||||
"wrapped_c_string_literal",
|
"wrapped_c_string_literal",
|
||||||
|
|
||||||
|
# Identifier helpers
|
||||||
|
"ensure_legal_c_identifier",
|
||||||
|
"is_legal_c_identifier",
|
||||||
|
"is_legal_py_identifier",
|
||||||
|
|
||||||
# Utility functions
|
# Utility functions
|
||||||
"FormatCounterFormatter",
|
"FormatCounterFormatter",
|
||||||
"compute_checksum",
|
"compute_checksum",
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue