B
    ,µ[¥‹  ã               @   s¶  d Z ddlZddlmZ y$ddlmZmZ ddlmZmZ W nN e	k
rŠ   y$ddl
mZmZ ddl
mZmZ W n e	k
r„   Y nX Y nX yddlmZ W n e	k
r´   dZY nX ddlZddlmZmZ ddd	d
ddddgZedddd'dd
„ƒZedddd(dd„ƒZd)dd	„Zedddeefdd„ƒZefdd„ZG dd„ deƒZG dd„ deƒZG dd„ deƒZG d d!„ d!eƒZedkrŽeZ neZ G d"d„ deƒZ!d#d$„ Z"d%d&„ Z#dS )*a}  
*******
GraphML
*******
Read and write graphs in GraphML format.

This implementation does not support mixed graphs (directed and unidirected
edges together), hyperedges, nested graphs, or ports.

"GraphML is a comprehensive and easy-to-use file format for graphs. It
consists of a language core to describe the structural properties of a
graph and a flexible extension mechanism to add application-specific
data. Its main features include support of

    * directed, undirected, and mixed graphs,
    * hypergraphs,
    * hierarchical graphs,
    * graphical representations,
    * references to external data,
    * application-specific attribute data, and
    * light-weight parsers.

Unlike many other file formats for graphs, GraphML does not use a
custom syntax. Instead, it is based on XML and hence ideally suited as
a common denominator for all kinds of services generating, archiving,
or processing graphs."

http://graphml.graphdrawing.org/

Format
------
GraphML is an XML format.  See
http://graphml.graphdrawing.org/specification.html for the specification and
http://graphml.graphdrawing.org/primer/graphml-primer.html
for examples.
é    N)Údefaultdict)ÚElementÚElementTree)ÚtostringÚ
fromstring)Ú	open_fileÚmake_strÚwrite_graphmlÚread_graphmlÚgenerate_graphmlÚwrite_graphml_xmlÚwrite_graphml_lxmlÚparse_graphmlÚGraphMLWriterÚGraphMLReaderé   Úwb)Úmodeúutf-8TFc             C   s&   t |||d}| | ¡ | |¡ dS )a
  Write G in GraphML XML format to path

    Parameters
    ----------
    G : graph
       A networkx graph
    path : file or string
       File or filename to write.
       Filenames ending in .gz or .bz2 will be compressed.
    encoding : string (optional)
       Encoding for text data.
    prettyprint : bool (optional)
       If True use line breaks and indenting in output XML.
    infer_numeric_types : boolean
       Determine if numeric types should be generalized.
       For example, if edges have both int and float 'weight' attributes,
       we infer in GraphML that both are floats.

    Examples
    --------
    >>> G = nx.path_graph(4)
    >>> nx.write_graphml(G, "test.graphml")

    Notes
    -----
    It may be a good idea in Python2 to convert strings to unicode
    before giving the graph to write_gml. At least the strings with
    either many characters to escape.

    This implementation does not support mixed graphs (directed
    and unidirected edges together) hyperedges, nested graphs, or ports.
    )ÚencodingÚprettyprintÚinfer_numeric_typesN)r   Úadd_graph_elementÚdump)ÚGÚpathr   r   r   Úwriter© r   ú9lib/python3.7/site-packages/networkx/readwrite/graphml.pyr   H   s    #
c             C   s   t || |||d}| ¡  dS )aã  Write G in GraphML XML format to path

    This function uses the LXML framework and should be faster than
    the version using the xml library.

    Parameters
    ----------
    G : graph
       A networkx graph
    path : file or string
       File or filename to write.
       Filenames ending in .gz or .bz2 will be compressed.
    encoding : string (optional)
       Encoding for text data.
    prettyprint : bool (optional)
       If True use line breaks and indenting in output XML.
    infer_numeric_types : boolean
       Determine if numeric types should be generalized.
       For example, if edges have both int and float 'weight' attributes,
       we infer in GraphML that both are floats.

    Examples
    --------
    >>> G = nx.path_graph(4)
    >>> nx.write_graphml_lxml(G, "fourpath.graphml")  # doctest: +SKIP

    Notes
    -----
    This implementation does not support mixed graphs (directed
    and unidirected edges together) hyperedges, nested graphs, or ports.
    )Úgraphr   r   r   N)ÚGraphMLWriterLxmlr   )r   r   r   r   r   r   r   r   r   r   q   s    "c             c   s6   t ||d}| | ¡ xt|ƒ ¡ D ]
}|V  q$W dS )až  Generate GraphML lines for G

    Parameters
    ----------
    G : graph
       A networkx graph
    encoding : string (optional)
       Encoding for text data.
    prettyprint : bool (optional)
       If True use line breaks and indenting in output XML.

    Examples
    --------
    >>> G = nx.path_graph(4)
    >>> linefeed = chr(10)  # linefeed = 

    >>> s = linefeed.join(nx.generate_graphml(G))  # doctest: +SKIP
    >>> for line in nx.generate_graphml(G):  # doctest: +SKIP
    ...    print(line)

    Notes
    -----
    This implementation does not support mixed graphs (directed and unidirected
    edges together) hyperedges, nested graphs, or ports.
    )r   r   N)r   r   ÚstrÚ
splitlines)r   r   r   r   Úliner   r   r   r   ™   s    
Úrbc             C   st   t ||d}t|| dƒ}t|ƒdkrld}|  d¡ |  ¡ }| d|¡}t||dƒ}t|ƒdkrlt d¡‚|d S )a!  Read graph in GraphML format from path.

    Parameters
    ----------
    path : file or string
       File or filename to write.
       Filenames ending in .gz or .bz2 will be compressed.

    node_type: Python type (default: str)
       Convert node ids to this type

    edge_key_type: Python type (default: int)
       Convert graphml edge ids to this type as key of multi-edges


    Returns
    -------
    graph: NetworkX graph
        If no parallel edges are found a Graph or DiGraph is returned.
        Otherwise a MultiGraph or MultiDiGraph is returned.

    Notes
    -----
    Default node and edge attributes are not propagated to each node and edge.
    They can be obtained from `G.graph` and applied to node and edge attributes
    if desired using something like this:

    >>> default_color = G.graph['node_default']['color']  # doctest: +SKIP
    >>> for node, data in G.nodes(data=True):  # doctest: +SKIP
    ...     if 'color' not in data:
    ...         data['color']=default_color
    >>> default_color = G.graph['edge_default']['color']  # doctest: +SKIP
    >>> for u, v, data in G.edges(data=True):  # doctest: +SKIP
    ...     if 'color' not in data:
    ...         data['color']=default_color

    This implementation does not support mixed graphs (directed and unidirected
    edges together), hypergraphs, nested graphs, or ports.

    For multigraphs the GraphML edge "id" will be used as the edge
    key.  If not specified then they "key" attribute will be used.  If
    there is no "key" attribute a default NetworkX multigraph edge key
    will be provided.

    Files with the yEd "yfiles" extension will can be read but the graphics
    information is discarded.

    yEd compressed files ("file.graphmlz" extension) can be read by renaming
    the file to "file.graphml.gz".

    )Ú	node_typeÚedge_key_type)r   r   s7   <graphml xmlns="http://graphml.graphdrawing.org/xmlns">s	   <graphml>)Ústringz%file not successfully read as graphml)r   ÚlistÚlenÚseekÚreadÚreplaceÚnxÚNetworkXError)r   r%   r&   ÚreaderÚglistÚheaderZ	old_bytesZ	new_bytesr   r   r   r
   ¸   s    5

c             C   s`   t |d}t|| dƒ}t|ƒdkrXd}|  d|¡}t||dƒ}t|ƒdkrXt d¡‚|d S )a‚  Read graph in GraphML format from string.

    Parameters
    ----------
    graphml_string : string
       String containing graphml information
       (e.g., contents of a graphml file).

    node_type: Python type (default: str)
       Convert node ids to this type

    Returns
    -------
    graph: NetworkX graph
        If no parallel edges are found a Graph or DiGraph is returned.
        Otherwise a MultiGraph or MultiDiGraph is returned.

    Examples
    --------
    >>> G = nx.path_graph(4)
    >>> linefeed = chr(10)  # linefeed = 

    >>> s = linefeed.join(nx.generate_graphml(G))
    >>> H = nx.parse_graphml(s)

    Notes
    -----
    Default node and edge attributes are not propagated to each node and edge.
    They can be obtained from `G.graph` and applied to node and edge attributes
    if desired using something like this:

    >>> default_color = G.graph['node_default']['color']  # doctest: +SKIP
    >>> for node, data in G.nodes(data=True):  # doctest: +SKIP
    ...    if 'color' not in data:
    ...        data['color']=default_color
    >>> default_color = G.graph['edge_default']['color']  # doctest: +SKIP
    >>> for u, v, data in G.edges(data=True):  # doctest: +SKIP
    ...    if 'color' not in data:
    ...        data['color']=default_color

    This implementation does not support mixed graphs (directed and unidirected
    edges together), hypergraphs, nested graphs, or ports.

    For multigraphs the GraphML edge "id" will be used as the edge
    key.  If not specified then they "key" attribute will be used.  If
    there is no "key" attribute a default NetworkX multigraph edge key
    will be provided.

    )r%   )r'   r   z7<graphml xmlns="http://graphml.graphdrawing.org/xmlns">z	<graphml>z%file not successfully read as graphml)r   r(   r)   r,   r-   r.   )Zgraphml_stringr%   r/   r0   r1   Z
new_stringr   r   r   r   ü   s    1

c               @   sX  e Zd ZdZdZdZd ddg¡Zyedƒ e	Z
eZW n ek
rJ   Y nX edfe	dfe	d	fe
d	fed
fedfedfedfedfg	ZyddlZW n   Y nŠX ejdfejdfejdfejdfejd
fejd
fejd
fejd
fejd
fejd
fejd
fejd
fejd
fejd
fej d
fej!d
fge Ze"eƒZ#e"dd„ eD ƒƒZ$dddddddœZ%dS )ÚGraphMLz%http://graphml.graphdrawing.org/xmlnsz)http://www.w3.org/2001/XMLSchema-instancez!http://www.yworks.com/xml/graphmlú z5http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsdi90  ZintegerÚyfilesr'   ÚintÚlongÚfloatZdoubleZbooleanr   Nc             c   s   | ]}t |ƒV  qd S )N)Úreversed)Ú.0Úar   r   r   ú	<genexpr>c  s    zGraphML.<genexpr>TF)ÚtrueÚfalseÚ0r   Ú1r   )&Ú__name__Ú
__module__Ú__qualname__Ú
NS_GRAPHMLÚNS_XSIÚNS_YÚjoinÚSCHEMALOCATIONÚchrr!   Úunicoder5   r6   Ú
ValueErrorr7   ÚboolÚtypesZnumpyZnpZfloat64Zfloat32Zfloat16Zfloat_Zint8Zint16Zint32Zint64Zuint8Zuint16Zuint32Zuint64Zint_ZintcZintpÚdictÚxml_typeÚpython_typeÚconvert_boolr   r   r   r   r2   :  sD   
r2   c               @   sr   e Zd Zddd„Zdd„ Zd	d
„ Zdd„ Zd dd„Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zd!dd„ZdS )"r   Núutf-8TFc             C   s’   ydd l }W n  tk
r,   d}t|ƒ‚Y nX t| _|| _|| _|| _|  d| j| j| j	dœ¡| _
i | _ttƒ| _ttƒ| _|d k	rŽ|  |¡ d S )Nr   z3GraphML writer requires xml.elementtree.ElementTreeÚgraphml)Úxmlnsz	xmlns:xsizxsi:schemaLocation)Úxml.etree.ElementTreeÚImportErrorr   Ú	myElementr   r   r   rC   rD   rG   ÚxmlÚkeysr   r(   Ú
attributesÚsetÚattribute_typesr   )Úselfr   r   r   r   rW   Úmsgr   r   r   Ú__init__s  s$    

zGraphMLWriter.__init__c             C   s(   | j r|  | j¡ t| jƒ | j¡}|S )N)r   ÚindentrW   r   Údecoder   )r\   Úsr   r   r   Ú__str__Š  s    zGraphMLWriter.__str__c             C   s¢   | j r–| j||f }ytdƒ t}t}W n tk
rD   t}t}Y nX t|ƒdkrˆt|kr^tS ||krj|S t	|krvt	S ||kr‚|S tS qžt
|ƒd S nt|ƒS dS )aˆ  Infer the attribute type of data named name. Currently this only
        supports inference of numeric types.

        If self.infer_numeric_types is false, type is used. Otherwise, pick the
        most general of types found across all values with name and scope. This
        means edges with data named 'weight' are treated separately from nodes
        with data named 'weight'.
        i90  r   r   N)r   r[   rH   r5   r!   rJ   r6   rI   r)   r7   r(   Útype)r\   ÚnameÚscopeÚvaluerL   Z
local_longZlocal_unicoder   r   r   Ú	attr_type  s*    	
zGraphMLWriter.attr_typec       
      C   s˜   |||f}y
| j | S  tk
r’   dtt| j ƒƒ }|| j |< ||||dœ}| jd|Ž}|d k	r€|  d¡}	t|ƒ|	_| |	¡ | j 	d|¡ Y nX |S )Nzd%i)ÚidÚforz	attr.namez	attr.typeÚkeyÚdefaultr   )rj   )
rX   ÚKeyErrorr)   r(   rV   r   ÚtextÚappendrW   Úinsert)
r\   rd   rg   re   rk   Zkeys_keyZnew_idZ
key_kwargsZkey_elementZdefault_elementr   r   r   Úget_keyµ  s"    





zGraphMLWriter.get_keyÚallc       	      C   sN   || j krd}t || ¡‚|  || j | ||¡}| jd|d}t|ƒ|_|S )zn
        Make a data element for an edge or a node. Keep a log of the
        type in the keys table.
        z2GraphML writer does not support %s as data values.Údata)rj   )rN   r-   r.   rp   rV   r   rm   )	r\   rd   Úelement_typerf   re   rk   r]   ZkeyidÚdata_elementr   r   r   Úadd_dataÉ  s    

zGraphMLWriter.add_datac          	   C   sT   xN|  ¡ D ]B\}}| jt|ƒ|f  t|ƒ¡ | j|  |||| |¡g¡ q
W dS )z€Appends attribute data to edges or nodes, and stores type information
        to be added later. See add_graph_element.
        N)Úitemsr[   r   Úaddrc   rY   rn   Úget)r\   re   Úxml_objrr   rk   ÚkÚvr   r   r   Úadd_attributesØ  s    zGraphMLWriter.add_attributesc             C   sX   |j  di ¡}xD|jddD ]4\}}| jdt|ƒd}|  d|||¡ | |¡ qW d S )NÚnode_defaultT)rr   Únode)rh   )r   rx   ÚnodesrV   r   r|   rn   )r\   r   Úgraph_elementrk   r~   rr   Znode_elementr   r   r   Ú	add_nodesà  s
    zGraphMLWriter.add_nodesc       	      C   sÐ   |  ¡ rpxÂ|jdddD ]R\}}}}| jdt|ƒt|ƒt|ƒd}|j di ¡}|  d|||¡ | |¡ qW n\xZ|jddD ]J\}}}| jdt|ƒt|ƒd}|j di ¡}|  d|||¡ | |¡ q~W d S )NT)rr   rX   Úedge)ÚsourceÚtargetrh   Úedge_default)rr   )rƒ   r„   )Úis_multigraphÚedgesrV   r   r   rx   r|   rn   )	r\   r   r€   Úur{   rj   rr   Úedge_elementrk   r   r   r   Ú	add_edgesç  s    zGraphMLWriter.add_edgesc             C   sð   |  ¡ rd}nd}|j dd¡}|dkr8| jd|d}n| jd||d}i }dd	„ |j ¡ D ƒ}|  d|||¡ |  ||¡ |  ||¡ xV| j ¡ D ]H\}}x>|D ]6\}}	}
}| 	|  
t|ƒ|  ||
|	¡t|	ƒ|
|¡¡ q¢W q”W | j 	|¡ dS )
z=
        Serialize graph G in GraphML to the stream.
        ÚdirectedÚ
undirectedrh   Nr   )Úedgedefault)r   rh   c             S   s   i | ]\}}|d kr||“qS ))r}   r…   r   )r9   rz   r{   r   r   r   ú
<dictcomp>
  s    z3GraphMLWriter.add_graph_element.<locals>.<dictcomp>)Úis_directedr   ÚpoprV   rv   r|   r   rŠ   rY   rn   ru   r   rg   rW   )r\   r   Údefault_edge_typeÚgraphidr€   rk   rr   ry   rz   r{   re   r   r   r   r   ø  s*    
zGraphMLWriter.add_graph_elementc             C   s   x|D ]}|   |¡ qW dS )z+ Add many graphs to this GraphML document. N)r   )r\   Z
graph_listr   r   r   r   Ú
add_graphs  s    
zGraphMLWriter.add_graphsc             C   s2   | j r|  | j¡ t| jƒ}|j|| jdd d S )NT)r   Zxml_declaration)r   r_   rW   r   Úwriter   )r\   ÚstreamZdocumentr   r   r   r      s    
zGraphMLWriter.dumpr   c             C   s˜   d|d  }t |ƒrz|jr$|j ¡ s.|d |_|jr>|j ¡ sD||_x|D ]}|  ||d ¡ qJW |jrr|j ¡ s”||_n|r”|jrŽ|j ¡ s”||_d S )NÚ
z  r   )r)   rm   ÚstripÚtailr_   )r\   ÚelemÚlevelÚir   r   r   r_   &  s    

zGraphMLWriter.indent)NrQ   TF)rq   N)r   )r@   rA   rB   r^   rb   rg   rp   ru   r|   r   rŠ   r   r“   r   r_   r   r   r   r   r   r  s    
% 
#c               @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚIncrementalElementzÉWrapper for _IncrementalWriter providing an Element like interface.

    This wrapper does not intend to be a complete implementation but rather to
    deal with those calls used in GraphMLWriter.
    c             C   s   || _ || _d S )N)rW   r   )r\   rW   r   r   r   r   r^   >  s    zIncrementalElement.__init__c             C   s   | j j|| jd d S )N)Úpretty_print)rW   r”   r   )r\   Úelementr   r   r   rn   B  s    zIncrementalElement.appendN)r@   rA   rB   Ú__doc__r^   rn   r   r   r   r   rœ   7  s   rœ   c               @   s6   e Zd Zddd„Zdd„ Zd	d
„ Zdd„ Zdd„ ZdS )r    Núutf-8TFc             C   sœ   t j| _|| _|| _|| _t j||d| _| j ¡ | _	| j	 
¡  g | _| j| _| j	 d| j| j| jdœ¡| _| j ¡  i | _ttƒ| _|d k	r˜|  |¡ d S )N)r   rR   )rS   z	xmlns:xsizxsi:schemaLocation)Ú	lxmletreer   rV   Z	_encodingÚ_prettyprintr   ZxmlfileÚ	_xml_baseÚ	__enter__Ú_xmlZwrite_declarationrW   Z_keysrž   rC   rD   rG   Ú_graphmlrX   r   rZ   r[   r   )r\   r   r   r   r   r   r   r   r   r^   G  s&    


zGraphMLWriterLxml.__init__c          	   C   sp  |  ¡ rd}nd}|j dd¡}|dkr:| jjd|d}n| jjd||d}dd	„ |j ¡ D ƒ}|j d
i ¡}|j di ¡}x0| ¡ D ]$\}}	| jt|ƒdf  	t
|	ƒ¡ q†W x<| ¡ D ]0\}}	| j|  |d|	¡ }
|  t|ƒ|
dd¡ q¸W i }x^|jddD ]N\}}xD| ¡ D ]8\}}	| jt|ƒdf  	t
|	ƒ¡ ||kr|	||< qW qþW xD| ¡ D ]8\}}	| j|  |d|	¡ }|  t|ƒ|d| |¡¡ qZW | ¡ rTi }xf|jdddD ]T\}}	}}xD| ¡ D ]8\}}	| jt|ƒdf  	t
|	ƒ¡ ||krÊ|	||< qÊW q´W xô| ¡ D ]8\}}	| j|  |d|	¡ }|  t|ƒ|d| |¡¡ qW n®i }xb|jddD ]R\}}	}xD| ¡ D ]8\}}	| jt|ƒdf  	t
|	ƒ¡ ||krz|	||< qzW qfW xD| ¡ D ]8\}}	| j|  |d|	¡ }|  t|ƒ|d| |¡¡ qÆW x"| jD ]}| jj|| jd q
W t| j| jƒ}|. |  d||i ¡ |  ||¡ |  ||¡ W dQ R X dS )z=
        Serialize graph G in GraphML to the stream.
        r‹   rŒ   rh   Nr   )r   )r   rh   c             S   s   i | ]\}}|d kr||“qS ))r}   r…   r   )r9   rz   r{   r   r   r   rŽ   |  s    z7GraphMLWriterLxml.add_graph_element.<locals>.<dictcomp>r}   r…   T)rr   r~   )rX   rr   r‚   )r   )r   r   r   r¥   rž   rv   rx   r[   r   rw   rc   rN   rg   rp   r   r†   r‡   rW   r”   r¢   rœ   r|   r   rŠ   )r\   r   r‘   r’   r€   Z	graphdatar}   r…   rz   r{   rs   rY   r~   ÚdÚTrˆ   Zekeyrj   Zincremental_writerr   r   r   r   g  sj    
 
 

"
 z#GraphMLWriterLxml.add_graph_elementc          
   C   sR   xL|  ¡ D ]@\}}|  t|ƒ|  t|ƒ||¡t|ƒ|| |¡¡}| |¡ q
W dS )zAppends attribute data.N)rv   ru   r   rg   rx   rn   )r\   re   ry   rr   rk   rz   r{   rt   r   r   r   r|   ±  s
    
z GraphMLWriterLxml.add_attributesc             C   s
   t  | ¡S )N)Úobjectrb   )r\   r   r   r   rb   ¹  s    zGraphMLWriterLxml.__str__c             C   s$   | j  d d d ¡ | j d d d ¡ d S )N)r¦   Ú__exit__r£   )r\   r   r   r   r   ¼  s    zGraphMLWriterLxml.dump)Nr    TF)r@   rA   rB   r^   r   r|   rb   r   r   r   r   r   r    F  s    
Jr    c               @   sR   e Zd ZdZeefdd„Zddd„Zddd„Zd	d
„ Z	dd„ Z
dd„ Zdd„ ZdS )r   z:Read a GraphML document.  Produces NetworkX graph objects.c             C   sJ   ydd l }W n  tk
r,   d}t|ƒ‚Y nX || _|| _d| _i | _d S )Nr   z3GraphML reader requires xml.elementtree.ElementTreeF)rT   rU   r%   r&   Ú
multigraphÚedge_ids)r\   r%   r&   rW   r]   r   r   r   r^   Ë  s    zGraphMLReader.__init__Nc             c   sr   |d k	rt |d| _n|d k	r*t|ƒ| _ntdƒ‚|  | j¡\}}x*| j d| j ¡D ]}|  |||¡V  qVW d S )N)Úfilez/Must specify either 'path' or 'string' as kwargz	{%s}graph)r   rW   r   rJ   Úfind_graphml_keysÚfindallrC   Ú
make_graph)r\   r   r'   rX   ÚdefaultsÚgr   r   r   Ú__call__Ö  s    zGraphMLReader.__call__c             C   sˆ  |  dd ¡}|d kr.|dkr&t ¡ }nt ¡ }i |jd< i |jd< xx| ¡ D ]l\}}|| d }|| d }	|| d }
|dkr˜|jd  |	|
|ƒi¡ |d	krL|jd  |	|
|ƒi¡ qLW | d
| j ¡}|d k	rÞt 	d¡‚x(| 
d| j ¡D ]}|  ||||¡ qðW x(| 
d| j ¡D ]}|  |||¡ qW |  ||¡}|j |¡ | js„| ¡ rht |¡}n
t |¡}tj|| jdd |S )Nr   r‹   r}   r…   ri   rd   rc   r~   r‚   z{%s}hyperedgez)GraphML reader doesn't support hyperedgesz{%s}nodez{%s}edgerh   )Úvaluesrd   )rx   r-   ZMultiDiGraphZ
MultiGraphr   rv   ÚupdateÚfindrC   r.   r¯   Úadd_nodeÚadd_edgeÚdecode_data_elementsr«   r   ZDiGraphZGraphZset_edge_attributesr¬   )r\   Ú	graph_xmlÚgraphml_keysr±   r   r   Zkey_idrf   Zkey_forrd   rO   Z	hyperedgeÚnode_xmlZedge_xmlrr   r   r   r   r°   á  s<    





zGraphMLReader.make_graphc       	      C   s€   |  d| j ¡}|dk	r"t d¡ |  | d¡¡}|  ||¡}|j|f|Ž |j d¡dkr||  d| j ¡}|  	||||¡ dS )z!Add a node to the graph.
        z{%s}portNzGraphML port tag not supported.rh   zyfiles.foldertypeÚgroupz	{%s}graph)
r¶   rC   ÚwarningsÚwarnr%   rx   r¹   r·   Zattribr°   )	r\   r   r¼   r»   r±   ÚportsZnode_idrr   rº   r   r   r   r·     s    
zGraphMLReader.add_nodec             C   s
  |  d| j ¡}|dk	r"t d¡ | d¡}| ¡ rJ|dkrJd}t |¡‚| ¡ sh|dkrhd}t |¡‚|  | d	¡¡}|  | d
¡¡}|  	||¡}	| d¡}
|
rÖ|
| j
||f< y|  |
¡}
W qà tk
rÒ   Y qàX n
|	 d¡}
| ||¡ròd| _| |||
|	fg¡ dS )z"Add an edge to the graph.
        z{%s}portNzGraphML port tag not supported.r‹   r=   z,directed=false edge found in directed graph.r<   z-directed=true edge found in undirected graph.rƒ   r„   rh   rj   T)r¶   rC   r¾   r¿   rx   r   r-   r.   r%   r¹   r¬   r&   rJ   Zhas_edger«   Zadd_edges_from)r\   r   r‰   r»   rÀ   r‹   r]   rƒ   r„   rr   Zedge_idr   r   r   r¸     s0    





zGraphMLReader.add_edgec          	   C   s˜  i }xŒ|  d| j ¡D ]v}| d¡}y|| d }|| d }W n" tk
rf   t d| ¡‚Y nX |j}|dk	r°tt|ƒƒdkr°|t	kr¢| j
| ¡  ||< n||ƒ||< qtt|ƒƒdkrd}	xhdD ]`}
d	| j|
| jf }| d
| ¡}|dk	r| d¡|d< | d¡|d< |	dkrÊ| d| ¡}	qÊW |	dk	rB|	j|d< x:dD ]2}d	| j|| jf }| d| ¡}|dk	rHP qHW |dk	r|j|d< qW |S )z:Use the key information to decode the data XML if present.z{%s}datarj   rd   rc   zBad GraphML data: no key %sNr   )Z	ShapeNodeZSVGNodeZ	ImageNodez{%s}%s/{%s}z
%sGeometryÚxÚyz%sNodeLabelZlabel)ZPolyLineEdgeZ
SplineEdgeZQuadCurveEdgeZ
BezierEdgeZArcEdgez%sEdgeLabel)r¯   rC   rx   rl   r-   r.   rm   r)   r(   rK   rP   ÚlowerrE   r¶   )r\   r»   Zobj_xmlrr   rt   rj   Z	data_nameZ	data_typerm   Z
node_labelr%   ZprefZgeometryÚeZ
edge_labelr   r   r   r¹   F  sB    






z"GraphMLReader.decode_data_elementsc       
      C   sÐ   i }i }x¾|  d| j ¡D ]ª}| d¡}| d¡}| d¡}| d¡}|dk	rV|}d}|dkrpd}t d	| ¡ |dkr†t d
| ¡‚|| j| | d¡dœ||< | d| j ¡}	|	dk	r|	j	||< qW ||fS )z=Extracts all the keys and key defaults from the xml.
        z{%s}keyrh   z	attr.typez	attr.namezyfiles.typeNr4   r'   z#No key type for id %s. Using stringzUnknown key for id %s.ri   )rd   rc   ri   z{%s}default)
r¯   rC   rx   r¾   r¿   r-   r.   rO   r¶   rm   )
r\   r€   r»   Zgraphml_key_defaultsrz   Zattr_idrg   Z	attr_nameZyfiles_typerk   r   r   r   r®   t  s,    



zGraphMLReader.find_graphml_keys)NN)N)r@   rA   rB   rŸ   r!   r5   r^   r³   r°   r·   r¸   r¹   r®   r   r   r   r   r   È  s   

+).c             C   s2   ddl m} ydd l}W n   |dƒ‚Y nX d S )Nr   )ÚSkipTestz#xml.etree.ElementTree not available)ZnoserÅ   rT   )ÚmodulerÅ   rW   r   r   r   Úsetup_module‘  s
    rÇ   c             C   s(   dd l }y| d¡ W n   Y nX d S )Nr   ztest.graphml)ÚosÚunlink)rÆ   rÈ   r   r   r   Úteardown_moduleš  s
    rÊ   )r   TF)r   TF)r   T)$rŸ   r¾   Úcollectionsr   Zxml.etree.cElementTreer   r   r   r   rU   rT   Z
lxml.etreeZetreer¡   Znetworkxr-   Znetworkx.utilsr   r   Ú__all__r   r   r   r!   r5   r
   r   r©   r2   r   rœ   r    r	   r   rÇ   rÊ   r   r   r   r   Ú<module>-   sT   


 '
 &

C>8 F|
 J	