diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | inference.py | 18 | ||||
-rw-r--r-- | test/unittest_inference.py | 12 |
3 files changed, 32 insertions, 0 deletions
@@ -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() |