1.1 --- a/common.py Sun Oct 23 14:54:04 2016 +0200
1.2 +++ b/common.py Sun Oct 23 14:56:33 2016 +0200
1.3 @@ -109,9 +109,16 @@
1.4 self.namespace_path = []
1.5 self.in_function = False
1.6
1.7 - # Attribute chains.
1.8 + # Retain the assignment value expression and track invocations.
1.9 +
1.10 + self.in_assignment = None
1.11 + self.in_invocation = False
1.12 +
1.13 + # Attribute chain state management.
1.14
1.15 self.attrs = []
1.16 + self.chain_assignment = []
1.17 + self.chain_invocation = []
1.18
1.19 def __repr__(self):
1.20 return "CommonModule(%r, %r)" % (self.name, self.importer)
1.21 @@ -580,17 +587,25 @@
1.22
1.23 return name_ref
1.24
1.25 + # Attribute chain handling.
1.26 +
1.27 def reset_attribute_chain(self):
1.28
1.29 "Reset the attribute chain for a subexpression of an attribute access."
1.30
1.31 self.attrs = []
1.32 + self.chain_assignment.append(self.in_assignment)
1.33 + self.chain_invocation.append(self.in_invocation)
1.34 + self.in_assignment = None
1.35 + self.in_invocation = False
1.36
1.37 def restore_attribute_chain(self, attrs):
1.38
1.39 "Restore the attribute chain for an attribute access."
1.40
1.41 self.attrs = attrs
1.42 + self.in_assignment = self.chain_assignment.pop()
1.43 + self.in_invocation = self.chain_invocation.pop()
1.44
1.45 def have_access_expression(self, node):
1.46
2.1 --- a/inspector.py Sun Oct 23 14:54:04 2016 +0200
2.2 +++ b/inspector.py Sun Oct 23 14:56:33 2016 +0200
2.3 @@ -41,15 +41,8 @@
2.4
2.5 BasicModule.__init__(self, name, importer)
2.6
2.7 - self.in_assignment = False
2.8 self.in_class = False
2.9 self.in_conditional = False
2.10 - self.in_invocation = False
2.11 -
2.12 - # Attribute chain state management.
2.13 -
2.14 - self.chain_assignment = []
2.15 - self.chain_invocation = []
2.16
2.17 # Accesses to global attributes.
2.18
2.19 @@ -350,10 +343,11 @@
2.20 self.record_name(n.name)
2.21
2.22 elif isinstance(n, compiler.ast.AssAttr):
2.23 - if expr: self.process_structure_node(expr)
2.24 + if expr:
2.25 + expr = self.process_structure_node(expr)
2.26
2.27 in_assignment = self.in_assignment
2.28 - self.in_assignment = True
2.29 + self.in_assignment = expr
2.30 self.process_attribute_access(n)
2.31 self.in_assignment = in_assignment
2.32
2.33 @@ -989,26 +983,6 @@
2.34
2.35 tracker.resume_broken_branches()
2.36
2.37 - # Attribute chain handling.
2.38 -
2.39 - def reset_attribute_chain(self):
2.40 -
2.41 - "Reset the attribute chain for a subexpression of an attribute access."
2.42 -
2.43 - CommonModule.reset_attribute_chain(self)
2.44 - self.chain_assignment.append(self.in_assignment)
2.45 - self.chain_invocation.append(self.in_invocation)
2.46 - self.in_assignment = False
2.47 - self.in_invocation = False
2.48 -
2.49 - def restore_attribute_chain(self, attrs):
2.50 -
2.51 - "Restore the attribute chain for an attribute access."
2.52 -
2.53 - CommonModule.restore_attribute_chain(self, attrs)
2.54 - self.in_assignment = self.chain_assignment.pop()
2.55 - self.in_invocation = self.chain_invocation.pop()
2.56 -
2.57 # Branch tracking methods.
2.58
2.59 def start_tracking(self, names):
3.1 --- a/translator.py Sun Oct 23 14:54:04 2016 +0200
3.2 +++ b/translator.py Sun Oct 23 14:56:33 2016 +0200
3.3 @@ -501,7 +501,10 @@
3.4 self.statement(name_ref)
3.5
3.6 elif isinstance(n, compiler.ast.AssAttr):
3.7 - self.statement(self.process_attribute_access(n, self.process_structure_node(expr)))
3.8 + in_assignment = self.in_assignment
3.9 + self.in_assignment = self.process_structure_node(expr)
3.10 + self.statement(self.process_attribute_access(n))
3.11 + self.in_assignment = in_assignment
3.12
3.13 # Lists and tuples are matched against the expression and their
3.14 # items assigned to expression items.
3.15 @@ -517,7 +520,7 @@
3.16 elif isinstance(n, compiler.ast.Subscript):
3.17 self.statement(self.process_subscript_node(n, expr))
3.18
3.19 - def process_attribute_access(self, n, expr=None):
3.20 + def process_attribute_access(self, n):
3.21
3.22 """
3.23 Process the given attribute access node 'n'.
3.24 @@ -553,7 +556,7 @@
3.25
3.26 subs = {
3.27 "<expr>" : str(attr_expr),
3.28 - "<assexpr>" : str(expr),
3.29 + "<assexpr>" : str(self.in_assignment),
3.30 "<context>" : "__tmp_context",
3.31 "<accessor>" : "__tmp_value",
3.32 }