def visitTryExcept(self, node): # If we are code after a 'try' block, then it either succeeded or # handled its own exception. So either the 'try' and 'else' blocks ran, # or some of the 'try' and one of the handlers ran. If we treat the # 'try' and 'else' blocks as one, then we can say that # 'try'/'except'/'else' produces unconditional locals when the same # name is local to 'try'/'else' and every handler. All other bindings # are conditional. # Visit children body_v = walk([node.body, node.else_], NameFinder()) # (A handler is (type, name, body) where 'type' and 'name' can be None) handler_vs = [ walk(h, NameFinder()) for h in node.handlers ] assert all(not v.conditional_locals for v in handler_vs) # Free names come from 'try', 'else', and names in 'except' that aren't # bound by the exception name. Since 'handlers' bundles each 'except' # body with its exception name, the bindings are already computed. self._see_unbound(body_v.free | union(v.free for v in handler_vs)) # Unconditional locals only come from locals in both the 'try'/'else' # body and every 'except' body. All other locals are conditional. locals = body_v.locals & intersect(v.locals for v in handler_vs) conditional_locals = \ (body_v.all_locals() | union(v.all_locals() for v in handler_vs)) \ - locals self._bind(locals) self._bind_conditional(conditional_locals)
def visitIf(self, node): unzip = lambda l: map(list, zip(*l)) # Gather children tests, bodies = unzip(node.tests) bodies.append(node.else_) # Visit children tests_v = walk(tests, NameFinder()) body_vs = [ walk(b, NameFinder()) for b in bodies ] assert not (tests_v.locals or tests_v.conditional_locals) # Free names come from tests and bodies self._see_unbound(tests_v.free | union(v.free for v in body_vs)) # Unconditional locals come from locals that appear in every body # including 'else'. (If we have no 'else', then its empty visitor will # nullify the intersection.) locals = intersect(v.locals for v in body_vs) # Conditional locals come from conditional locals plus the rest of the # unconditional locals conditional_locals = union(v.all_locals() for v in body_vs) - locals self._bind(locals) self._bind_conditional(conditional_locals)
def assert_events(self, *events): 'Test that a set of events fired (since the last call).' attrs = 'modified', 'added', 'removed', 'changed', 'reset' # Validate attributes in expected events unknown_attrs = union(map(set, events)) - set(attrs) if unknown_attrs: raise ValueError('Unknown attributes: %s' % list(unknown_attrs)) # (Make tidy dicts for descriptive errors) assert_equal_up_to_reordering_with_numpy_arrays( [ dict([ (k, set(e[k])) for k in attrs if k in e ]) for e in events ], [ dict([ (k, set(getattr(e,k))) for k in attrs if getattr(e,k) ]) for e in self._q ], ) # Validate properties 'all_modified' and 'not_empty' for e in self._q: assert_equal(set(e.all_modified), set(e.modified + e.added + e.removed + e.changed)) assert_equal(e.not_empty, bool(e.all_modified)) self.flush()
def equate(self, *args): 'Declare that the given elements are equivalent to each other.' args = set(args) # Singleton classes are implicit if len(args) == 1: return unaffected, to_merge = [], [] for c in self._classes: if args & c: to_merge.append(c) else: unaffected.append(c) self._classes = unaffected + [args | union(to_merge)]
def assert_events(self, *events): 'Test that a set of events fired (since the last call).' attrs = 'added', 'changed', 'removed' # Validate attributes in expected events unknown_attrs = union(map(set, events)) - set(attrs) if unknown_attrs: raise ValueError('Unknown attributes: %s' % list(unknown_attrs)) # (Make tidy dicts for descriptive errors) assert_equal_up_to_reordering_with_numpy_arrays( [ dict([ (k, e[k]) for k in attrs if k in e ]) for e in events ], [ dict([ (k, dict(getattr(e,k))) for k in attrs if getattr(e,k) ]) for e in self._q ], ) self.flush()
def reachable_graph(graph, *nodes): ''' Return the subgraph of the given graph reachable from the given nodes. Assumes 'graph' is directed and acyclic. >>> g = DiGraph({1: [2], 2: [3, 4], 5: [6]}) >>> sorted( reachable_graph(g, 1).nodes() ) [1, 2, 3, 4] >>> sorted( reachable_graph(g, 1).edges() ) [(1, 2), (2, 3), (2, 4)] >>> sorted( reachable_graph(g, 2).nodes() ) [2, 3, 4] >>> sorted( reachable_graph(g, 2).edges() ) [(2, 3), (2, 4)] >>> sorted( reachable_graph(g, 3).nodes() ) [3] >>> sorted( reachable_graph(g, 3).edges() ) [] >>> sorted( reachable_graph(g, 4).nodes() ) [4] >>> sorted( reachable_graph(g, 4).edges() ) [] >>> sorted( reachable_graph(g, 5).nodes() ) [5, 6] >>> sorted( reachable_graph(g, 5).edges() ) [(5, 6)] >>> sorted( reachable_graph(g, 6).nodes() ) [6] >>> sorted( reachable_graph(g, 6).edges() ) [] ''' assert is_directed_acyclic_graph(graph) return graph.subgraph(union( bfs(graph, n) for n in nodes ))