summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--inference.py18
-rw-r--r--test/unittest_inference.py12
3 files changed, 32 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 50ff441f..738b4031 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,8 @@ Change log for the astng package
================================
--
+ * fix #18953: inference fails with augmented assignment (special case for augmented
+ assignement in infer_ass method)
* fix #13944: false positive for class/instance attributes (Instance.getattr
should return assign nodes on instance classes as well as instance.
* include spelling fixes provided by Dotan Barak
diff --git a/inference.py b/inference.py
index 460f19ff..a136a58d 100644
--- a/inference.py
+++ b/inference.py
@@ -184,6 +184,7 @@ def infer_name(self, context=None):
context.lookupname = self.name
return _infer_stmts(stmts, context, frame)
nodes.Name.infer = path_wrapper(infer_name)
+nodes.AssName.infer_lhs = infer_name # won't work with a path wrapper
def infer_callfunc(self, context=None):
@@ -257,6 +258,7 @@ def infer_getattr(self, context=None):
# XXX method / function
context.boundnode = None
nodes.Getattr.infer = path_wrapper(raise_if_nothing_infered(infer_getattr))
+nodes.AssAttr.infer_lhs = raise_if_nothing_infered(infer_getattr) # # won't work with a path wrapper
def infer_global(self, context=None):
@@ -376,10 +378,26 @@ def infer_ass(self, context=None):
"""infer a AssName/AssAttr: need to inspect the RHS part of the
assign node
"""
+ stmt = self.statement()
+ if isinstance(stmt, nodes.AugAssign):
+ return stmt.infer(context)
stmts = list(self.assigned_stmts(context=context))
return _infer_stmts(stmts, context)
nodes.AssName.infer = path_wrapper(infer_ass)
nodes.AssAttr.infer = path_wrapper(infer_ass)
+
+def infer_augassign(self, context=None):
+ failures = []
+ for lhs in self.target.infer_lhs(context):
+ for val in _infer_binop(self.op, lhs, self.value, context, failures):
+ yield val
+ for lhs in failures:
+ for rhs in self.value.infer(context):
+ for val in _infer_binop(self.op, rhs, lhs, context):
+ yield val
+nodes.AugAssign.infer = path_wrapper(infer_augassign)
+
+
# no infer method on DelName and DelAttr (expected InferenceError)
diff --git a/test/unittest_inference.py b/test/unittest_inference.py
index 0700b164..bcfdd5d4 100644
--- a/test/unittest_inference.py
+++ b/test/unittest_inference.py
@@ -995,5 +995,17 @@ class EnvBasedTC2:
self.assertEquals(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Function)
+ def test_augassign(self):
+ code = '''
+a = 1
+a += 2
+print a
+'''
+ astng = builder.string_build(code, __name__, __file__)
+ infered = list(get_name_node(astng, 'a').infer())
+ self.assertEquals(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Const)
+ self.assertEquals(infered[0].value, 3)
+
if __name__ == '__main__':
unittest_main()