Skip to content

Commit 607f18c

Browse files
gh-107972: Argument Clinic: Ensure a C basename is provided after 'as' (#107973)
Co-authored-by: Adam Turner <[email protected]>
1 parent e90036c commit 607f18c

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

Lib/test/test_clinic.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ def _make_clinic(*, filename='clinic_tests'):
2828
return c
2929

3030

31-
def _expect_failure(tc, parser, code, errmsg, *, filename=None, lineno=None):
31+
def _expect_failure(tc, parser, code, errmsg, *, filename=None, lineno=None,
32+
strip=True):
3233
"""Helper for the parser tests.
3334
3435
tc: unittest.TestCase; passed self in the wrapper
@@ -38,7 +39,9 @@ def _expect_failure(tc, parser, code, errmsg, *, filename=None, lineno=None):
3839
filename: str, optional filename
3940
lineno: int, optional line number
4041
"""
41-
code = dedent(code).strip()
42+
code = dedent(code)
43+
if strip:
44+
code = code.strip()
4245
errmsg = re.escape(errmsg)
4346
with tc.assertRaisesRegex(clinic.ClinicError, errmsg) as cm:
4447
parser(code)
@@ -638,6 +641,19 @@ class C "void *" ""
638641
err = "'__new__' must be a class method"
639642
self.expect_failure(block, err, lineno=7)
640643

644+
def test_no_c_basename_cloned(self):
645+
block = """
646+
/*[clinic input]
647+
foo2
648+
[clinic start generated code]*/
649+
/*[clinic input]
650+
foo as = foo2
651+
[clinic start generated code]*/
652+
"""
653+
err = "No C basename provided after 'as' keyword"
654+
self.expect_failure(block, err, lineno=5)
655+
656+
641657

642658
class ParseFileUnitTest(TestCase):
643659
def expect_parsing_failure(
@@ -857,9 +873,10 @@ def parse_function(self, text, signatures_in_block=2, function_index=1):
857873
assert isinstance(s[function_index], clinic.Function)
858874
return s[function_index]
859875

860-
def expect_failure(self, block, err, *, filename=None, lineno=None):
876+
def expect_failure(self, block, err, *,
877+
filename=None, lineno=None, strip=True):
861878
return _expect_failure(self, self.parse_function, block, err,
862-
filename=filename, lineno=lineno)
879+
filename=filename, lineno=lineno, strip=strip)
863880

864881
def checkDocstring(self, fn, expected):
865882
self.assertTrue(hasattr(fn, "docstring"))
@@ -1520,6 +1537,11 @@ def test_illegal_c_basename(self):
15201537
err = "Illegal C basename: '935'"
15211538
self.expect_failure(block, err)
15221539

1540+
def test_no_c_basename(self):
1541+
block = "foo as "
1542+
err = "No C basename provided after 'as' keyword"
1543+
self.expect_failure(block, err, strip=False)
1544+
15231545
def test_single_star(self):
15241546
block = """
15251547
module foo

Tools/clinic/clinic.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4879,9 +4879,11 @@ def state_modulename_name(self, line: str) -> None:
48794879
before, equals, existing = line.rpartition('=')
48804880
c_basename: str | None
48814881
if equals:
4882-
full_name, _, c_basename = before.partition(' as ')
4882+
full_name, as_, c_basename = before.partition(' as ')
48834883
full_name = full_name.strip()
48844884
c_basename = c_basename.strip()
4885+
if as_ and not c_basename:
4886+
fail("No C basename provided after 'as' keyword")
48854887
existing = existing.strip()
48864888
if (is_legal_py_identifier(full_name) and
48874889
(not c_basename or is_legal_c_identifier(c_basename)) and
@@ -4932,10 +4934,11 @@ def state_modulename_name(self, line: str) -> None:
49324934
line, _, returns = line.partition('->')
49334935
returns = returns.strip()
49344936

4935-
full_name, _, c_basename = line.partition(' as ')
4937+
full_name, as_, c_basename = line.partition(' as ')
49364938
full_name = full_name.strip()
49374939
c_basename = c_basename.strip() or None
4938-
4940+
if as_ and not c_basename:
4941+
fail("No C basename provided after 'as' keyword")
49394942
if not is_legal_py_identifier(full_name):
49404943
fail(f"Illegal function name: {full_name!r}")
49414944
if c_basename and not is_legal_c_identifier(c_basename):

0 commit comments

Comments
 (0)