summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <cpopa@cloudbasesolutions.com>2015-06-25 18:57:00 +0300
committerClaudiu Popa <cpopa@cloudbasesolutions.com>2015-06-25 18:57:00 +0300
commit8f550e18295a573a4e9a106cd9af3cac944af7c6 (patch)
treefd52cd168dd508287fd5a5f289f6a1d6cbefd6ed
parent993a174a3b8cf7df95122d3e49a1a07c0966dd9f (diff)
downloadpylint-8f550e18295a573a4e9a106cd9af3cac944af7c6.tar.gz
Detect a couple of objects which can't be base classes (bool, slice, range and memoryview, which weren't detected until now).
-rw-r--r--ChangeLog3
-rw-r--r--pylint/checkers/classes.py9
-rw-r--r--pylint/test/functional/inherit_non_class.py16
-rw-r--r--pylint/test/functional/inherit_non_class.txt6
4 files changed, 32 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 68571ce..800e8c4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -184,6 +184,9 @@ ChangeLog for Pylint
* Add a new error, 'invalid-star-assignment-target', emitted when
a starred expression (*x) is used as the lhs side of an assignment,
as in `*x = [1, 2]`. This is not a SyntaxError on Python 3 though.
+
+ * Detect a couple of objects which can't be base classes (bool,
+ slice, range and memoryview, which weren't detected until now).
diff --git a/pylint/checkers/classes.py b/pylint/checkers/classes.py
index 371db18..962cca5 100644
--- a/pylint/checkers/classes.py
+++ b/pylint/checkers/classes.py
@@ -43,6 +43,7 @@ if sys.version_info >= (3, 0):
else:
NEXT_METHOD = 'next'
ITER_METHODS = ('__iter__', '__getitem__')
+INVALID_BASE_CLASSES = {'bool', 'range', 'slice', 'memoryview'}
def _get_method_args(method):
@@ -52,6 +53,10 @@ def _get_method_args(method):
return len(args)
+def _is_invalid_base_class(cls):
+ return cls.name in INVALID_BASE_CLASSES and is_builtin_object(cls)
+
+
def _called_in_methods(func, klass, methods):
""" Check if the func was called in any of the given methods,
belonging to the *klass*. Returns True if so, False otherwise.
@@ -336,7 +341,9 @@ a metaclass class method.'}
if (isinstance(ancestor, astroid.Instance) and
ancestor.is_subtype_of('%s.type' % (BUILTINS,))):
continue
- if not isinstance(ancestor, astroid.Class):
+
+ if (not isinstance(ancestor, astroid.Class) or
+ _is_invalid_base_class(ancestor)):
self.add_message('inherit-non-class',
args=base.as_string(), node=node)
diff --git a/pylint/test/functional/inherit_non_class.py b/pylint/test/functional/inherit_non_class.py
index 95afbe0..0929ed1 100644
--- a/pylint/test/functional/inherit_non_class.py
+++ b/pylint/test/functional/inherit_non_class.py
@@ -63,3 +63,19 @@ class Unknown(Missing):
class Unknown1(Good5 if True else Bad1):
pass
+
+
+class NotInheritableBool(bool): # [inherit-non-class]
+ pass
+
+
+class NotInheritableRange(range): # [inherit-non-class]
+ pass
+
+
+class NotInheritableSlice(slice): # [inherit-non-class]
+ pass
+
+
+class NotInheritableMemoryView(memoryview): # [inherit-non-class]
+ pass
diff --git a/pylint/test/functional/inherit_non_class.txt b/pylint/test/functional/inherit_non_class.txt
index 6821f3b..3be70cb 100644
--- a/pylint/test/functional/inherit_non_class.txt
+++ b/pylint/test/functional/inherit_non_class.txt
@@ -2,4 +2,8 @@ inherit-non-class:21:Bad:Inheriting '1', which is not a class.
inherit-non-class:24:Bad1:"Inheriting 'lambda abc: 42', which is not a class."
inherit-non-class:27:Bad2:Inheriting 'object()', which is not a class.
inherit-non-class:30:Bad3:Inheriting 'return_class', which is not a class.
-inherit-non-class:33:Bad4:Inheriting 'Empty()', which is not a class. \ No newline at end of file
+inherit-non-class:33:Bad4:Inheriting 'Empty()', which is not a class.
+inherit-non-class:68:NotInheritableBool:Inheriting 'bool', which is not a class.
+inherit-non-class:72:NotInheritableRange:Inheriting 'range', which is not a class.
+inherit-non-class:76:NotInheritableSlice:Inheriting 'slice', which is not a class.
+inherit-non-class:80:NotInheritableMemoryView:Inheriting 'memoryview', which is not a class. \ No newline at end of file