1.1 --- a/common.py Tue Jan 24 19:10:31 2017 +0100
1.2 +++ b/common.py Wed Jan 25 00:00:38 2017 +0100
1.3 @@ -394,9 +394,18 @@
1.4
1.5 name_ref = self.process_structure_node(expr)
1.6
1.7 - # Have the assignment nodes access each item via the sequence API.
1.8 + # Either unpack the items and present them directly to each assignment
1.9 + # node.
1.10 +
1.11 + if isinstance(name_ref, LiteralSequenceRef) and \
1.12 + self.process_literal_sequence_items(n, name_ref):
1.13
1.14 - self.process_assignment_node_items_by_position(n, expr, name_ref)
1.15 + pass
1.16 +
1.17 + # Or have the assignment nodes access each item via the sequence API.
1.18 +
1.19 + else:
1.20 + self.process_assignment_node_items_by_position(n, expr, name_ref)
1.21
1.22 def process_assignment_node_items_by_position(self, n, expr, name_ref):
1.23
1.24 @@ -441,11 +450,31 @@
1.25 """
1.26 Process the given assignment node 'n', obtaining from the given
1.27 'name_ref' the items to be assigned to the assignment targets.
1.28 +
1.29 + Return whether this method was able to process the assignment node as
1.30 + a sequence of direct assignments.
1.31 """
1.32
1.33 if len(n.nodes) == len(name_ref.items):
1.34 - for node, item in zip(n.nodes, name_ref.items):
1.35 - self.process_assignment_node(node, item)
1.36 + assigned_names, count = get_names_from_nodes(n.nodes)
1.37 + accessed_names, _count = get_names_from_nodes(name_ref.items)
1.38 +
1.39 + # Only assign directly between items if all assigned names are
1.40 + # plain names (not attribute assignments), and if the assigned names
1.41 + # do not appear in the accessed names.
1.42 +
1.43 + if len(assigned_names) == count and \
1.44 + not assigned_names.intersection(accessed_names):
1.45 +
1.46 + for node, item in zip(n.nodes, name_ref.items):
1.47 + self.process_assignment_node(node, item)
1.48 +
1.49 + return True
1.50 +
1.51 + # Otherwise, use the position-based mechanism to obtain values.
1.52 +
1.53 + else:
1.54 + return False
1.55 else:
1.56 raise InspectError("In %s, item assignment needing %d items is given %d items." % (
1.57 self.get_namespace_path(), len(n.nodes), len(name_ref.items)))
1.58 @@ -796,6 +825,40 @@
1.59 l.append(arg)
1.60 return l
1.61
1.62 +def get_names_from_nodes(nodes):
1.63 +
1.64 + """
1.65 + Return the names employed in the given 'nodes' along with the number of
1.66 + nodes excluding sequences.
1.67 + """
1.68 +
1.69 + names = set()
1.70 + count = 0
1.71 +
1.72 + for node in nodes:
1.73 +
1.74 + # Add names and count them.
1.75 +
1.76 + if isinstance(node, (compiler.ast.AssName, compiler.ast.Name)):
1.77 + names.add(node.name)
1.78 + count += 1
1.79 +
1.80 + # Add names from sequences and incorporate their counts.
1.81 +
1.82 + elif isinstance(node, (compiler.ast.AssList, compiler.ast.AssTuple,
1.83 + compiler.ast.List, compiler.ast.Set,
1.84 + compiler.ast.Tuple)):
1.85 + _names, _count = get_names_from_nodes(node.nodes)
1.86 + names.update(_names)
1.87 + count += _count
1.88 +
1.89 + # Count non-name, non-sequence nodes.
1.90 +
1.91 + else:
1.92 + count += 1
1.93 +
1.94 + return names, count
1.95 +
1.96 # Result classes.
1.97
1.98 class InstructionSequence: