Skip to content

Commit e90036c

Browse files
gh-107880: Argument Clinic: Fix regression in gh-107885 (#107974)
Co-authored-by: Alex Waygood <[email protected]>
1 parent 6515ec3 commit e90036c

File tree

2 files changed

+51
-17
lines changed

2 files changed

+51
-17
lines changed

Lib/test/test_clinic.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,35 @@ def test_directive_output_invalid_command(self):
609609
"""
610610
self.expect_failure(block, err, lineno=2)
611611

612+
def test_validate_cloned_init(self):
613+
block = """
614+
/*[clinic input]
615+
class C "void *" ""
616+
C.meth
617+
a: int
618+
[clinic start generated code]*/
619+
/*[clinic input]
620+
@classmethod
621+
C.__init__ = C.meth
622+
[clinic start generated code]*/
623+
"""
624+
err = "'__init__' must be a normal method, not a class or static method"
625+
self.expect_failure(block, err, lineno=8)
626+
627+
def test_validate_cloned_new(self):
628+
block = """
629+
/*[clinic input]
630+
class C "void *" ""
631+
C.meth
632+
a: int
633+
[clinic start generated code]*/
634+
/*[clinic input]
635+
C.__new__ = C.meth
636+
[clinic start generated code]*/
637+
"""
638+
err = "'__new__' must be a class method"
639+
self.expect_failure(block, err, lineno=7)
640+
612641

613642
class ParseFileUnitTest(TestCase):
614643
def expect_parsing_failure(
@@ -1918,7 +1947,7 @@ class Foo "" ""
19181947
self.parse_function(block)
19191948

19201949
def test_new_must_be_a_class_method(self):
1921-
err = "__new__ must be a class method!"
1950+
err = "'__new__' must be a class method!"
19221951
block = """
19231952
module foo
19241953
class Foo "" ""
@@ -1927,7 +1956,7 @@ class Foo "" ""
19271956
self.expect_failure(block, err, lineno=2)
19281957

19291958
def test_init_must_be_a_normal_method(self):
1930-
err = "__init__ must be a normal method, not a class or static method!"
1959+
err = "'__init__' must be a normal method, not a class or static method!"
19311960
block = """
19321961
module foo
19331962
class Foo "" ""
@@ -2030,7 +2059,7 @@ def test_illegal_c_identifier(self):
20302059
self.expect_failure(block, err, lineno=2)
20312060

20322061
def test_cannot_convert_special_method(self):
2033-
err = "__len__ is a special method and cannot be converted"
2062+
err = "'__len__' is a special method and cannot be converted"
20342063
block = """
20352064
class T "" ""
20362065
T.__len__

Tools/clinic/clinic.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4840,6 +4840,21 @@ def state_dsl_start(self, line: str) -> None:
48404840

48414841
self.next(self.state_modulename_name, line)
48424842

4843+
def update_function_kind(self, fullname: str) -> None:
4844+
fields = fullname.split('.')
4845+
name = fields.pop()
4846+
_, cls = self.clinic._module_and_class(fields)
4847+
if name in unsupported_special_methods:
4848+
fail(f"{name!r} is a special method and cannot be converted to Argument Clinic!")
4849+
if name == '__new__':
4850+
if (self.kind is not CLASS_METHOD) or (not cls):
4851+
fail("'__new__' must be a class method!")
4852+
self.kind = METHOD_NEW
4853+
elif name == '__init__':
4854+
if (self.kind is not CALLABLE) or (not cls):
4855+
fail("'__init__' must be a normal method, not a class or static method!")
4856+
self.kind = METHOD_INIT
4857+
48434858
def state_modulename_name(self, line: str) -> None:
48444859
# looking for declaration, which establishes the leftmost column
48454860
# line should be
@@ -4888,6 +4903,7 @@ def state_modulename_name(self, line: str) -> None:
48884903
function_name = fields.pop()
48894904
module, cls = self.clinic._module_and_class(fields)
48904905

4906+
self.update_function_kind(full_name)
48914907
overrides: dict[str, Any] = {
48924908
"name": function_name,
48934909
"full_name": full_name,
@@ -4948,20 +4964,9 @@ def state_modulename_name(self, line: str) -> None:
49484964
function_name = fields.pop()
49494965
module, cls = self.clinic._module_and_class(fields)
49504966

4951-
fields = full_name.split('.')
4952-
if fields[-1] in unsupported_special_methods:
4953-
fail(f"{fields[-1]} is a special method and cannot be converted to Argument Clinic! (Yet.)")
4954-
4955-
if fields[-1] == '__new__':
4956-
if (self.kind is not CLASS_METHOD) or (not cls):
4957-
fail("__new__ must be a class method!")
4958-
self.kind = METHOD_NEW
4959-
elif fields[-1] == '__init__':
4960-
if (self.kind is not CALLABLE) or (not cls):
4961-
fail("__init__ must be a normal method, not a class or static method!")
4962-
self.kind = METHOD_INIT
4963-
if not return_converter:
4964-
return_converter = init_return_converter()
4967+
self.update_function_kind(full_name)
4968+
if self.kind is METHOD_INIT and not return_converter:
4969+
return_converter = init_return_converter()
49654970

49664971
if not return_converter:
49674972
return_converter = CReturnConverter()

0 commit comments

Comments
 (0)