From d51d80489e4c105c0d92362dcf2fe97cc0818c5f Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Sat, 10 Jun 2023 22:30:38 +0900 Subject: [PATCH 01/10] Ignore cached_property in method-hidden check (#8753) --- pylint/checkers/classes/class_checker.py | 10 +++++++++- tests/functional/m/method_hidden.py | 7 +++++++ tests/functional/m/method_hidden.txt | 6 +++--- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index bdfb0968a4..cb6cffcbba 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -49,6 +49,7 @@ _AccessNodes = Union[nodes.Attribute, nodes.AssignAttr] INVALID_BASE_CLASSES = {"bool", "range", "slice", "memoryview"} +ALLOWED_PROPETIES = {"property", "cached_property"} BUILTIN_DECORATORS = {"builtins.property", "builtins.classmethod"} ASTROID_TYPE_COMPARATORS = { nodes.Const: lambda a, b: a.value == b.value, @@ -1252,11 +1253,18 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: # attribute affectation will call this method, not hiding it return if isinstance(decorator, nodes.Name): - if decorator.name == "property": + if decorator.name in ALLOWED_PROPETIES: # attribute affectation will either call a setter or raise # an attribute error, anyway not hiding the function return + if ( + isinstance(decorator, nodes.Attribute) + and decorator.expr.name == "functools" + and decorator.attrname == "cached_property" + ): + return + # Infer the decorator and see if it returns something useful inferred = safe_infer(decorator) if not inferred: diff --git a/tests/functional/m/method_hidden.py b/tests/functional/m/method_hidden.py index ea94b3ca26..6adb80b624 100644 --- a/tests/functional/m/method_hidden.py +++ b/tests/functional/m/method_hidden.py @@ -2,6 +2,7 @@ # pylint: disable=unused-private-member """check method hiding ancestor attribute """ +import functools class Abcd: @@ -113,6 +114,12 @@ def _protected(self): # [method-hidden] pass +class CachedChild(Parent): + @functools.cached_property + def _protected(self): + pass + + class ParentTwo: def __init__(self): self.__private = None diff --git a/tests/functional/m/method_hidden.txt b/tests/functional/m/method_hidden.txt index abce3cd407..23651bd4a0 100644 --- a/tests/functional/m/method_hidden.txt +++ b/tests/functional/m/method_hidden.txt @@ -1,3 +1,3 @@ -method-hidden:17:4:17:12:Cdef.abcd:An attribute defined in functional.m.method_hidden line 11 hides this method:UNDEFINED -method-hidden:85:4:85:11:One.one:An attribute defined in functional.m.method_hidden line 83 hides this method:UNDEFINED -method-hidden:112:4:112:18:Child._protected:An attribute defined in functional.m.method_hidden line 108 hides this method:UNDEFINED +method-hidden:18:4:18:12:Cdef.abcd:An attribute defined in functional.m.method_hidden line 12 hides this method:UNDEFINED +method-hidden:86:4:86:11:One.one:An attribute defined in functional.m.method_hidden line 84 hides this method:UNDEFINED +method-hidden:113:4:113:18:Child._protected:An attribute defined in functional.m.method_hidden line 109 hides this method:UNDEFINED From d273883ca94d2719ac7b2c8baa9ac813e63df167 Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Sun, 11 Jun 2023 12:17:24 +0900 Subject: [PATCH 02/10] check if decorator.expr is nodes.Name --- pylint/checkers/classes/class_checker.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index cb6cffcbba..a1ac19affc 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -1260,8 +1260,9 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: if ( isinstance(decorator, nodes.Attribute) - and decorator.expr.name == "functools" and decorator.attrname == "cached_property" + and isinstance(decorator.expr, nodes.Name) + and decorator.expr.name == "functools" ): return From f982d3d15656cca6d739c0773370e8fe289cacdf Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Sun, 11 Jun 2023 22:19:12 +0900 Subject: [PATCH 03/10] Change the import method during testing for operation confirmation --- tests/functional/m/method_hidden.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/functional/m/method_hidden.py b/tests/functional/m/method_hidden.py index 6adb80b624..ed9d7bb43a 100644 --- a/tests/functional/m/method_hidden.py +++ b/tests/functional/m/method_hidden.py @@ -1,8 +1,10 @@ # pylint: disable=too-few-public-methods,missing-docstring # pylint: disable=unused-private-member +# pylint: disable=import-error """check method hiding ancestor attribute """ -import functools +import functools as ft +import something_else as functools class Abcd: @@ -115,10 +117,14 @@ def _protected(self): # [method-hidden] class CachedChild(Parent): - @functools.cached_property + @ft.cached_property def _protected(self): pass + @functools.cached_property + def _protected_two(self): # [method-hidden] + pass + class ParentTwo: def __init__(self): From 8d62ba0a0b55f24d010082b8e8f484ab7d816f37 Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Sun, 11 Jun 2023 22:57:05 +0900 Subject: [PATCH 04/10] Check module name using lookup method --- pylint/checkers/classes/class_checker.py | 28 ++++++++++++++++++------ tests/functional/m/method_hidden.py | 3 ++- tests/functional/m/method_hidden.txt | 6 ++--- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index a1ac19affc..12e2040c6a 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -1258,13 +1258,9 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: # an attribute error, anyway not hiding the function return - if ( - isinstance(decorator, nodes.Attribute) - and decorator.attrname == "cached_property" - and isinstance(decorator.expr, nodes.Name) - and decorator.expr.name == "functools" - ): - return + if isinstance(decorator, nodes.Attribute): + if self._check_functools_or_not(decorator): + return # Infer the decorator and see if it returns something useful inferred = safe_infer(decorator) @@ -1463,6 +1459,24 @@ def _check_invalid_overridden_method( node=function_node, ) + def _check_functools_or_not(self, decorator: nodes.Attribute) -> bool: + if decorator.attrname != "cached_property": + return False + + if not isinstance(decorator.expr, nodes.Name): + return False + + _, import_nodes = decorator.expr.lookup(decorator.expr.name) + + if not import_nodes: + return False + import_node = import_nodes[0] + + if not isinstance(import_node, (astroid.Import, astroid.ImportFrom)): + return False + + return "functools" in dict(import_node.names) + def _check_slots(self, node: nodes.ClassDef) -> None: if "__slots__" not in node.locals: return diff --git a/tests/functional/m/method_hidden.py b/tests/functional/m/method_hidden.py index ed9d7bb43a..f49737d3d7 100644 --- a/tests/functional/m/method_hidden.py +++ b/tests/functional/m/method_hidden.py @@ -109,6 +109,7 @@ def default(self, o): class Parent: def __init__(self): self._protected = None + self._protected_two = None class Child(Parent): @@ -122,7 +123,7 @@ def _protected(self): pass @functools.cached_property - def _protected_two(self): # [method-hidden] + def _protected_two(self): pass diff --git a/tests/functional/m/method_hidden.txt b/tests/functional/m/method_hidden.txt index 23651bd4a0..e099b791db 100644 --- a/tests/functional/m/method_hidden.txt +++ b/tests/functional/m/method_hidden.txt @@ -1,3 +1,3 @@ -method-hidden:18:4:18:12:Cdef.abcd:An attribute defined in functional.m.method_hidden line 12 hides this method:UNDEFINED -method-hidden:86:4:86:11:One.one:An attribute defined in functional.m.method_hidden line 84 hides this method:UNDEFINED -method-hidden:113:4:113:18:Child._protected:An attribute defined in functional.m.method_hidden line 109 hides this method:UNDEFINED +method-hidden:20:4:20:12:Cdef.abcd:An attribute defined in functional.m.method_hidden line 14 hides this method:UNDEFINED +method-hidden:88:4:88:11:One.one:An attribute defined in functional.m.method_hidden line 86 hides this method:UNDEFINED +method-hidden:116:4:116:18:Child._protected:An attribute defined in functional.m.method_hidden line 111 hides this method:UNDEFINED From 0576db8e0438243e295ca10ba2a272e1592e2b6f Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Tue, 13 Jun 2023 21:02:13 +0900 Subject: [PATCH 05/10] Fix variable names and use qname Co-authored-by: Pierre Sassoulas --- pylint/checkers/classes/class_checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index 12e2040c6a..9ffb1655a0 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -49,7 +49,7 @@ _AccessNodes = Union[nodes.Attribute, nodes.AssignAttr] INVALID_BASE_CLASSES = {"bool", "range", "slice", "memoryview"} -ALLOWED_PROPETIES = {"property", "cached_property"} +ALLOWED_PROPERTIES = {"bultins.property", "functools.cached_property"} BUILTIN_DECORATORS = {"builtins.property", "builtins.classmethod"} ASTROID_TYPE_COMPARATORS = { nodes.Const: lambda a, b: a.value == b.value, From ac28e033da723e6e31ef9f582ac30fd3e8cf68c0 Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Tue, 13 Jun 2023 21:02:47 +0900 Subject: [PATCH 06/10] Fix variable name Co-authored-by: Pierre Sassoulas --- pylint/checkers/classes/class_checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index 9ffb1655a0..377673f4b7 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -1253,7 +1253,7 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: # attribute affectation will call this method, not hiding it return if isinstance(decorator, nodes.Name): - if decorator.name in ALLOWED_PROPETIES: + if decorator.name in ALLOWED_PROPERTIES: # attribute affectation will either call a setter or raise # an attribute error, anyway not hiding the function return From a3827965c6e1461f5c0859a4da55cafb6f26666e Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Tue, 13 Jun 2023 21:39:30 +0900 Subject: [PATCH 07/10] Add test code that satisfies the conditional branch --- tests/functional/m/method_hidden.py | 5 +++++ tests/functional/m/method_hidden.txt | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/functional/m/method_hidden.py b/tests/functional/m/method_hidden.py index f49737d3d7..28231a839d 100644 --- a/tests/functional/m/method_hidden.py +++ b/tests/functional/m/method_hidden.py @@ -110,6 +110,7 @@ class Parent: def __init__(self): self._protected = None self._protected_two = None + self._protected_three = None class Child(Parent): @@ -126,6 +127,10 @@ def _protected(self): def _protected_two(self): pass + @functools().cached_property + def _protected_three(self): + pass + class ParentTwo: def __init__(self): diff --git a/tests/functional/m/method_hidden.txt b/tests/functional/m/method_hidden.txt index e099b791db..dbbb33be28 100644 --- a/tests/functional/m/method_hidden.txt +++ b/tests/functional/m/method_hidden.txt @@ -1,3 +1,3 @@ method-hidden:20:4:20:12:Cdef.abcd:An attribute defined in functional.m.method_hidden line 14 hides this method:UNDEFINED method-hidden:88:4:88:11:One.one:An attribute defined in functional.m.method_hidden line 86 hides this method:UNDEFINED -method-hidden:116:4:116:18:Child._protected:An attribute defined in functional.m.method_hidden line 111 hides this method:UNDEFINED +method-hidden:117:4:117:18:Child._protected:An attribute defined in functional.m.method_hidden line 111 hides this method:UNDEFINED From f57aa29406ef1ceab0575350b9639c0cd79b22ba Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Tue, 13 Jun 2023 21:47:12 +0900 Subject: [PATCH 08/10] add news fragments for issue #8753 --- doc/whatsnew/fragments/8753.bugfix | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/whatsnew/fragments/8753.bugfix diff --git a/doc/whatsnew/fragments/8753.bugfix b/doc/whatsnew/fragments/8753.bugfix new file mode 100644 index 0000000000..7b0ba8cc78 --- /dev/null +++ b/doc/whatsnew/fragments/8753.bugfix @@ -0,0 +1,3 @@ +Fix a false positive for ``method-hidden`` when using ``cached_property`` decorator. + +Closes #8753 From 70615c29f520a45ecd70ae2b6ffa080d73bb5792 Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Fri, 23 Jun 2023 00:11:01 +0900 Subject: [PATCH 09/10] Separate tests for python3.9 above --- tests/functional/m/method_hidden.py | 5 - tests/functional/m/method_hidden.txt | 2 +- tests/functional/m/method_hidden_py39.py | 142 ++++++++++++++++++++++ tests/functional/m/method_hidden_py39.rc | 2 + tests/functional/m/method_hidden_py39.txt | 3 + 5 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 tests/functional/m/method_hidden_py39.py create mode 100644 tests/functional/m/method_hidden_py39.rc create mode 100644 tests/functional/m/method_hidden_py39.txt diff --git a/tests/functional/m/method_hidden.py b/tests/functional/m/method_hidden.py index 28231a839d..f49737d3d7 100644 --- a/tests/functional/m/method_hidden.py +++ b/tests/functional/m/method_hidden.py @@ -110,7 +110,6 @@ class Parent: def __init__(self): self._protected = None self._protected_two = None - self._protected_three = None class Child(Parent): @@ -127,10 +126,6 @@ def _protected(self): def _protected_two(self): pass - @functools().cached_property - def _protected_three(self): - pass - class ParentTwo: def __init__(self): diff --git a/tests/functional/m/method_hidden.txt b/tests/functional/m/method_hidden.txt index dbbb33be28..e099b791db 100644 --- a/tests/functional/m/method_hidden.txt +++ b/tests/functional/m/method_hidden.txt @@ -1,3 +1,3 @@ method-hidden:20:4:20:12:Cdef.abcd:An attribute defined in functional.m.method_hidden line 14 hides this method:UNDEFINED method-hidden:88:4:88:11:One.one:An attribute defined in functional.m.method_hidden line 86 hides this method:UNDEFINED -method-hidden:117:4:117:18:Child._protected:An attribute defined in functional.m.method_hidden line 111 hides this method:UNDEFINED +method-hidden:116:4:116:18:Child._protected:An attribute defined in functional.m.method_hidden line 111 hides this method:UNDEFINED diff --git a/tests/functional/m/method_hidden_py39.py b/tests/functional/m/method_hidden_py39.py new file mode 100644 index 0000000000..28231a839d --- /dev/null +++ b/tests/functional/m/method_hidden_py39.py @@ -0,0 +1,142 @@ +# pylint: disable=too-few-public-methods,missing-docstring +# pylint: disable=unused-private-member +# pylint: disable=import-error +"""check method hiding ancestor attribute +""" +import functools as ft +import something_else as functools + + +class Abcd: + """dummy""" + + def __init__(self): + self.abcd = 1 + + +class Cdef(Abcd): + """dummy""" + + def abcd(self): # [method-hidden] + """test""" + print(self) + + +class AbcdMixin: + def abcd(self): + pass + + +class Dabc(AbcdMixin, Abcd): + def abcd(self): + pass + + +class CustomProperty: + """dummy""" + + def __init__(self, _): + pass + + def __get__(self, obj, __): + if not obj: + return self + return 5 + + def __set__(self, _, __): + pass + + +class Ddef: + """dummy""" + + def __init__(self): + self.five = "five" + + @CustomProperty + def five(self): + """Always 5.""" + return self + + +def my_decorator(*args, **kwargs): + return CustomProperty(*args, **kwargs) + + +class Foo: + def __init__(self): + self._bar = 42 + self._baz = 84 + + @my_decorator + def method(self): # E0202 + return self._baz + + @method.setter + def method(self, value): + self._baz = value + + def do_something_with_baz(self, value): + self.method = value + + +class One: + def __init__(self, one=None): + if one is not None: + self.one = one + + def one(self): # [method-hidden] + pass + + +class Two(One): + def one(self): + pass + + +try: + import unknown as js +except ImportError: + import json as js + + +class JsonEncoder(js.JSONEncoder): + # pylint: disable=useless-super-delegation,super-with-arguments + def default(self, o): + return super(JsonEncoder, self).default(o) + + +class Parent: + def __init__(self): + self._protected = None + self._protected_two = None + self._protected_three = None + + +class Child(Parent): + def _protected(self): # [method-hidden] + pass + + +class CachedChild(Parent): + @ft.cached_property + def _protected(self): + pass + + @functools.cached_property + def _protected_two(self): + pass + + @functools().cached_property + def _protected_three(self): + pass + + +class ParentTwo: + def __init__(self): + self.__private = None + + +class ChildTwo(ParentTwo): + def __private(self): + pass diff --git a/tests/functional/m/method_hidden_py39.rc b/tests/functional/m/method_hidden_py39.rc new file mode 100644 index 0000000000..15ad50f5ab --- /dev/null +++ b/tests/functional/m/method_hidden_py39.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver = 3.9 diff --git a/tests/functional/m/method_hidden_py39.txt b/tests/functional/m/method_hidden_py39.txt new file mode 100644 index 0000000000..ed2572523b --- /dev/null +++ b/tests/functional/m/method_hidden_py39.txt @@ -0,0 +1,3 @@ +method-hidden:20:4:20:12:Cdef.abcd:An attribute defined in functional.m.method_hidden_py39 line 14 hides this method:UNDEFINED +method-hidden:88:4:88:11:One.one:An attribute defined in functional.m.method_hidden_py39 line 86 hides this method:UNDEFINED +method-hidden:117:4:117:18:Child._protected:An attribute defined in functional.m.method_hidden_py39 line 111 hides this method:UNDEFINED From f010a3ed802f2e795eab3b42e374da3f1f79d5ca Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Fri, 23 Jun 2023 00:48:08 +0900 Subject: [PATCH 10/10] Refactoring tests for readability --- tests/functional/m/method_hidden.py | 3 +- tests/functional/m/method_hidden.txt | 6 +- tests/functional/m/method_hidden_py39.py | 132 +--------------------- tests/functional/m/method_hidden_py39.txt | 3 - 4 files changed, 7 insertions(+), 137 deletions(-) delete mode 100644 tests/functional/m/method_hidden_py39.txt diff --git a/tests/functional/m/method_hidden.py b/tests/functional/m/method_hidden.py index f49737d3d7..19fd60c722 100644 --- a/tests/functional/m/method_hidden.py +++ b/tests/functional/m/method_hidden.py @@ -1,10 +1,9 @@ # pylint: disable=too-few-public-methods,missing-docstring # pylint: disable=unused-private-member -# pylint: disable=import-error """check method hiding ancestor attribute """ import functools as ft -import something_else as functools +import something_else as functools # pylint: disable=import-error class Abcd: diff --git a/tests/functional/m/method_hidden.txt b/tests/functional/m/method_hidden.txt index e099b791db..41a3c2bb5b 100644 --- a/tests/functional/m/method_hidden.txt +++ b/tests/functional/m/method_hidden.txt @@ -1,3 +1,3 @@ -method-hidden:20:4:20:12:Cdef.abcd:An attribute defined in functional.m.method_hidden line 14 hides this method:UNDEFINED -method-hidden:88:4:88:11:One.one:An attribute defined in functional.m.method_hidden line 86 hides this method:UNDEFINED -method-hidden:116:4:116:18:Child._protected:An attribute defined in functional.m.method_hidden line 111 hides this method:UNDEFINED +method-hidden:19:4:19:12:Cdef.abcd:An attribute defined in functional.m.method_hidden line 13 hides this method:UNDEFINED +method-hidden:87:4:87:11:One.one:An attribute defined in functional.m.method_hidden line 85 hides this method:UNDEFINED +method-hidden:115:4:115:18:Child._protected:An attribute defined in functional.m.method_hidden line 110 hides this method:UNDEFINED diff --git a/tests/functional/m/method_hidden_py39.py b/tests/functional/m/method_hidden_py39.py index 28231a839d..ac087d0d6c 100644 --- a/tests/functional/m/method_hidden_py39.py +++ b/tests/functional/m/method_hidden_py39.py @@ -1,142 +1,16 @@ # pylint: disable=too-few-public-methods,missing-docstring -# pylint: disable=unused-private-member -# pylint: disable=import-error """check method hiding ancestor attribute """ -import functools as ft -import something_else as functools - - -class Abcd: - """dummy""" - - def __init__(self): - self.abcd = 1 - - -class Cdef(Abcd): - """dummy""" - - def abcd(self): # [method-hidden] - """test""" - print(self) - - -class AbcdMixin: - def abcd(self): - pass - - -class Dabc(AbcdMixin, Abcd): - def abcd(self): - pass - - -class CustomProperty: - """dummy""" - - def __init__(self, _): - pass - - def __get__(self, obj, __): - if not obj: - return self - return 5 - - def __set__(self, _, __): - pass - - -class Ddef: - """dummy""" - - def __init__(self): - self.five = "five" - - @CustomProperty - def five(self): - """Always 5.""" - return self - - -def my_decorator(*args, **kwargs): - return CustomProperty(*args, **kwargs) - - -class Foo: - def __init__(self): - self._bar = 42 - self._baz = 84 - - @my_decorator - def method(self): # E0202 - return self._baz - - @method.setter - def method(self, value): - self._baz = value - - def do_something_with_baz(self, value): - self.method = value - - -class One: - def __init__(self, one=None): - if one is not None: - self.one = one - - def one(self): # [method-hidden] - pass - - -class Two(One): - def one(self): - pass - - -try: - import unknown as js -except ImportError: - import json as js - - -class JsonEncoder(js.JSONEncoder): - # pylint: disable=useless-super-delegation,super-with-arguments - def default(self, o): - return super(JsonEncoder, self).default(o) +import something_else as functools # pylint: disable=import-error class Parent: def __init__(self): self._protected = None - self._protected_two = None - self._protected_three = None class Child(Parent): - def _protected(self): # [method-hidden] - pass - - -class CachedChild(Parent): - @ft.cached_property - def _protected(self): - pass - - @functools.cached_property - def _protected_two(self): - pass - @functools().cached_property - def _protected_three(self): - pass - - -class ParentTwo: - def __init__(self): - self.__private = None - - -class ChildTwo(ParentTwo): - def __private(self): + def _protected(self): + # This test case is only valid for python3.9 and above pass diff --git a/tests/functional/m/method_hidden_py39.txt b/tests/functional/m/method_hidden_py39.txt deleted file mode 100644 index ed2572523b..0000000000 --- a/tests/functional/m/method_hidden_py39.txt +++ /dev/null @@ -1,3 +0,0 @@ -method-hidden:20:4:20:12:Cdef.abcd:An attribute defined in functional.m.method_hidden_py39 line 14 hides this method:UNDEFINED -method-hidden:88:4:88:11:One.one:An attribute defined in functional.m.method_hidden_py39 line 86 hides this method:UNDEFINED -method-hidden:117:4:117:18:Child._protected:An attribute defined in functional.m.method_hidden_py39 line 111 hides this method:UNDEFINED