diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2015-10-04 22:16:22 +0300 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2015-10-04 22:16:22 +0300 |
commit | 20b663ec6fb7cf830559e169e5fb106f9bd182ac (patch) | |
tree | 7850bff6e62413cd4be89c92679dcad3a19b8767 /pylint/checkers | |
parent | 48f89e053b0b91d5cc1a1401a5b871815e4bcf9e (diff) | |
download | pylint-20b663ec6fb7cf830559e169e5fb106f9bd182ac.tar.gz |
Don't emit 'assigning-non-slot' for descriptors. Closes issue #652.
Diffstat (limited to 'pylint/checkers')
-rw-r--r-- | pylint/checkers/classes.py | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/pylint/checkers/classes.py b/pylint/checkers/classes.py index 71041ea..0fc0fae 100644 --- a/pylint/checkers/classes.py +++ b/pylint/checkers/classes.py @@ -57,6 +57,25 @@ def _is_invalid_base_class(cls): return cls.name in INVALID_BASE_CLASSES and is_builtin_object(cls) +def _has_data_descriptor(cls, attr): + attributes = cls.getattr(attr) + for attribute in attributes: + try: + for inferred in attribute.infer(): + if isinstance(inferred, astroid.Instance): + try: + inferred.getattr('__get__') + inferred.getattr('__set__') + except astroid.NotFoundError: + continue + else: + return True + except astroid.InferenceError: + # Can't infer, avoid emitting a false positive in this case. + return True + return False + + 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. @@ -578,6 +597,10 @@ a metaclass class method.'} # Properties circumvent the slots mechanism, # so we should not emit a warning for them. return + if (node.attrname in klass.locals + and _has_data_descriptor(klass, node.attrname)): + # Descriptors circumvent the slots mechanism as well. + return self.add_message('assigning-non-slot', args=(node.attrname, ), node=node) |