code: def add_pipe(self, pipe, branch=None):
          
          #TODO: Check if consume/spawn/produce is right!
          self.log.debug('%s adding pipe: %s' % (repr(self), repr(pipe)))
          for i in xrange(len(pipe) - 1):
              edge = (pipe[i + 1], pipe[i])
              edge = (self.add_piper(edge[0], create=True, branch=branch)[1], \
                      self.add_piper(edge[1], create=True, branch=branch)[1])
              if edge[0] in self.dfs(edge[1], []):
                  self.log.error('%s cannot add the %s>>>%s edge (introduces a cycle)' % \
                                  (repr(self), edge[0], edge[1]))
                  raise DaggerError('%s cannot add the %s>>>%s edge (introduces a cycle)' % \
                                  (repr(self), edge[0], edge[1]))
              self.add_edge(edge)
              self.clear_nodes() #dfs
              self.log.debug('%s added the %s>>>%s edge' % \
                            (repr(self), edge[0], edge[1]))
docs: Adds a pipe (A, ..., N) which is an N-``tuple`` tuple of ``Pipers`` 
          instances. Adding a pipe means to add all the ``Pipers`` and connect 
          them in the specified left to right order.
          
          The direction of the edges in the ``DictGraph`` is reversed compared to 
          the left to right data-flow in a pipe.
  
          Arguments:
          
            - pipe(sequence) N-``tuple`` of ``Piper`` instances or objects which 
              are valid  ``add_piper`` arguments. See: ``Dagger.add_piper`` and 
              ``Dagger.resolve``.