def bfs_conditional(G, source, reverse=False, keys=True, data=False,
                    yield_nodes=True, yield_if=None,
                    continue_if=None, visited_nodes=None,
                    yield_source=False):
    if reverse and hasattr(G, 'reverse'):
        G = G.reverse()
    if isinstance(G, nx.Graph):
        neighbors = functools.partial(G.edges, data=data)
    else:
        neighbors = functools.partial(G.edges, keys=keys, data=data)
    queue = collections.deque([])
    if visited_nodes is None:
        visited_nodes = set([])
    else:
        visited_nodes = set(visited_nodes)
    if source not in visited_nodes:
        if yield_nodes and yield_source:
            yield source
        visited_nodes.add(source)
        new_edges = neighbors(source)
        if isinstance(new_edges, list):
            new_edges = iter(new_edges)
        queue.append((source, new_edges))
    while queue:
        parent, edges = queue[0]
        for edge in edges:
            child = edge[1]
            if yield_nodes:
                if child not in visited_nodes:
                    if yield_if is None or yield_if(G, child, edge):
                        yield child
            else:
                if yield_if is None or yield_if(G, child, edge):
                    yield edge
            if child not in visited_nodes:
                visited_nodes.add(child)
                if continue_if is None or continue_if(G, child, edge):
                    new_edges = neighbors(child)
                    if isinstance(new_edges, list):
                        new_edges = iter(new_edges)
                    queue.append((child, new_edges))
        queue.popleft()