diff options
author | cpopa <devnull@localhost> | 2014-04-09 11:24:43 +0300 |
---|---|---|
committer | cpopa <devnull@localhost> | 2014-04-09 11:24:43 +0300 |
commit | f45cab1b0f8541d6ff2fe39b72090ad9e6613c0e (patch) | |
tree | a33b02af8e73b7ac4a73c16a692cb0d90df1378c /checkers/classes.py | |
parent | a819a9485a94769a2315b0dc742849298c191d0d (diff) | |
parent | f6b867557013eb562a01bc5d025ab065edc778f6 (diff) | |
download | pylint-f45cab1b0f8541d6ff2fe39b72090ad9e6613c0e.tar.gz |
Merge with default.
Diffstat (limited to 'checkers/classes.py')
-rw-r--r-- | checkers/classes.py | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/checkers/classes.py b/checkers/classes.py index af64a44..8242162 100644 --- a/checkers/classes.py +++ b/checkers/classes.py @@ -156,7 +156,15 @@ MSGS = { 'bad-context-manager', 'Used when the __exit__ special method, belonging to a \ context manager, does not accept 3 arguments \ - (type, value, traceback).') + (type, value, traceback).'), + 'E0236': ('Invalid object %r in __slots__, must contain ' + 'only non empty strings', + 'invalid-slots-object', + 'Used when an invalid (non-string) object occurs in __slots__.'), + 'E0238': ('Invalid __slots__ object', + 'invalid-slots', + 'Used when an invalid __slots__ is found in class. ' + 'Only a string, an iterable or a sequence is permitted.') } @@ -240,6 +248,7 @@ a metaclass class method.'} node.local_attr('__init__') except astroid.NotFoundError: self.add_message('W0232', args=node, node=node) + self._check_slots(node) @check_messages('E0203', 'W0201') def leave_class(self, cnode): @@ -333,6 +342,49 @@ a metaclass class method.'} elif node.name == '__exit__': self._check_exit(node) + def _check_slots(self, node): + if '__slots__' not in node.locals: + return + for slots in node.igetattr('__slots__'): + # check if __slots__ is a valid type + for meth in ('__iter__', '__getitem__'): + try: + slots.getattr(meth) + break + except astroid.NotFoundError: + continue + else: + self.add_message('invalid-slots', node=node) + continue + + if isinstance(slots, astroid.Const): + # a string, ignore the following checks + continue + if not hasattr(slots, 'itered'): + # we can't obtain the values, maybe a .deque? + continue + + if isinstance(slots, astroid.Dict): + values = [item[0] for item in slots.items] + else: + values = slots.itered() + if values is YES: + return + + for elt in values: + if elt is YES: + continue + if (not isinstance(elt, astroid.Const) or + not isinstance(elt.value, str)): + self.add_message('invalid-slots-object', + args=elt.as_string(), + node=elt) + continue + if not elt.value: + self.add_message('invalid-slots-object', + args=elt.as_string(), + node=elt) + def _check_iter(self, node): try: infered = node.infer_call_result(node) |