σ
mάJ]c           @` s-  d  Z  d d l m Z m Z m Z m Z d d l Z e j e  Z	 d d l
 m Z d d l m Z d d l m Z d d l m Z d d l m Z m Z d	 d
 l m Z d	 d l m Z m Z m Z d	 d l m Z d d l m Z m Z m  Z  m! Z! m" Z" d d l# m$ Z$ d Z% d e& f d     YZ' d S(   uΆ    Implements a very low level facility for communicating with a Bokeh
Server.

Users will always want to use :class:`~bokeh.client.session.ClientSession`
instead for standard usage.

i    (   t   absolute_importt   divisiont   print_functiont   unicode_literalsN(   t
   quote_plus(   t   gen(   t   HTTPRequest(   t   IOLoop(   t   websocket_connectt   WebSocketErrori   (   t   Protocol(   t   MessageErrort   ProtocolErrort   ValidationError(   t   Receiveri   (   t   NOT_YET_CONNECTEDt   CONNECTED_BEFORE_ACKt   CONNECTED_AFTER_ACKt   DISCONNECTEDt   WAITING_FOR_REPLY(   t    WebSocketClientConnectionWrapperu   ClientConnectiont   ClientConnectionc           B` sR  e  Z d  Z d d d  Z e d    Z e d    Z e d    Z d   Z	 d d  Z
 d   Z d	   Z d
   Z d   Z d   Z e j d    Z d   Z e j d    Z e j d    Z d   Z e j d    Z e j d    Z d   Z d   Z d   Z d   Z e j d    Z e j d    Z e j d    Z RS(   us    A Bokeh low-level class used to implement ``ClientSession``; use ``ClientSession`` to connect to the server.

    c         C` s   | |  _  | |  _ | |  _ t d  |  _ t |  j  |  _ d |  _ t	   |  _
 | d k ri t   } n  | |  _ d |  _ d |  _ d S(   u6    Opens a websocket connection to the server.

        u   1.0N(   t   _urlt   _sessiont
   _argumentsR
   t	   _protocolR   t	   _receivert   Nonet   _socketR   t   _stateR   t   _loopt   _until_predicatet   _server_info(   t   selft   sessiont   websocket_urlt   io_loopt	   arguments(    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   __init__A   s    						c         C` s   t  |  j t  S(   ug    Whether we've connected the Websocket and have exchanged initial
        handshake messages.

        (   t
   isinstanceR   R   (   R!   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt	   connectedV   s    c         C` s   |  j  S(   u2    The Tornado ``IOLoop`` this connection is using. (   R   (   R!   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyR$   ^   s    c         C` s   |  j  S(   u1    The URL of the websocket this Connection is to. (   R   (   R!   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   urld   s    c         ` s      f d   }   j  |  d  S(   Nc           ` s"   t    j t  p! t    j t  S(   N(   R'   R   R   R   (    (   R!   (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   connected_or_closedl   s    (   t   _loop_until(   R!   R*   (    (   R!   s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   connectk   s    u   closedc         C` s)   |  j  d k	 r% |  j  j d |  n  d S(   u*    Close the Websocket connection.

        iθ  N(   R   R   t   close(   R!   t   why(    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyR-   r   s    c         C` s   |  j    d S(   u   Force a round-trip request/reply to the server, sometimes needed to
        avoid race conditions. Mostly useful for testing.

        Outside of test suites, this method hurts performance and should not be
        needed.

        Returns:
           None

        N(   t   _send_request_server_info(   R!   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   force_roundtripy   s    c         ` sK   t    j t  r+   j   t     _ n   f d   }   j |  d S(   u6   Execute a blocking loop that runs and executes event callbacks
        until the connection is closed (e.g. by hitting Ctrl-C).

        While this method can be used to run Bokeh application code "outside"
        the Bokeh server, this practice is HIGHLY DISCOURAGED for any real
        use case.

        c           ` s   t    j t  S(   N(   R'   R   R   (    (   R!   (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   closed   s    N(   R'   R   R   t   _tell_session_about_disconnectR   R+   (   R!   R1   (    (   R!   s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   loop_until_closed   s
    	
c         C` sz   |  j  j d  } |  j |  } | d k r< t d   n: | j d d k ri t d | j d   n | j |  d S(   uί    Pull a document from the server, overwriting the passed-in document

        Args:
            document : (Document)
              The document to overwrite with server content.

        Returns:
            None

        u   PULL-DOC-REQu   Connection to server was lostu   msgtypeu   ERRORu   Failed to pull document: u   textN(   R   t   createt   _send_message_wait_for_replyR   t   RuntimeErrort   headert   contentt   push_to_document(   R!   t   documentt   msgt   reply(    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   pull_doc   s    c         C` st   |  j  j d |  } |  j |  } | d k r? t d   n1 | j d d k rl t d | j d   n | Sd S(   uδ    Push a document to the server, overwriting any existing server-side doc.

        Args:
            document : (Document)
                A Document to push to the server

        Returns:
            The server reply

        u   PUSH-DOCu   Connection to server was lostu   msgtypeu   ERRORu   Failed to push document: u   textN(   R   R4   R5   R   R6   R7   R8   (   R!   R:   R;   R<   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   push_doc­   s    c         C` s(   |  j  d k r! |  j   |  _  n  |  j  S(   uq    Ask for information about the server.

        Returns:
            A dictionary of server attributes.

        N(   R    R   R/   (   R!   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   request_server_infoΑ   s    c         c` s   |  j  d  k r" t j d |  n` y* | j |  j   V} t j d | |  Wn3 t k
 r } t j d |  |  j d d  n Xt j	 d    d  S(   Nu-   We're disconnected, so not sending message %ru   Sent %r [%d bytes]u#   Error sending message to server: %rR.   u   received error while sending(
   R   R   t   logt   infot   sendt   debugR	   R-   R   t   Return(   R!   t   messaget   sentt   e(    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   send_messageΜ   s    c         C` s}   d |  j  |  j j f } |  j d  k	 ry xN |  j j   D]: \ } } | d j t t |   t t |    7} q8 Wn  | S(   Nu1   %s?bokeh-protocol-version=1.0&bokeh-session-id=%su   &{}={}(	   R   R   t   idR   R   t   itemst   formatR   t   str(   R!   t   versioned_urlt   keyt   value(    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   _versioned_urlξ   s
    5c         c` s   |  j    } t |  } y  t |  V} t |  |  _ Wn# t k
 r] } t j d |  n X|  j d  k r{ |  j	   Vn |  j
 t    Vd  S(   Nu   Failed to connect to server: %r(   RP   R   R   R   R   t	   ExceptionR@   RA   R   t   _transition_to_disconnectedt   _transitionR   (   R!   RM   t   requestt   socketRG   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   _connect_asyncυ   s    c         c` su   |  j    V} | d  k r' |  j   VnJ | j d k rV t j d  |  j j |  n t j d |  |  j   Vd  S(   Nu	   PATCH-DOCu"   Got PATCH-DOC, applying to sessionu   Ignoring %r(	   t   _pop_messageR   RR   t   msgtypeR@   RC   R   t   _handle_patcht   _next(   R!   RE   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   _handle_messages  s    c         C` sR   | |  _  y$ |  j j |  j  |  j j   Wn t k
 rM |  j d  n Xd  S(   Nu   user interruption(   R   R   t   add_callbackRZ   t   startt   KeyboardInterruptR-   (   R!   t	   predicate(    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyR+     s    	c         c` s   |  j  d  k	 re |  j    re t j d |  j j j |  j  j  d  |  _  |  j j   t	 j
 d    n+ t j d |  j j j  |  j j |   Vd  S(   Nu4   Stopping client loop in state %s due to True from %su   Running state (   R   R   R@   RC   R   t	   __class__t   __name__R   t   stopR   RD   t   run(   R!   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyRZ     s    		c         c` s(  x!t  r#|  j d  k r* t j d    n  d  } y |  j j   V} Wn# t k
 ri } t j d |  n X| d  k r t j	 d  t j d    n  yF |  j
 j |  V} | d  k	 rΪ t j d |  t j |   n  Wq t t t f k
 r} t j d | d t  |  j d d  q Xq Wd  S(   Nu   Error reading from socket %ru   Connection closed by serveru   Received message %ru   %rt   exc_infoR.   u!   error parsing message from server(   t   TrueR   R   R   RD   t   read_messageRQ   R@   RC   RA   R   t   consumeR   R   R   t   errorR-   (   R!   t   fragmentRG   RE   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyRW   )  s&    	c         ` s   t  | j d      _ g    f d   }   j j   j |  |      f d   }   j |     f d   }   j |   j S(   Nu   msgidc         ` s     j  |   d  S(   N(   t   append(   t   future(   t   send_result(    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   message_sentI  s    c           ` s   t    d k p   j  k S(   Ni    (   t   lenR   (    (   R!   Rl   t   waiter(    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt    have_send_result_or_disconnectedM  s    c           ` s     j   k p  j d  k	 S(   N(   R   R<   R   (    (   R!   Ro   (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   have_reply_or_disconnectedQ  s    (   R   R7   R   R   t
   add_futureRH   R+   R<   (   R!   RE   Rm   Rp   Rq   (    (   R!   Rl   Ro   s6   lib/python2.7/site-packages/bokeh/client/connection.pyR5   D  s    	c         C` so   d d l  m } t | d  r@ t | j |  r@ d  | j _ n  |  j j d | g d t	 } |  j
 |  d  S(   Ni    (   t   ColumnDataChangedEventu   hintu	   PATCH-DOCt   use_buffers(   t   bokeh.document.eventsRs   t   hasattrR'   t   hintR   t   colsR   R4   t   FalseRH   (   R!   t
   session_idt   eventRs   R;   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   _send_patch_documentW  s
    !c         C` sC   |  j  j d  } |  j |  } | d  k r< t d   n  | j S(   Nu   SERVER-INFO-REQu<   Did not get a reply to server info request before disconnect(   R   R4   R5   R   R6   R8   (   R!   R;   R<   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyR/   c  s
    c         C` s   |  j  r |  j  j   n  d  S(   N(   R   t   _notify_disconnected(   R!   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyR2   j  s    	c         c` s/   t  j d | j j  | |  _ |  j   Vd  S(   Nu   transitioning to state (   R@   RC   R`   Ra   R   RZ   (   R!   t	   new_state(    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyRS   n  s    	c         c` s   |  j    |  j t    Vd  S(   N(   R2   RS   R   (   R!   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyRR   t  s    
c         c` st   |  j    V} | rF | j d k rF t j d |  |  j t    Vn* | d  k r` |  j   Vn t d |   d  S(   Nu   ACKu   Received %ru   Received %r instead of ACK(	   RW   RX   R@   RC   RS   R   R   RR   R   (   R!   RE   (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   _wait_for_acky  s    N(    Ra   t
   __module__t   __doc__R   R&   t   propertyR(   R$   R)   R,   R-   R0   R3   R=   R>   R?   R   t	   coroutineRH   RP   RV   R[   R+   RZ   RW   R5   R|   R/   R2   RS   RR   R   (    (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyR   <   s4   						"						(   u   ClientConnection((   R   t
   __future__R    R   R   R   t   loggingt	   getLoggerRa   R@   t   six.moves.urllib.parseR   t   tornadoR   t   tornado.httpclientR   t   tornado.ioloopR   t   tornado.websocketR   R	   t   protocolR
   t   protocol.exceptionsR   R   R   t   protocol.receiverR   t   statesR   R   R   R   R   t	   websocketR   t   __all__t   objectR   (    (    (    s6   lib/python2.7/site-packages/bokeh/client/connection.pyt   <module>   s   "	(