diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | pylint/checkers/utils.py | 6 | ||||
-rw-r--r-- | pylint/test/functional/abstract_class_instantiated_py2.py | 21 | ||||
-rw-r--r-- | pylint/test/functional/abstract_class_instantiated_py2.txt | 8 | ||||
-rw-r--r-- | pylint/test/functional/abstract_class_instantiated_py3.py | 20 | ||||
-rw-r--r-- | pylint/test/functional/abstract_class_instantiated_py3.txt | 8 |
6 files changed, 55 insertions, 14 deletions
@@ -303,6 +303,12 @@ ChangeLog for Pylint * 'deprecated-module' can be shown for modules which aren't available. Closes issue #362. + * Don't consider a class abstract if its members can't + be properly inferred. + + This fixes a false positive related to abstract-class-instantiated. + Closes issue #648. + 2015-03-14 -- 1.4.3 diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py index 767bba8..dda5f44 100644 --- a/pylint/checkers/utils.py +++ b/pylint/checkers/utils.py @@ -524,6 +524,12 @@ def unimplemented_abstract_methods(node, is_abstract_cb=None): if isinstance(obj, astroid.AssignName): infered = safe_infer(obj) if not infered: + # Might be an abstract function, + # but since we don't have enough information + # in order to take this decision, we're taking + # the *safe* decision instead. + if obj.name in visited: + del visited[obj.name] continue if not isinstance(infered, astroid.FunctionDef): if obj.name in visited: diff --git a/pylint/test/functional/abstract_class_instantiated_py2.py b/pylint/test/functional/abstract_class_instantiated_py2.py index 9b3f315..d30c1a5 100644 --- a/pylint/test/functional/abstract_class_instantiated_py2.py +++ b/pylint/test/functional/abstract_class_instantiated_py2.py @@ -5,12 +5,12 @@ abstract methods. # pylint: disable=too-few-public-methods, missing-docstring # pylint: disable=no-absolute-import, metaclass-assignment -# pylint: disable=abstract-method - -__revision__ = 0 +# pylint: disable=abstract-method, import-error, wildcard-import import abc from abc import ABCMeta +from lala import Bala + class GoodClass(object): __metaclass__ = abc.ABCMeta @@ -56,6 +56,20 @@ class FourthBadClass(ThirdBadClass): pass +class SomeMetaclass(object): + __metaclass__ = ABCMeta + + @abc.abstractmethod + def prop(self): + pass + +class FifthGoodClass(SomeMetaclass): + """Don't consider this abstract if some attributes are + there, but can't be inferred. + """ + prop = Bala # missing + + def main(): """ do nothing """ GoodClass() @@ -66,3 +80,4 @@ def main(): SecondBadClass() # [abstract-class-instantiated] ThirdBadClass() # [abstract-class-instantiated] FourthBadClass() # [abstract-class-instantiated] + diff --git a/pylint/test/functional/abstract_class_instantiated_py2.txt b/pylint/test/functional/abstract_class_instantiated_py2.txt index 68e7eb5..1e4a72d 100644 --- a/pylint/test/functional/abstract_class_instantiated_py2.txt +++ b/pylint/test/functional/abstract_class_instantiated_py2.txt @@ -1,4 +1,4 @@ -abstract-class-instantiated:65:main:Abstract class 'BadClass' with abstract methods instantiated
-abstract-class-instantiated:66:main:Abstract class 'SecondBadClass' with abstract methods instantiated
-abstract-class-instantiated:67:main:Abstract class 'ThirdBadClass' with abstract methods instantiated
-abstract-class-instantiated:68:main:Abstract class 'FourthBadClass' with abstract methods instantiated
+abstract-class-instantiated:79:main:Abstract class 'BadClass' with abstract methods instantiated
+abstract-class-instantiated:80:main:Abstract class 'SecondBadClass' with abstract methods instantiated
+abstract-class-instantiated:81:main:Abstract class 'ThirdBadClass' with abstract methods instantiated
+abstract-class-instantiated:82:main:Abstract class 'FourthBadClass' with abstract methods instantiated
diff --git a/pylint/test/functional/abstract_class_instantiated_py3.py b/pylint/test/functional/abstract_class_instantiated_py3.py index 0b2dd4a..f373189 100644 --- a/pylint/test/functional/abstract_class_instantiated_py3.py +++ b/pylint/test/functional/abstract_class_instantiated_py3.py @@ -4,12 +4,12 @@ abstract methods. """ # pylint: disable=too-few-public-methods, missing-docstring -# pylint: disable=abstract-method - -__revision__ = 0 +# pylint: disable=abstract-method, import-error import abc import weakref +from lala import Bala + class GoodClass(object, metaclass=abc.ABCMeta): pass @@ -82,11 +82,25 @@ class NoMroAbstractMethods(Container, Iterator, Sizable, Hashable): class BadMroAbstractMethods(Container, Iterator, AbstractSizable): pass +class SomeMetaclass(metaclass=abc.ABCMeta): + + @abc.abstractmethod + def prop(self): + pass + +class FourthGoodClass(SomeMetaclass): + """Don't consider this abstract if some attributes are + there, but can't be inferred. + """ + prop = Bala # missing + + def main(): """ do nothing """ GoodClass() SecondGoodClass() ThirdGoodClass() + FourthGoodClass() weakref.WeakKeyDictionary() weakref.WeakValueDictionary() NoMroAbstractMethods() diff --git a/pylint/test/functional/abstract_class_instantiated_py3.txt b/pylint/test/functional/abstract_class_instantiated_py3.txt index 6469929..629eec7 100644 --- a/pylint/test/functional/abstract_class_instantiated_py3.txt +++ b/pylint/test/functional/abstract_class_instantiated_py3.txt @@ -1,4 +1,4 @@ -abstract-class-instantiated:94:main:Abstract class 'BadMroAbstractMethods' with abstract methods instantiated
-abstract-class-instantiated:95:main:Abstract class 'BadClass' with abstract methods instantiated
-abstract-class-instantiated:96:main:Abstract class 'SecondBadClass' with abstract methods instantiated
-abstract-class-instantiated:97:main:Abstract class 'ThirdBadClass' with abstract methods instantiated
+abstract-class-instantiated:108:main:Abstract class 'BadMroAbstractMethods' with abstract methods instantiated
+abstract-class-instantiated:109:main:Abstract class 'BadClass' with abstract methods instantiated
+abstract-class-instantiated:110:main:Abstract class 'SecondBadClass' with abstract methods instantiated
+abstract-class-instantiated:111:main:Abstract class 'ThirdBadClass' with abstract methods instantiated
|