Skip to content

gh-104683: Argument Clinic: Extract parse_function_names() helper #107964

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
2 changes: 1 addition & 1 deletion Lib/test/test_clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
61 changes: 29 additions & 32 deletions Tools/clinic/clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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:
Expand Down