1.1 --- a/micropython/data.py Sat May 19 01:33:10 2012 +0200
1.2 +++ b/micropython/data.py Sun May 20 02:16:08 2012 +0200
1.3 @@ -389,11 +389,12 @@
1.4 # First, visit the contributors and combine their attribute
1.5 # usage with the usage recorded directly on the user.
1.6
1.7 - contributors, combined_usage = self.get_usage_from_contributors(user)
1.8 + self.get_usage_from_contributors(user)
1.9 + self.set_contributors(user)
1.10
1.11 # Record the defining user on each contributor.
1.12
1.13 - for contributor in contributors:
1.14 + for contributor in user._attrcontributors:
1.15 contributor._attrdefs.append(user)
1.16
1.17 # Then, tell the importer about the usage.
1.18 @@ -402,7 +403,7 @@
1.19
1.20 # Only provide information about names defined by this user.
1.21
1.22 - usage = combined_usage.get(name, [])
1.23 + usage = user._attrcombined.get(name, [])
1.24
1.25 # Skip reporting where no actual usage occurs.
1.26
1.27 @@ -479,6 +480,21 @@
1.28 attrtypes[name] = get_object_types_for_usage(combined_usage, objtable, name, self.full_name())
1.29 return attrtypes
1.30
1.31 + def set_contributors(self, node):
1.32 + if not hasattr(node, "_attrcontributors"):
1.33 + node._attrcontributors = None
1.34 + all_contributors = set()
1.35 +
1.36 + for contributor in node._attrbranches:
1.37 + all_contributors.add(contributor)
1.38 + self.set_contributors(contributor)
1.39 +
1.40 + contributors = contributor._attrcontributors
1.41 + if contributors is not None:
1.42 + all_contributors.update(contributors)
1.43 +
1.44 + node._attrcontributors = all_contributors
1.45 +
1.46 def get_usage_from_contributors(self, node):
1.47
1.48 """
1.49 @@ -488,44 +504,76 @@
1.50 usage possibilities (each a collection of attribute names).
1.51 """
1.52
1.53 + unfinished = {}
1.54 +
1.55 if not hasattr(node, "_attrcombined"):
1.56 -
1.57 - node._attrcontributors = set()
1.58 - node._attrcombined = {}
1.59 -
1.60 - contributor_usage = {}
1.61 - all_contributors = set()
1.62 -
1.63 - # Visit each contributor, gathering usage for each name.
1.64 + node._attrcombined = None
1.65
1.66 for contributor in node._attrbranches:
1.67
1.68 - # Get contributed usage for each contributor.
1.69 - # This gathers usage for each name such as {(a, b), (c, d)} and
1.70 - # {(a, b), (e, f)} into a single set {(a, b), (c, d), (e, f)}.
1.71 -
1.72 - contributors, contributed_usage = self.get_usage_from_contributors(contributor)
1.73 - update_mapping_dict(contributor_usage, [contributed_usage])
1.74 -
1.75 - # Record all contributors.
1.76 -
1.77 - all_contributors.add(contributor)
1.78 - all_contributors.update(contributors)
1.79 -
1.80 - # Then get the resulting usage.
1.81 - # First, make the current usage compatible with the contributed
1.82 - # usage: this makes the attribute usage for each name merely one
1.83 - # member in a list of many possibilities.
1.84 - # Then, combine the current usage with the contributed usage.
1.85 - # Thus, usage of {(f, g)} combined with {(a, b), (c, d)} would give
1.86 - # {(f, g, a, b), (f, g, c, d)}.
1.87 -
1.88 - usage = combine_mapping_dicts(deepen_mapping_dict(node._attrnames), contributor_usage)
1.89 -
1.90 - node._attrcontributors = all_contributors
1.91 - node._attrcombined = usage
1.92 -
1.93 - return node._attrcontributors, node._attrcombined
1.94 + # Get contributor details.
1.95 +
1.96 + unfinished_contributors = self.get_usage_from_contributors(contributor)
1.97 +
1.98 + # Collect unfinished contributors and affected nodes.
1.99 +
1.100 + if node._attrcombined is None:
1.101 + if not unfinished.has_key(contributor):
1.102 + unfinished[contributor] = []
1.103 + unfinished[contributor].append(node)
1.104 + continue
1.105 +
1.106 + for unfinished_contributor, nodes in unfinished_contributors.items():
1.107 + if not unfinished.has_key(unfinished_contributor):
1.108 + unfinished[unfinished_contributor] = nodes
1.109 + else:
1.110 + unfinished[unfinished_contributor] += nodes
1.111 +
1.112 + unfinished[contributor].append(node)
1.113 +
1.114 + # Set the current state of the usage on this node.
1.115 +
1.116 + node._attrcombined = self.get_usage_from_contributors_for_node(node)
1.117 +
1.118 + # Complete unfinished contributors relying on this node.
1.119 +
1.120 + if unfinished.has_key(node):
1.121 + processed = set()
1.122 + for contributor in unfinished[node]:
1.123 + if not contributor in processed:
1.124 + processed.add(contributor)
1.125 + contributor._attrcombined = self.get_usage_from_contributors_for_node(contributor)
1.126 + del unfinished[node]
1.127 +
1.128 + return unfinished
1.129 +
1.130 + def get_usage_from_contributors_for_node(self, node):
1.131 +
1.132 + # Visit each contributor, gathering usage for each name.
1.133 +
1.134 + contributor_usage = {}
1.135 + all_contributions = []
1.136 +
1.137 + for contributor in node._attrbranches:
1.138 + usage = contributor._attrcombined
1.139 + if usage is not None:
1.140 + all_contributions.append(usage)
1.141 +
1.142 + # Get contributed usage for each contributor.
1.143 + # This gathers usage for each name such as {(a, b), (c, d)} and
1.144 + # {(a, b), (e, f)} into a single set {(a, b), (c, d), (e, f)}.
1.145 +
1.146 + update_mapping_dict(contributor_usage, all_contributions)
1.147 +
1.148 + # Then get the resulting usage.
1.149 + # First, make the current usage compatible with the contributed
1.150 + # usage: this makes the attribute usage for each name merely one
1.151 + # member in a list of many possibilities.
1.152 + # Then, combine the current usage with the contributed usage.
1.153 + # Thus, usage of {(f, g)} combined with {(a, b), (c, d)} would give
1.154 + # {(f, g, a, b), (f, g, c, d)}.
1.155 +
1.156 + return combine_mapping_dicts(deepen_mapping_dict(node._attrnames), contributor_usage)
1.157
1.158 def use_attribute(self, name, attrname, value=None):
1.159
1.160 @@ -995,6 +1043,8 @@
1.161 else:
1.162 return None
1.163
1.164 + __call__ = get_value # convenient access to any single value
1.165 +
1.166 def update(self, context_values, single_assignment):
1.167
1.168 """