summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2020-03-06 10:46:26 +0100
committerClaudiu Popa <pcmanticore@gmail.com>2020-03-06 10:54:48 +0100
commit17a5ee681bcf4aacffcc4ec5afbc3436cfdc4537 (patch)
tree10c691821e62b58c4c4a9efd5b29ef828306c24c /tests
parent88fd426e14c34cb5771fd6c06f5a1ba50bb03292 (diff)
downloadastroid-git-17a5ee681bcf4aacffcc4ec5afbc3436cfdc4537.tar.gz
Cache the inference of FunctionDef to prevent property inference mutating locals
When inferring a property, we instantiate a new `objects.Property` object, which in turn, because it inherits from `FunctionDef`, sets itself in the locals of the wrapping frame. This means that everytime we infer a property, the locals are mutated with a new instance of the property. Using `context` with `path_wrapper` would not have helped, because we call `inferred()` on functions in multiple places in pylint's codebase.
Diffstat (limited to 'tests')
-rw-r--r--tests/unittest_inference.py22
1 files changed, 22 insertions, 0 deletions
diff --git a/tests/unittest_inference.py b/tests/unittest_inference.py
index 751a4586..49ff6cdc 100644
--- a/tests/unittest_inference.py
+++ b/tests/unittest_inference.py
@@ -5707,5 +5707,27 @@ def test_self_reference_infer_does_not_trigger_recursion_error():
assert inferred is util.Uninferable
+def test_inferring_properties_multiple_time_does_not_mutate_locals_multiple_times():
+ code = """
+ class A:
+ @property
+ def a(self):
+ return 42
+
+ A()
+ """
+ node = extract_node(code)
+ # Infer the class
+ cls = next(node.infer())
+ prop, = cls.getattr("a")
+
+ # Try to infer the property function *multiple* times. `A.locals` should be modified only once
+ for _ in range(3):
+ prop.inferred()
+ a_locals = cls.locals["a"]
+ # [FunctionDef, Property]
+ assert len(a_locals) == 2
+
+
if __name__ == "__main__":
unittest.main()