# HG changeset patch # User Paul Boddie # Date 1339200116 -7200 # Node ID d486a4cf17305b3bae36af13221778b8d0b478fa # Parent 830194e3b6aba66ed25961c77c49010e9aa6e6a9 Improved contributor and usage discovery where contribution loops are encountered. Added a test of nested conditional statements. Updated the "to do" list. diff -r 830194e3b6ab -r d486a4cf1730 TO_DO.txt --- a/TO_DO.txt Tue Jun 05 01:54:54 2012 +0200 +++ b/TO_DO.txt Sat Jun 09 02:01:56 2012 +0200 @@ -94,8 +94,6 @@ Self-related Usage ------------------ -Usage of self to restrict attribute usage observations and coverage. - Perform attribute usage on attributes of self as names, potentially combining observations across methods. diff -r 830194e3b6ab -r d486a4cf1730 micropython/data.py --- a/micropython/data.py Tue Jun 05 01:54:54 2012 +0200 +++ b/micropython/data.py Sat Jun 09 02:01:56 2012 +0200 @@ -390,7 +390,6 @@ # usage with the usage recorded directly on the user. self.get_usage_from_contributors(user) - self.set_contributors(user) # Record the defining user on each contributor. @@ -485,21 +484,6 @@ attrtypes[name] = objtypes return attrtypes - def set_contributors(self, node): - if not hasattr(node, "_attrcontributors"): - node._attrcontributors = None - all_contributors = set() - - for contributor in node._attrbranches: - all_contributors.add(contributor) - self.set_contributors(contributor) - - contributors = contributor._attrcontributors - if contributors is not None: - all_contributors.update(contributors) - - node._attrcontributors = all_contributors - def get_usage_from_contributors(self, node): """ @@ -513,6 +497,7 @@ if not hasattr(node, "_attrcombined"): node._attrcombined = None + node._attrcontributors = None for contributor in node._attrbranches: @@ -522,23 +507,33 @@ # Collect unfinished contributors and affected nodes. - if node._attrcombined is None: + # Where the contributor is already set to None, a loop has + # occurred and this node will need to have its usage + # recalculated later for the unfinished contributor. + + if contributor._attrcombined is None: if not unfinished.has_key(contributor): unfinished[contributor] = [] unfinished[contributor].append(node) continue + # Where the contributor provides usage details, it may also + # communicate unfinished contributor information. As a + # consequence, this node is also affected. + for unfinished_contributor, nodes in unfinished_contributors.items(): if not unfinished.has_key(unfinished_contributor): unfinished[unfinished_contributor] = nodes else: unfinished[unfinished_contributor] += nodes - unfinished[contributor].append(node) + if node not in unfinished[unfinished_contributor]: + unfinished[unfinished_contributor].append(node) # Set the current state of the usage on this node. - node._attrcombined = self.get_usage_from_contributors_for_node(node) + node._attrcombined, node._attrcontributors = \ + self.get_usage_from_contributors_for_node(node) # Complete unfinished contributors relying on this node. @@ -547,7 +542,10 @@ for contributor in unfinished[node]: if not contributor in processed: processed.add(contributor) - contributor._attrcombined = self.get_usage_from_contributors_for_node(contributor) + + contributor._attrcombined, contributor._attrcontributors = \ + self.get_usage_from_contributors_for_node(contributor) + del unfinished[node] return unfinished @@ -558,12 +556,18 @@ contributor_usage = {} all_contributions = [] + all_contributors = set() for contributor in node._attrbranches: usage = contributor._attrcombined if usage is not None: all_contributions.append(usage) + all_contributors.add(contributor) + contributors = contributor._attrcontributors + if contributors is not None: + all_contributors.update(contributors) + # Get contributed usage for each contributor. # This gathers usage for each name such as {(a, b), (c, d)} and # {(a, b), (e, f)} into a single set {(a, b), (c, d), (e, f)}. @@ -578,7 +582,7 @@ # Thus, usage of {(f, g)} combined with {(a, b), (c, d)} would give # {(f, g, a, b), (f, g, c, d)}. - return combine_mapping_dicts(deepen_mapping_dict(node._attrnames), contributor_usage) + return combine_mapping_dicts(deepen_mapping_dict(node._attrnames), contributor_usage), all_contributors def use_attribute(self, name, attrname, value=None): diff -r 830194e3b6ab -r d486a4cf1730 tests/attribute_access_type_restriction_conditional_nested.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/attribute_access_type_restriction_conditional_nested.py Sat Jun 09 02:01:56 2012 +0200 @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +class C: + def f(self): + return 1 + def g(self): + return 2 + +class D: + def g(self): + return 3 + +def test_conditional(x, obj): + obj.f() + if x: + if x: + a = obj.g() + return a + return 1 + +c = C() +d = D() +result1_2 = test_conditional(1, c) + +# vim: tabstop=4 expandtab shiftwidth=4