U
    Ñtœd®(  ã                   @   sZ   d Z ddlZddlZddlZddlZdZdZG dd„ dƒZG dd„ dƒZ	G d	d
„ d
ƒZ
dS )zGClasses that help igraph communicate with Gephi (http://www.gephi.org).é    N)ÚGephiConnectionÚGephiGraphStreamerÚGephiGraphStreamingAPIFormatzrestructuredtext enc                   @   sd   e Zd ZdZddd„Zdd	„ Zd
d„ Zdd„ Zdd„ Ze	dd„ ƒZ
e
jdd„ ƒZ
dd„ Zdd„ ZdS )r   z=Object that represents a connection to a Gephi master server.Nú	127.0.0.1é�  é   c                 C   s$   g | _ d| _|p|  |||¡| _dS )a¹  Constructs a connection to a Gephi master server.

        The connection object can be constructed either by specifying the
        ``url`` directly, or by specifying the ``host``, ``port`` and
        ``workspace`` arguments.  The latter three are evaluated only if
        ``url`` is None; otherwise the ``url`` will take precedence.

        The ``url`` argument does not have to include the operation (e.g.,
        ``?operation=updateGraph``); the connection will take care of it.
        E.g., if you wish to connect to workspace 2 in a local Gephi instance
        on port 7341, the correct form to use for the ``url`` is as follows::

            http://localhost:7341/workspace0
        i   N)Ú_pending_operationsÚ_autoflush_thresholdÚ_construct_default_urlÚurl)Úselfr   ÚhostÚportÚ	workspace© r   úL/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/igraph/remote/gephi.pyÚ__init__   s    zGephiConnection.__init__c                 C   s*   z|   ¡  W n tjjk
r$   Y nX d S )N)ÚcloseÚurllibÚerrorÚURLError©r   r   r   r   Ú__del__%   s    zGephiConnection.__del__c                 C   s   d|||f S )Nzhttp://%s:%d/workspace%dr   )r   r   r   r   r   r   r   r
   ,   s    z&GephiConnection._construct_default_urlc                 C   s   |   ¡  dS )úZFlushes all the pending operations to the Gephi master server in a
        single request.N)Úflushr   r   r   r   r   /   s    zGephiConnection.closec                 C   s,   d  | j¡}g | _tjj| j|d�}| ¡ S )r   ó    )Údata)Újoinr   r   ÚrequestÚurlopenÚ_update_urlÚread)r   r   Úconnr   r   r   r   4   s    zGephiConnection.flushc                 C   s   | j S )z;The URL of the Gephi workspace where the data will be sent.)Ú	_url_rootr   r   r   r   r   <   s    zGephiConnection.urlc                 C   s"   || _ | j d | _| j d | _d S )Nz?operation=getGraphz?operation=updateGraph)r#   Z_get_urlr    )r   Úvaluer   r   r   r   A   s    c                 C   s(   | j  |¡ t| j ƒ| jkr$|  ¡  dS )z^Sends the given raw data to the Gephi streaming master server in an HTTP
        POST request.N)r   ÚappendÚlenr	   r   )r   r   r   r   r   ÚwriteG   s    zGephiConnection.writec                 C   s   d| j j| jf S )Nz
%s(url=%r))Ú	__class__Ú__name__r   r   r   r   r   Ú__repr__N   s    zGephiConnection.__repr__)Nr   r   r   )r)   Ú
__module__Ú__qualname__Ú__doc__r   r   r
   r   r   Úpropertyr   Úsetterr'   r*   r   r   r   r   r      s   


r   c                   @   sH   e Zd ZdZi fdd„Zi fdd„Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dS )r   z�Object that implements the Gephi graph streaming API format and returns
    Python objects corresponding to the events defined in the API.
    c                 C   s   d||iiS )a©  Generates a Python object corresponding to the event that adds a node
        with the given identifier and attributes in the Gephi graph streaming API.

        Example::

            >>> api = GephiGraphStreamingAPIFormat()
            >>> api.get_add_node_event("spam")
            {'an': {'spam': {}}}
            >>> api.get_add_node_event("spam", dict(ham="eggs"))
            {'an': {'spam': {'ham': 'eggs'}}}
        Zanr   ©r   Ú
identifierÚ
attributesr   r   r   Úget_add_node_eventW   s    z/GephiGraphStreamingAPIFormat.get_add_node_eventc                 C   s0   t |ƒ}||d< ||d< t|ƒ|d< d||iiS )z½Generates a Python object corresponding to the event that adds an edge
        with the given source, target, directednessr and attributes in the Gephi
        graph streaming API.
        ÚsourceÚtargetÚdirectedZae)ÚdictÚbool)r   r1   r4   r5   r6   r2   Úresultr   r   r   Úget_add_edge_evente   s
    z/GephiGraphStreamingAPIFormat.get_add_edge_eventc                 C   s   d||iiS )aA  Generates a Python object corresponding to the event that changes the
        attributes of some node in the Gephi graph streaming API. The given attributes
        are merged into the existing ones; use C{None} as the attribute value to
        delete a given attribute.

        Example::

            >>> api = GephiGraphStreamingAPIFormat()
            >>> api.get_change_node_event("spam", dict(ham="eggs"))
            {'cn': {'spam': {'ham': 'eggs'}}}
            >>> api.get_change_node_event("spam", dict(ham=None))
            {'cn': {'spam': {'ham': None}}}
        Zcnr   r0   r   r   r   Úget_change_node_eventp   s    z2GephiGraphStreamingAPIFormat.get_change_node_eventc                 C   s   d||iiS )aA  Generates a Python object corresponding to the event that changes the
        attributes of some edge in the Gephi graph streaming API. The given attributes
        are merged into the existing ones; use C{None} as the attribute value to
        delete a given attribute.

        Example::

            >>> api = GephiGraphStreamingAPIFormat()
            >>> api.get_change_edge_event("spam", dict(ham="eggs"))
            {'ce': {'spam': {'ham': 'eggs'}}}
            >>> api.get_change_edge_event("spam", dict(ham=None))
            {'ce': {'spam': {'ham': None}}}
        Zcer   r0   r   r   r   Úget_change_edge_event€   s    z2GephiGraphStreamingAPIFormat.get_change_edge_eventc                 C   s   d|i iiS )a1  Generates a Python object corresponding to the event that deletes a
        node with the given identifier in the Gephi graph streaming API.

        Example::

            >>> api = GephiGraphStreamingAPIFormat()
            >>> api.get_delete_node_event("spam")
            {'dn': {'spam': {}}}
        Údnr   ©r   r1   r   r   r   Úget_delete_node_event�   s    
z2GephiGraphStreamingAPIFormat.get_delete_node_eventc                 C   s   d|i iiS )a:  Generates a Python object corresponding to the event that deletes an
        edge with the given identifier in the Gephi graph streaming API.

        Example::

            >>> api = GephiGraphStreamingAPIFormat()
            >>> api.get_delete_edge_event("spam:ham")
            {'de': {'spam:ham': {}}}
        Úder   r>   r   r   r   Úget_delete_edge_eventœ   s    
z2GephiGraphStreamingAPIFormat.get_delete_edge_eventN)
r)   r+   r,   r-   r3   r:   r;   r<   r?   rA   r   r   r   r   r   R   s   r   c                   @   s6   e Zd ZdZddd„Zdd„ Zddd„Zdd
d„ZdS )r   aŸ  Class that produces JSON event objects that stream an igraph graph to
    Gephi using the Gephi Graph Streaming API.

    The Gephi graph streaming format is a simple JSON-based format that can be used
    to post mutations to a graph (i.e. node and edge additions, removals and updates)
    to a remote component. For instance, one can open up Gephi (http://www.gephi.org),
    install the Gephi graph streaming plugin and then send a graph from igraph
    straight into the Gephi window by using `GephiGraphStreamer` with the
    appropriate URL where Gephi is listening.

    Example::

        >>> from cStringIO import StringIO
        >>> from igraph import Graph
        >>> buf = StringIO()
        >>> streamer = GephiGraphStreamer()
        >>> graph = Graph.Formula("A --> B, B --> C")
        >>> streamer.post(graph, buf)
        >>> print(buf.getvalue())        # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
        {"an": {"igraph:...:v:0": {"name": "A"}}}
        {"an": {"igraph:...:v:1": {"name": "B"}}}
        {"an": {"igraph:...:v:2": {"name": "C"}}}
        {"ae": {"igraph:...:e:0:1": {...}}}
        {"ae": {"igraph:...:e:1:2": {...}}}
        <BLANKLINE>

    Nc                 C   s   |pt jdd�| _tƒ | _dS )a"  Constructs a Gephi graph streamer that will post graphs to a
        given file-like object or a Gephi connection.

        ``encoder`` must either be ``None`` or an instance of ``json.JSONEncoder``
        and it must contain the JSON encoder to be used when posting JSON objects.
        T)Úensure_asciiN)ÚjsonÚJSONEncoderÚencoderr   Úformat)r   rE   r   r   r   r   Æ   s    zGephiGraphStreamer.__init__c                 c   s˜   dt t|ƒƒf }| jj}|jD ]}|d||jf | ¡ ƒV  q | jj}| ¡ }|j	D ]<}|d||j
|jf d||j
f d||jf || ¡ ƒV  qVdS )a  Iterates over the JSON objects that build up the graph using the
        Gephi graph streaming API. The objects returned from this function are
        Python objects; they must be formatted with ``json.dumps`` before
        sending them to the destination.
        z	igraph:%sz%s:v:%dz
%s:e:%d:%dN)ÚhexÚidrF   r3   ÚvsÚindexr2   r:   Zis_directedÚesr4   r5   )r   ÚgraphZ	id_prefixÚadd_nodeZvertexZadd_edger6   Úedger   r   r   ÚiterjsonobjÐ   s    

ûzGephiGraphStreamer.iterjsonobjc                 C   s8   |p| j }|  |¡D ]}| j|||dd� q| ¡  dS )aC  Posts the given graph to the destination of the streamer using the
        given JSON encoder. When ``encoder`` is ``None``, it falls back to the
        default JSON encoder of the streamer in the `encoder` property.

        ``destination`` must be a file-like object or an instance of
        `GephiConnection`.
        F)rE   r   N)rE   rO   Ú
send_eventr   )r   rL   ÚdestinationrE   Zjsonobjr   r   r   Úpostë   s    
zGephiGraphStreamer.postTc                 C   s:   |p| j }| | |¡ d¡¡ | d¡ |r6| ¡  dS )aö  Sends a single JSON event to the given destination using the given
        JSON encoder.  When ``encoder`` is ``None``, it falls back to the
        default JSON encoder of the streamer in the `encoder` property.

        ``destination`` must be a file-like object or an instance of
        `GephiConnection`.

        The method flushes the destination after sending the event. If you want
        to avoid this (e.g., because you are sending many events), set
        ``flush`` to ``False``.
        zutf-8s   
N)rE   r'   Úencoder   )r   ÚeventrQ   rE   r   r   r   r   rP   ø   s
    

zGephiGraphStreamer.send_event)N)N)NT)r)   r+   r,   r-   r   rO   rR   rP   r   r   r   r   r   ©   s
   


r   )r-   rC   Úurllib.errorr   Úurllib.parseÚurllib.requestÚ__all__Ú__docformat__r   r   r   r   r   r   r   Ú<module>   s   DW