예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
    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()
예제 #4
0
    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)]
예제 #5
0
    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()
예제 #6
0
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 ))