1.1 --- a/annotate.py Sat Nov 25 01:36:18 2006 +0100
1.2 +++ b/annotate.py Sat Nov 25 03:07:54 2006 +0100
1.3 @@ -301,6 +301,11 @@
1.4 if not attributes:
1.5 if not attr.type in non_accesses:
1.6 non_accesses.append(attr)
1.7 +
1.8 + # Revoke this type from any name involved.
1.9 +
1.10 + self._prune_non_accesses(loadattr, attr)
1.11 +
1.12 for attribute, accessor in attributes:
1.13 if attribute is not None:
1.14 types.append(attribute)
1.15 @@ -311,6 +316,11 @@
1.16 else:
1.17 if not attr in non_accesses:
1.18 non_accesses.append(attr)
1.19 +
1.20 + # Revoke this type from any name involved.
1.21 +
1.22 + self._prune_non_accesses(loadattr, attr)
1.23 +
1.24 if not types:
1.25 print "No attribute found for", loadattr.name, "given", self.namespace.types
1.26 self.namespace.set_types(types)
1.27 @@ -319,6 +329,14 @@
1.28 self.annotate(loadattr)
1.29 return loadattr
1.30
1.31 + def _prune_non_accesses(self, loadattr, attr):
1.32 + if isinstance(loadattr.expr, LoadName):
1.33 + self.namespace.revoke(loadattr.expr.name, attr)
1.34 + elif isinstance(loadattr.expr, LoadAttr):
1.35 + for expr_attr in loadattr.expr.expr.types:
1.36 + if hasattr(expr_attr.type, "namespace"):
1.37 + expr_attr.type.namespace.revoke(loadattr.expr.name, attr)
1.38 +
1.39 def visitLoadExc(self, loadexc):
1.40 self.namespace.types = self.namespace.raises[:]
1.41 self.annotate(loadexc)
1.42 @@ -848,6 +866,10 @@
1.43
1.44 __getitem__ = load
1.45
1.46 + def revoke(self, name, type):
1.47 + print "Revoke", type, "from", name
1.48 + self.names[name].remove(type)
1.49 +
1.50 def merge_namespace(self, namespace):
1.51 self.merge_items(namespace.names.items())
1.52 combine(self.returns, namespace.returns)
2.1 --- a/tests/logical_attr.py Sat Nov 25 01:36:18 2006 +0100
2.2 +++ b/tests/logical_attr.py Sat Nov 25 03:07:54 2006 +0100
2.3 @@ -6,5 +6,7 @@
2.4 b = 3.0
2.5 class C:
2.6 c = 4
2.7 -a = X() and Y() or B() and not C()
2.8 +class D(X):
2.9 + y = True
2.10 +a = X() and Y() or B() and not C() or D()
2.11 b = a.x and a.y or a.b and not a.c