summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2019-05-21 09:22:23 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2019-05-21 09:22:23 +0200
commitf9e99fd5f3acaf2d836c7a3456f7538611cd4167 (patch)
tree08671d28d1d8ff8989874ce169802ff3b5bef67a
parent47d97c0bf2e7409fbc75645051ad20db2c298cb0 (diff)
downloadpylint-git-f9e99fd5f3acaf2d836c7a3456f7538611cd4167.tar.gz
Don't emit ``attribute-defined-outside-init`` for variables defined in setters.
Close #409
-rw-r--r--ChangeLog4
-rw-r--r--pylint/checkers/classes.py19
-rw-r--r--pylint/test/functional/attribute_defined_outside_init.py13
3 files changed, 30 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 1f9ab6425..b00e0ca86 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,10 @@ What's New in Pylint 2.4.0?
Release date: TBA
+* Don't emit ``attribute-defined-outside-init`` for variables defined in setters.
+
+ Close #409
+
* Syntax errors report the column number.
Close #2914
diff --git a/pylint/checkers/classes.py b/pylint/checkers/classes.py
index df39331d3..1313f4830 100644
--- a/pylint/checkers/classes.py
+++ b/pylint/checkers/classes.py
@@ -811,7 +811,11 @@ a metaclass class method.",
defining_methods = self.config.defining_attr_methods
current_module = cnode.root()
for attr, nodes in cnode.instance_attrs.items():
- # skip nodes which are not in the current module and it may screw up
+ # Exclude `__dict__` as it is already defined.
+ if attr == "__dict__":
+ continue
+
+ # Skip nodes which are not in the current module and it may screw up
# the output, while it's not worth it
nodes = [
n
@@ -821,11 +825,14 @@ a metaclass class method.",
]
if not nodes:
continue # error detected by typechecking
- # check if any method attr is defined in is a defining method
- if any(node.frame().name in defining_methods for node in nodes):
- continue
- # Exclude `__dict__` as it is already defined.
- if attr == "__dict__":
+
+ # Check if any method attr is defined in is a defining method
+ # or if we have the attribute defined in a setter.
+ frames = (node.frame() for node in nodes)
+ if any(
+ frame.name in defining_methods or is_property_setter(frame)
+ for frame in frames
+ ):
continue
# check attribute is defined in a parent's __init__
diff --git a/pylint/test/functional/attribute_defined_outside_init.py b/pylint/test/functional/attribute_defined_outside_init.py
index ab5cf5f19..ff31e955d 100644
--- a/pylint/test/functional/attribute_defined_outside_init.py
+++ b/pylint/test/functional/attribute_defined_outside_init.py
@@ -65,3 +65,16 @@ class Mixin(object):
class F:
def func(self):
self.__dict__ = {'foo': 'bar'}
+
+
+class Mine:
+ def __init__(self, param):
+ self.prop = param
+
+ @property
+ def prop(self):
+ return self.__prop
+
+ @prop.setter
+ def prop(self, value):
+ self.__prop = value