code: def _export_graph_to_dict_dict(
      graph,
      use_vids: bool = True,
      edge_attrs: Union[str, Sequence[str]] = None,
      skip_none: bool = False,
      vertex_name_attr: str = "name",
  ):
      """Export graph to dictionary of dicts of edge attributes
  
      This function is the reverse of Graph.DictDict.
  
      Example:
  
        >>> g = Graph.Full(3)
        >>> g.es['name'] = ['first_edge', 'second', 'third']
        >>> g.to_dict_dict()
        {0: {1: {'name': 'first_edge'}, 2: {'name': 'second'}}, 1: {2: {'name': 'third'}}}
  
      @param use_vids: whether to label vertices in the output data
        structure by their ids or their vertex_name_attr attribute. If
        use_vids=False but vertices lack a vertex_name_attr attribute, an
        AttributeError is raised.
      @param edge_attrs: list of edge attributes to export.
        None (default) signified all attributes (unlike Graph.to_tuple_list). A
        string is acceptable to signify a single attribute and will be wrapped
        in a list internally.
      @param skip_none: whether to skip, for each edge, attributes that
        have a value of None. This is useful if only some edges are expected to
        possess an attribute.
      @param vertex_name_attr: only used with use_vids=False to choose what
        vertex attribute to use to name your vertices in the output data
        structure.
  
      @return: dictionary of dictionaries of dictionaries, with the outer keys
        vertex ids/names, the middle keys ids/names of their neighbors, and the
        innermost dictionary representing attributes of that edge.
      """
      if edge_attrs is not None:
          if isinstance(edge_attrs, str):
              edge_attrs = [edge_attrs]
          missing_attrs = list(
              set(edge_attrs) - set(graph.edge_attributes())
          )
          if missing_attrs:
              raise AttributeError(
                  f"Missing attributes: {missing_attrs}"
              )
  
      if not use_vids:
          if vertex_name_attr not in graph.vertex_attributes():
              raise AttributeError(
                  f"Vertices do not have a {vertex_name_attr} attribute"
              )
          vs_names = graph.vs[vertex_name_attr]
  
      # Temporary output data structure
      res = defaultdict(lambda: defaultdict(dict))
  
      for edge in graph.es:
          source, target = edge.tuple
  
          if not use_vids:
              source = vs_names[source]
              target = vs_names[target]
  
          attrdic = edge.attributes()
          if edge_attrs is not None:
              attrdic = {k: attrdic[k] for k in edge_attrs}
          if skip_none:
              attrdic = {
                  k: v for k, v in attrdic.items() if v is not None
              }
  
          res[source][target] = attrdic
  
      res = {key: dict(val) for key, val in res.items()}
      return res
  
file_path: python-igraph/src/igraph/io/objects.py
imports: from typing import Union, Sequence
  from collections import defaultdict
  from itertools import repeat
  from warnings import warn
  from igraph.datatypes import UniqueIdGenerator
label_desc: Use image node_id 9 for calling a global function with example usage: _export_graph_to_dict_dict(graph, use_vids, edge_attrs, skip_none, vertex_name_attr) and returns: res