mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-107880: Argument Clinic: Fix regression in gh-107885 (#107974)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
6515ec3d3d
commit
e90036c9bd
2 changed files with 51 additions and 17 deletions
|
@ -609,6 +609,35 @@ class ClinicWholeFileTest(TestCase):
|
||||||
"""
|
"""
|
||||||
self.expect_failure(block, err, lineno=2)
|
self.expect_failure(block, err, lineno=2)
|
||||||
|
|
||||||
|
def test_validate_cloned_init(self):
|
||||||
|
block = """
|
||||||
|
/*[clinic input]
|
||||||
|
class C "void *" ""
|
||||||
|
C.meth
|
||||||
|
a: int
|
||||||
|
[clinic start generated code]*/
|
||||||
|
/*[clinic input]
|
||||||
|
@classmethod
|
||||||
|
C.__init__ = C.meth
|
||||||
|
[clinic start generated code]*/
|
||||||
|
"""
|
||||||
|
err = "'__init__' must be a normal method, not a class or static method"
|
||||||
|
self.expect_failure(block, err, lineno=8)
|
||||||
|
|
||||||
|
def test_validate_cloned_new(self):
|
||||||
|
block = """
|
||||||
|
/*[clinic input]
|
||||||
|
class C "void *" ""
|
||||||
|
C.meth
|
||||||
|
a: int
|
||||||
|
[clinic start generated code]*/
|
||||||
|
/*[clinic input]
|
||||||
|
C.__new__ = C.meth
|
||||||
|
[clinic start generated code]*/
|
||||||
|
"""
|
||||||
|
err = "'__new__' must be a class method"
|
||||||
|
self.expect_failure(block, err, lineno=7)
|
||||||
|
|
||||||
|
|
||||||
class ParseFileUnitTest(TestCase):
|
class ParseFileUnitTest(TestCase):
|
||||||
def expect_parsing_failure(
|
def expect_parsing_failure(
|
||||||
|
@ -1918,7 +1947,7 @@ class ClinicParserTest(TestCase):
|
||||||
self.parse_function(block)
|
self.parse_function(block)
|
||||||
|
|
||||||
def test_new_must_be_a_class_method(self):
|
def test_new_must_be_a_class_method(self):
|
||||||
err = "__new__ must be a class method!"
|
err = "'__new__' must be a class method!"
|
||||||
block = """
|
block = """
|
||||||
module foo
|
module foo
|
||||||
class Foo "" ""
|
class Foo "" ""
|
||||||
|
@ -1927,7 +1956,7 @@ class ClinicParserTest(TestCase):
|
||||||
self.expect_failure(block, err, lineno=2)
|
self.expect_failure(block, err, lineno=2)
|
||||||
|
|
||||||
def test_init_must_be_a_normal_method(self):
|
def test_init_must_be_a_normal_method(self):
|
||||||
err = "__init__ must be a normal method, not a class or static method!"
|
err = "'__init__' must be a normal method, not a class or static method!"
|
||||||
block = """
|
block = """
|
||||||
module foo
|
module foo
|
||||||
class Foo "" ""
|
class Foo "" ""
|
||||||
|
@ -2030,7 +2059,7 @@ class ClinicParserTest(TestCase):
|
||||||
self.expect_failure(block, err, lineno=2)
|
self.expect_failure(block, err, lineno=2)
|
||||||
|
|
||||||
def test_cannot_convert_special_method(self):
|
def test_cannot_convert_special_method(self):
|
||||||
err = "__len__ is a special method and cannot be converted"
|
err = "'__len__' is a special method and cannot be converted"
|
||||||
block = """
|
block = """
|
||||||
class T "" ""
|
class T "" ""
|
||||||
T.__len__
|
T.__len__
|
||||||
|
|
|
@ -4840,6 +4840,21 @@ class DSLParser:
|
||||||
|
|
||||||
self.next(self.state_modulename_name, line)
|
self.next(self.state_modulename_name, line)
|
||||||
|
|
||||||
|
def update_function_kind(self, fullname: str) -> None:
|
||||||
|
fields = fullname.split('.')
|
||||||
|
name = fields.pop()
|
||||||
|
_, cls = self.clinic._module_and_class(fields)
|
||||||
|
if name in unsupported_special_methods:
|
||||||
|
fail(f"{name!r} is a special method and cannot be converted to Argument Clinic!")
|
||||||
|
if name == '__new__':
|
||||||
|
if (self.kind is not CLASS_METHOD) or (not cls):
|
||||||
|
fail("'__new__' must be a class method!")
|
||||||
|
self.kind = METHOD_NEW
|
||||||
|
elif name == '__init__':
|
||||||
|
if (self.kind is not CALLABLE) or (not cls):
|
||||||
|
fail("'__init__' must be a normal method, not a class or static method!")
|
||||||
|
self.kind = METHOD_INIT
|
||||||
|
|
||||||
def state_modulename_name(self, line: str) -> None:
|
def state_modulename_name(self, line: str) -> None:
|
||||||
# looking for declaration, which establishes the leftmost column
|
# looking for declaration, which establishes the leftmost column
|
||||||
# line should be
|
# line should be
|
||||||
|
@ -4888,6 +4903,7 @@ class DSLParser:
|
||||||
function_name = fields.pop()
|
function_name = fields.pop()
|
||||||
module, cls = self.clinic._module_and_class(fields)
|
module, cls = self.clinic._module_and_class(fields)
|
||||||
|
|
||||||
|
self.update_function_kind(full_name)
|
||||||
overrides: dict[str, Any] = {
|
overrides: dict[str, Any] = {
|
||||||
"name": function_name,
|
"name": function_name,
|
||||||
"full_name": full_name,
|
"full_name": full_name,
|
||||||
|
@ -4948,19 +4964,8 @@ class DSLParser:
|
||||||
function_name = fields.pop()
|
function_name = fields.pop()
|
||||||
module, cls = self.clinic._module_and_class(fields)
|
module, cls = self.clinic._module_and_class(fields)
|
||||||
|
|
||||||
fields = full_name.split('.')
|
self.update_function_kind(full_name)
|
||||||
if fields[-1] in unsupported_special_methods:
|
if self.kind is METHOD_INIT and not return_converter:
|
||||||
fail(f"{fields[-1]} is a special method and cannot be converted to Argument Clinic! (Yet.)")
|
|
||||||
|
|
||||||
if fields[-1] == '__new__':
|
|
||||||
if (self.kind is not CLASS_METHOD) or (not cls):
|
|
||||||
fail("__new__ must be a class method!")
|
|
||||||
self.kind = METHOD_NEW
|
|
||||||
elif fields[-1] == '__init__':
|
|
||||||
if (self.kind is not CALLABLE) or (not cls):
|
|
||||||
fail("__init__ must be a normal method, not a class or static method!")
|
|
||||||
self.kind = METHOD_INIT
|
|
||||||
if not return_converter:
|
|
||||||
return_converter = init_return_converter()
|
return_converter = init_return_converter()
|
||||||
|
|
||||||
if not return_converter:
|
if not return_converter:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue