U
    td(                     @   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   zObject 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 )zGenerates 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