Returns the full pipe of a dispatch run.

    :param sol:
         A Solution object.
    :type sol: schedula.utils.Solution

    :param base:
        Base node id.
    :type base: tuple[str]

    :return:
        Full pipe of a dispatch run.
    :rtype: DspPipe

def get_full_pipe(sol, base=()):
    """
    Returns the full pipe of a dispatch run.

    :param sol:
         A Solution object.
    :type sol: schedula.utils.Solution

    :param base:
        Base node id.
    :type base: tuple[str]

    :return:
        Full pipe of a dispatch run.
    :rtype: DspPipe
    """

    pipe, i = DspPipe(), len(base)

    for p in sol._pipe:
        n, s = p[-1]
        d = s.dsp
        p = {'task': p}

        if n in s._errors:
            p['error'] = s._errors[n]

        node_id = s.full_name + (n,)

        assert base == node_id[:i], '%s != %s' % (node_id[:i], base)

        n_id = node_id[i:]

        n, path = d.get_node(n, node_attr=None)
        if n['type'] == 'function' and 'function' in n:
            try:
                sub_sol = s.workflow.node[path[-1]]['solution']
                sp = get_full_pipe(sub_sol, base=node_id)
                if sp:
                    p['sub_pipe'] = sp
            except KeyError:
                pass

        pipe[bypass(*n_id)] = p

    return pipe