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

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
Erlend E. Aasland 2023-08-16 15:47:15 +02:00 committed by GitHub
parent b61f5995ae
commit 42429d3b9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 33 deletions

View file

@ -682,7 +682,7 @@ class ClinicWholeFileTest(TestCase):
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)

View file

@ -1674,18 +1674,8 @@ class CLanguage(Language):
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 @@ class DSLParser:
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 @@ class DSLParser:
# 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 @@ class DSLParser:
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: