<commit_before>import asyncio
import queue as _qu
import textwrap as _tw

cycle_str = 'Graph contains cycle beteween {} and {}'


def find_path(dag, start, end, path=[]):
    path = path + [start]
    yield start
    if start not in dag._nodes:
        raise ValueError('Node does not exist')
    if start == end:
        return
    for node in dag.adjacent(start):
        if node in path:
            raise ValueError(cycle_str.format(start, node))
        if node not in path:
            yield from  find_path(dag, node, end, path=path)


def topological_sort(dag):
    T = []
    Q = _qu.LifoQueue()
    # Put all elements on queue that have no predecessor
    a = [el for el in dag.iternodes() if not el.has_predecessor]
    print(a)
    while not Q.empty():
        u = Q.get()
        print(u)
        print(list(u.outgoing))
        T.append(u)
    print(T)


class Connection:
    def __init__(self, source, dest, outport, inport):
        self.source = source
        self.dest = dest
        self.outport = outport
        self.inport = inport

    def __repr__(self):
        "{source} -> {dest} [label='{inport} -> {outport}']".format(source=self.source, dest=self.dest,
                                                                    inport=self.outport, outport=self.outport)

    def __eq__(self, other):
        return (
        self.source == other.source and self.dest == other.dest and
        self.inport == other.outport and self.outport == other.outport)

    def __hash__(self):
        return (self.source, self.dest, self.inport, self.outport).__hash__()



class Multigraph:
    def __init__(self):
        self._arcs = set()
        self._nodes = set()

    def connect(self, node1, node2, outport, inport):
        # Add nodes that are not in the node list
        [self._nodes.add(node) for node in [node1, node2] if not self.hasnode(node)]
        c = Connection(node1, node2, outport, inport)
        self._arcs.add(c)
        node1.connect(node2, outport, inport)

    def hasarc(self, node1, node2, outport, inport):
        return node1 in self._arcs and {node2: (outport, inport)} in self._arcs[node1]

    def hasnode(self, node):
        return node in self._nodes

    def disconnect(self, node1, node2):
        # TODO implement it
        pass

    def iternodes(self):
        return self._nodes.__iter__()

    def iterarcs(self):
            yield from self._arcs

    def adjacent(self, node):
        if node in self._arcs:
            yield from self._arcs[node]
        else:
            return

    def dfs(self):
        """
        Depth first traversal
        """
        seen = set()

        def inner_dfs(G, start_node):
            seen.add(start_node)
            for node in G.adjacent(start_node):
                print("current node {}, seen {}".format(node, seen))
                if node not in seen:
                    seen.add(node)
                    yield node
                else:
                    # raise ValueError(cycle_str.format(start_node, node))
                    return

        for node in self.iternodes():
            print(node)
            yield from inner_dfs(self, node)

    def __repr__(self):
        arc_str = ("{} -> {}".format(a, b) for a, b in self.iterarcs())
        out_str = "\n".join(arc_str)
        return out_str

    def dot(self):
        nodes_gen = (node.gv_node() for node in self.iternodes())
        arc_str = (
            "{source} -> {dest} [label=\"{inport} -> {outport}\"]".format(source=connection.source, dest=connection.dest,
                                                                        inport=connection.inport,
                                                                        outport=connection.outport) for
            connection in self.iterarcs())
        # edged_gen
        graph_str = """
            digraph DAG{{
            graph[bgcolor=white, margin=0]
                {nodes}
                {edges}
            }}
            """.format(nodes="\n".join(nodes_gen), edges="\n".join(arc_str))
        return _tw.dedent(graph_str)

    def __call__(self):
        loop = asyncio.get_event_loop()
        # Find nodes with no predecessors
        a = [el for el in self.iternodes() if not el.has_predecessor and el.n_out > 0]
        # #Execute them


        while True:
            coros = [c() for c in a]
            loop.run_until_complete(asyncio.gather(*coros))
            #
            #     except StopIteration:
            #         print('Computation completed')

# #Two generators
# simple_gen = (i for i in range(40))
# reverse_gen = (2 for i in range(40))
# #A simple sum process
# @process<commit_msg>Using set to represent connections.<commit_after>import asyncio
import queue as _qu
import textwrap as _tw

from pyperator.utils import Connection

cycle_str = 'Graph contains cycle beteween {} and {}'


def find_path(dag, start, end, path=[]):
    path = path + [start]
    yield start
    if start not in dag._nodes:
        raise ValueError('Node does not exist')
    if start == end:
        return
    for node in dag.adjacent(start):
        if node in path:
            raise ValueError(cycle_str.format(start, node))
        if node not in path:
            yield from  find_path(dag, node, end, path=path)


def topological_sort(dag):
    T = []
    Q = _qu.LifoQueue()
    # Put all elements on queue that have no predecessor
    a = [el for el in dag.iternodes() if not el.has_predecessor]
    print(a)
    while not Q.empty():
        u = Q.get()
        print(u)
        print(list(u.outgoing))
        T.append(u)
    print(T)


class Multigraph:
    def __init__(self):
        self._arcs = set()
        self._nodes = set()

    def connect(self, node1, node2, outport, inport):
        # Add nodes that are not in the node list
        [self._nodes.add(node) for node in [node1, node2] if not self.hasnode(node)]
        c = node1.connect(node2, outport, inport)
        self._arcs.add(c)

    def hasarc(self, node1, node2, outport, inport):
        return node1 in self._arcs and {node2: (outport, inport)} in self._arcs[node1]

    def hasnode(self, node):
        return node in self._nodes

    def disconnect(self, node1, node2):
        # TODO implement it
        pass

    def iternodes(self):
        return self._nodes.__iter__()

    def iterarcs(self):
            yield from self._arcs

    def adjacent(self, node):
        if node in self._arcs:
            yield from self._arcs[node]
        else:
            return

    def dfs(self):
        """
        Depth first traversal
        """
        seen = set()

        def inner_dfs(G, start_node):
            seen.add(start_node)
            for node in G.adjacent(start_node):
                print("current node {}, seen {}".format(node, seen))
                if node not in seen:
                    seen.add(node)
                    yield node
                else:
                    # raise ValueError(cycle_str.format(start_node, node))
                    return

        for node in self.iternodes():
            print(node)
            yield from inner_dfs(self, node)

    def __repr__(self):
        arc_str = ("{} -> {}".format(a, b) for a, b in self.iterarcs())
        out_str = "\n".join(arc_str)
        return out_str

    def dot(self):
        nodes_gen = (node.gv_node() for node in self.iternodes())
        arc_str = (
            "{source}:{outport} -> {dest}:{inport}".format(source=connection.source, dest=connection.dest,
                                                                        inport=connection.inport,
                                                                        outport=connection.outport) for
            connection in self.iterarcs())
        # edged_gen
        graph_str = """
            digraph DAG{{
            graph[bgcolor=white, margin=0]
                {nodes}
                {edges}
            }}
            """.format(nodes=";\n".join(nodes_gen), edges="\n".join(arc_str))
        return _tw.dedent(graph_str)

    def __call__(self):
        loop = asyncio.get_event_loop()
        # Find nodes with no predecessors
        a = [el for el in self.iternodes()]
        # #Execute them


        while True:
            coros = [c() for c in a]
            loop.run_until_complete(asyncio.gather(*coros))
            #
            #     except StopIteration:
            #         print('Computation completed')

# #Two generators
# simple_gen = (i for i in range(40))
# reverse_gen = (2 for i in range(40))
# #A simple sum process
# @process
{'fraction_non_alphanumeric': 0.10802936720661928, 'fraction_numerical': 0.004777997902342384, 'mean_word_length': 1.74975969240628, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '182215', 'n_tokens_mistral': 2568, 'n_tokens_neox': 2500, 'n_words': 704}