code: def add_func_edges(dsp, fun_id, nodes_bunch, edge_weights=None, input=True,
                     data_nodes=None):
      
  
      # Namespace shortcut for speed.
      add_edge = _add_edge_dmap_fun(dsp.dmap, edge_weights)
      node, add_data = dsp.dmap.nodes, dsp.add_data
      remove_nodes = dsp.dmap.remove_nodes_from
  
      # Define an error message.
      msg = 'Invalid %sput id: {} is not a data node' % ['out', 'in'][input]
      i, j = ('i', 'o') if input else ('o', 'i')
  
      data_nodes = data_nodes or []  # Update data nodes.
  
      for u in nodes_bunch:  # Iterate nodes.
          try:
              if node[u]['type'] != 'data':  # The node is not a data node.
                  data_nodes.append(fun_id)  # Add function id to be removed.
  
                  remove_nodes(data_nodes)  # Remove function and new data nodes.
  
                  raise ValueError(msg.format(u))  # Raise error.
          except KeyError:
              data_nodes.append(add_data(data_id=u))  # Add new data node.
  
          add_edge(**{i: u, j: fun_id, 'w': u})  # Add edge.
  
      return data_nodes
docs: Adds function node edges.
  
      :param dsp:
          A dispatcher that identifies the model adopted.
      :type dsp: schedula.Dispatcher
  
      :param fun_id:
          Function node id.
      :type fun_id: str
  
      :param nodes_bunch:
          A container of nodes which will be iterated through once.
      :type nodes_bunch: iterable
  
      :param edge_weights:
          Edge weights.
      :type edge_weights: dict, optional
  
      :param input:
          If True the nodes_bunch are input nodes, otherwise are output nodes.
      :type input: bool, optional
  
      :param data_nodes:
          Data nodes to be deleted if something fail.
      :type data_nodes: list
  
      :return:
          List of new data nodes.
      :rtype: list