ó
ù2¢\c           @   sF  d  Z  d d l m Z d d l m Z m Z d d l m Z d d l Z d d l m	 Z	 m
 Z
 d d l m Z d d l m Z m Z d d	 l m Z d d
 l m Z d d l m Z m Z m Z m Z m Z m Z m Z m Z m Z m Z m Z d d l  m! Z! m" Z" d d l# m$ Z$ m% Z% d d l& m' Z' d e f d „  ƒ  YZ( d S(   sf   A MultiKernelManager for use in the notebook webserver

- raises HTTPErrors
- creates REST API models
iÿÿÿÿ(   t   defaultdict(   t   datetimet	   timedelta(   t   partialN(   t   gent   web(   t   Future(   t   IOLoopt   PeriodicCallback(   t   Session(   t   MultiKernelManager(   t   Anyt   Boolt   Dictt   Listt   Unicodet
   TraitErrort   Integert   Floatt   Instancet   defaultt   validate(   t
   to_os_patht   exists(   t   utcnowt	   isoformat(   t   getcwdt   MappingKernelManagerc           B   s  e  Z d  Z e d ƒ d „  ƒ Z e e ƒ  ƒ Z e d e ƒ Z	 e
 ƒ  Z d& Z e Z e d ƒ d „  ƒ Z e d ƒ d „  ƒ Z e d d e d d	 ƒZ d
 Z e e d e d d ƒZ e e d e d d ƒZ e e d e d d ƒZ e e d e d d ƒZ e d d e d d ƒZ e ƒ  Z e d ƒ d „  ƒ Z e  e! d d ƒZ" d „  Z# d „  Z$ d „  Z% e& j' d& d& d „ ƒ Z( d „  Z) d „  Z* d „  Z+ e d „ Z, e& j' d „  ƒ Z- d „  Z. d „  Z/ d „  Z0 d  „  Z1 d! „  Z2 d" „  Z3 d# „  Z4 d$ „  Z5 d% „  Z6 RS('   sE   A KernelManager that handles notebook mapping and HTTP error handlingt   kernel_manager_classc         C   s   d S(   Ns)   jupyter_client.ioloop.IOLoopKernelManager(    (   t   self(    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   _default_kernel_manager_class!   s    t   configt   root_dirc         C   s*   y |  j  j SWn t k
 r% t ƒ  SXd  S(   N(   t   parentt   notebook_dirt   AttributeErrorR   (   R   (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   _default_root_dir/   s    c         C   sh   | d } t  j j | ƒ s1 t  j j | ƒ } n  t | ƒ sQ t  j j | ƒ rd t d | ƒ ‚ n  | S(   s'   Do a bit of validation of the root dir.t   values%   kernel root dir %r is not a directory(   t   ost   patht   isabst   abspathR   t   isdirR   (   R   t   proposalR%   (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   _update_root_dir6   s    
 i    t   helpsê   Timeout (in seconds) after which a kernel is considered idle and ready to be culled.
        Values of 0 or lower disable culling. Very short timeouts may result in kernels being culled
        for users with poor network connections.i,  s^   The interval (in seconds) on which to check for idle kernels exceeding the cull timeout value.sx   Whether to consider culling kernels which have one or more connections.
        Only effective if cull_idle_timeout > 0.sd   Whether to consider culling kernels which are busy.
        Only effective if cull_idle_timeout > 0.se  Whether messages from kernels whose frontends have disconnected should be buffered in-memory.

        When True (default), messages are buffered and replayed on reconnect,
        avoiding lost messages due to interrupted connectivity.

        Disable if long-running kernels will produce too much output while
        no frontends are connected.
        i<   sÂ  Timeout for giving up on a kernel (in seconds).

        On starting and restarting kernels, we check whether the
        kernel is running and responsive by sending kernel_info_requests.
        This sets the timeout in seconds for how long the kernel can take
        before being presumed dead. 
        This affects the MappingKernelManager (which handles kernel restarts) 
        and the ZMQChannelsHandler (which handles the startup).
        t   _kernel_buffersc         C   s   t  d „  ƒ S(   Nc           S   s   i g  d 6d d 6i  d 6S(   Nt   buffert    t   session_keyt   channels(    (    (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   <lambda>p   R0   (   R    (   R   (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   _default_kernel_buffersn   s    sA   The last activity on any kernel, including shutting down a kernelc         K   s&   t  t |  ƒ j |   t ƒ  |  _ d  S(   N(   t   superR   t   __init__R   t   last_kernel_activity(   R   t   kwargs(    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyR6   u   s    c         C   s$   |  j  j d | ƒ |  j | ƒ d S(   s   notice that a kernel dieds"   Kernel %s died, removing from map.N(   t   logt   warningt   remove_kernel(   R   t	   kernel_id(    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   _handle_kernel_died}   s    c         C   sQ   t  | |  j ƒ } x8 t j j | ƒ rL | |  j k rL t j j | ƒ } q W| S(   s$   Turn API path into absolute OS path.(   R   R    R&   R'   R*   t   dirname(   R   R'   t   os_path(    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   cwd_for_path‚   s    %c         +   sþ   ˆ  d k r´ | d k	 r. ˆ j | ƒ | d <n  t j t t ˆ ƒ j |   ƒ V‰  d ˆ j ˆ  <ˆ j ˆ  ƒ ˆ j	 j
 d ˆ  ƒ ˆ j	 j d | ƒ ˆ j ˆ  ‡  ‡ f d †  d ƒ n! ˆ j ˆ  ƒ ˆ j	 j
 d ˆ  ƒ ˆ j së ˆ j ƒ  n  t j ˆ  ƒ ‚ d S(	   ss  Start a kernel for a session and return its kernel_id.

        Parameters
        ----------
        kernel_id : uuid
            The uuid to associate the new kernel with. If this
            is not None, this kernel will be persistent whenever it is
            requested.
        path : API path
            The API path (unicode, '/' delimited) for the cwd.
            Will be transformed to an OS path relative to root_dir.
        kernel_name : str
            The name identifying which kernel spec to launch. This is ignored if
            an existing kernel is returned, but it may be checked in the future.
        t   cwdi    s   Kernel started: %ss   Kernel args: %rc              s   ˆ j  ˆ  ƒ S(   N(   R=   (    (   R<   R   (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyR3   ¨   R0   t   deads   Using existing kernel: %sN(   t   NoneR@   R   t   maybe_futureR5   R   t   start_kernelt   _kernel_connectionst   start_watching_activityR9   t   infot   debugt   add_restart_callbackt   _check_kernel_idt   _initialized_cullert   initialize_cullert   Return(   R   R<   R'   R8   (    (   R<   R   sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyRE   ‹   s"    	
	c            sØ   ˆ j  s4 x$ | j ƒ  D] \ } } | j ƒ  q Wd Sˆ j j d | ƒ ˆ j ˆ ƒ ˆ j ˆ ƒ ˆ j ˆ ‰  | ˆ  d <g  ˆ  d <| ˆ  d <‡  ‡ ‡ f d †  } x0 | j ƒ  D]" \ } } | j t	 | | ƒ ƒ q® Wd S(   sÜ  Start buffering messages for a kernel

        Parameters
        ----------
        kernel_id : str
            The id of the kernel to stop buffering.
        session_key: str
            The session_key, if any, that should get the buffer.
            If the session_key matches the current buffered session_key,
            the buffer will be returned.
        channels: dict({'channel': ZMQStream})
            The zmq channels whose messages should be buffered.
        Ns   Starting buffering for %sR1   R/   R2   c            s1   ˆ j  j d ˆ |  ƒ ˆ  d j |  | f ƒ d  S(   Ns   Buffering msg on %s:%sR/   (   R9   RI   t   append(   t   channelt	   msg_parts(   t   buffer_infoR<   R   (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt
   buffer_msgÖ   s    (
   t   buffer_offline_messagest   itemst   closeR9   RH   RK   t   stop_bufferingR.   t   on_recvR   (   R   R<   R1   R2   RP   t   streamRS   (    (   RR   R<   R   sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   start_buffering¶   s    	


c         C   sh   |  j  j d | ƒ | |  j k r& d S|  j | } | d | k rW |  j j | ƒ | S|  j | ƒ d S(   ss  Get the buffer for a given kernel

        Parameters
        ----------
        kernel_id : str
            The id of the kernel to stop buffering.
        session_key: str, optional
            The session_key, if any, that should get the buffer.
            If the session_key matches the current buffered session_key,
            the buffer will be returned.
        s   Getting buffer for %sNR1   (   R9   RI   R.   t   popRW   (   R   R<   R1   RR   (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt
   get_bufferÝ   s    c         C   s½   |  j  j d | ƒ |  j | ƒ | |  j k r3 d S|  j j | ƒ } x> | d j ƒ  D], } | j ƒ  sV | j d ƒ | j	 ƒ  qV qV W| d } | r¹ |  j  j
 d t | ƒ | d ƒ n  d S(   sš   Stop buffering kernel messages

        Parameters
        ----------
        kernel_id : str
            The id of the kernel to stop buffering.
        s   Clearing buffer for %sNR2   R/   s&   Discarding %s buffered messages for %sR1   (   R9   RI   RK   R.   R[   t   valuest   closedRX   RC   RV   RH   t   len(   R   R<   RR   RY   t
   msg_buffer(    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyRW   ö   s    
c         C   s„   |  j  | ƒ |  j | } | j r< | j j ƒ  d | _ n  |  j | ƒ |  j j | d ƒ t ƒ  |  _	 t
 t |  ƒ j | d | ƒS(   s   Shutdown a kernel by kernel_idt   nowN(   RK   t   _kernelst   _activity_streamRV   RC   RW   RF   R[   R   R7   R5   R   t   shutdown_kernel(   R   R<   Ra   t   kernel(    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyRd     s    	c         #   s  ˆ j  ˆ ƒ t j t t ˆ ƒ j ˆ ƒ ƒ Vˆ j ˆ ƒ ‰ ˆ j ƒ  ‰  t ƒ  ‰ ‡  ‡ ‡ ‡ ‡ f d †  ‰ ‡ ‡ ‡ ‡ f d †  } ‡ ‡ ‡ ‡ f d †  } ‡ ‡ ‡ ‡ f d †  ‰ ˆ j	 ˆ d ƒ ˆ j
 j ˆ  d ƒ ˆ  j | ƒ t j ƒ  ‰ ˆ j ˆ j ƒ  ˆ j | ƒ ‰ ˆ Vd S(   s   Restart a kernel by kernel_idc              s:   ˆ  j  ƒ  s ˆ  j ƒ  n  ˆ j ˆ ƒ ˆ j ˆ d ƒ d S(   s:   Common cleanup when restart finishes/fails for any reason.RB   N(   R^   RV   t   remove_timeoutt   remove_restart_callback(    (   RP   Re   t   loopt   on_restart_failedt   timeout(    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   finish%  s    c            s:   ˆ j  j d ˆ ƒ ˆ  ƒ  ˆ j ƒ  s6 ˆ j |  ƒ n  d  S(   Ns   Kernel info reply received: %s(   R9   RI   t   donet
   set_result(   t   msg(   Rk   t   futureR<   R   (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   on_reply,  s    c              sC   ˆ j  j d ˆ ƒ ˆ  ƒ  ˆ j ƒ  s? ˆ j t j d ƒ ƒ n  d  S(   Ns)   Timeout waiting for kernel_info_reply: %ss   Timeout waiting for restart(   R9   R:   Rl   t   set_exceptionR   t   TimeoutError(    (   Rk   Ro   R<   R   (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt
   on_timeout2  s    c              s@   ˆ j  j d ˆ ƒ ˆ  ƒ  ˆ j ƒ  s< ˆ j t d ƒ ƒ n  d  S(   Ns   Restarting kernel failed: %ss   Restart failed(   R9   R:   Rl   Rq   t   RuntimeError(    (   Rk   Ro   R<   R   (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyRi   8  s    RB   t   kernel_info_requestN(   RK   R   RD   R5   R   t   restart_kernelt
   get_kernelt   connect_shellR   RJ   t   sessiont   sendRX   R   t   currentt   add_timeoutt   timet   kernel_info_timeout(   R   R<   Rp   Rs   (    (	   RP   Rk   Ro   Re   R<   Rh   Ri   R   Rj   sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyRv     s     	c         C   s)   | |  j  k r% |  j  | c d 7<n  d S(   s#   Notice a new connection to a kerneli   N(   RF   (   R   R<   (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   notify_connectF  s    c         C   s)   | |  j  k r% |  j  | c d 8<n  d S(   s$   Notice a disconnection from a kerneli   N(   RF   (   R   R<   (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   notify_disconnectK  s    c         C   s]   |  j  | ƒ |  j | } i | d 6| j d 6t | j ƒ d 6| j d 6|  j | d 6} | S(   sq   Return a JSON-safe dict representing a kernel

        For use in representing kernels in the JSON APIs.
        t   idt   namet   last_activityt   execution_statet   connections(   RK   Rb   t   kernel_nameR   Rƒ   R„   RF   (   R   R<   Re   t   model(    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   kernel_modelP  s    

c         C   sL   g  } t  t |  ƒ j ƒ  } x* | D]" } |  j | ƒ } | j | ƒ q" W| S(   s1   Returns a list of kernel_id's of kernels running.(   R5   R   t   list_kernel_idsRˆ   RO   (   R   t   kernelst
   kernel_idsR<   R‡   (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   list_kernelsa  s    c         C   s)   | |  k r% t  j d d | ƒ ‚ n  d S(   s5   Check a that a kernel_id exists and raise 404 if not.i”  u   Kernel does not exist: %sN(   R   t	   HTTPError(   R   R<   (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyRK   k  s    c            s~   ˆ j  ˆ ‰  d ˆ  _ t ƒ  ˆ  _ ˆ  j ƒ  ˆ  _ t d ˆ  j j d ˆ  j j	 ƒ ‰ ‡  ‡ ‡ ‡ f d †  } ˆ  j j
 | ƒ d S(   s¯   Start watching IOPub messages on a kernel for activity.
        
        - update last_activity on every message
        - record execution_state from status messages
        t   startingR   t   keyc            s   t  ƒ  ˆ _ ˆ  _ ˆ j |  ƒ \ } } ˆ j | ƒ } | d d } ˆ j j d ˆ | ƒ | d k r{ | d d ˆ  _ n  d S(   s.   Record an IOPub message arriving from a kernelt   headert   msg_types   activity on %s: %st   statust   contentR„   N(   R   R7   Rƒ   t   feed_identitiest   deserializeR9   RI   R„   (   t   msg_listt   identst   fed_msg_listRn   R‘   (   Re   R<   R   Ry   (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   record_activity‚  s    N(   Rb   R„   R   Rƒ   t   connect_iopubRc   R	   Ry   R   R   RX   (   R   R<   R™   (    (   Re   R<   R   Ry   sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyRG   r  s    	c         C   sþ   |  j  rñ |  j d k rñ |  j d k rñ t j ƒ  } |  j d k rn |  j j d |  j |  j	 ƒ |  j	 |  _ n  t
 |  j d |  j ƒ |  _ |  j j d |  j |  j ƒ |  j rÂ |  j j d ƒ n  |  j rÞ |  j j d ƒ n  |  j j ƒ  qñ n  t |  _  d S(   s‰   Start idle culler if 'cull_idle_timeout' is greater than zero.

        Regardless of that value, set flag that we've been here.
        i    sK   Invalid value for 'cull_interval' detected (%s) - using default value (%s).iè  sK   Culling kernels with idle durations > %s seconds at %s second intervals ...s   Culling kernels even if busys+   Culling kernels even with connected clientsN(   RL   t   cull_idle_timeoutt   _culler_callbackRC   R   R{   t   cull_intervalR9   R:   t   cull_interval_defaultR   t   cull_kernelsRH   t	   cull_busyt   cull_connectedt   startt   True(   R   Rh   (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyRM     s"    		c         C   sw   |  j  j d |  j |  j ƒ xT t |  j ƒ D]C } y |  j | ƒ Wq, t k
 rn } |  j  j d | | ƒ q, Xq, Wd  S(   Ns9   Polling every %s seconds for kernels idle > %s seconds...sY   The following exception was encountered while checking the idle duration of kernel %s: %s(	   R9   RI   R   R›   t   listRb   t   cull_kernel_if_idlet	   Exceptiont	   exception(   R   R<   t   e(    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyRŸ   ¨  s    c   
      C   s  |  j  | } |  j j d | | j | j ƒ | j d  k	 rt ƒ  } | | j } | t d |  j ƒ k } |  j	 p~ | j
 d k } |  j j | d ƒ } |  j p£ | } | r| r| rt | j ƒ  ƒ }	 |  j j d | j
 | j | | |	 ƒ |  j | ƒ qn  d  S(   Ns.   kernel_id=%s, kernel_name=%s, last_activity=%st   secondst   busyi    sR   Culling '%s' kernel '%s' (%s) with %d connections due to %s seconds of inactivity.(   Rb   R9   RI   R†   Rƒ   RC   R   R   R›   R    R„   RF   t   getR¡   t   intt   total_secondsR:   Rd   (
   R   R<   Re   t   dt_nowt   dt_idlet   is_idle_timet   is_idle_executeR…   t   is_idle_connectedt   idle_duration(    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyR¥   ³  s    	N(7   t   __name__t
   __module__t   __doc__R   R   R   R   t   kernel_argvR£   R    R   RF   RC   Rœ   t   FalseRL   R$   R   R,   R   R›   Rž   R   R   R¡   R    RT   R   R~   R   R.   R4   R   R   R7   R6   R=   R@   R   t	   coroutineRE   RZ   R\   RW   Rd   Rv   R   R€   Rˆ   RŒ   RK   RG   RM   RŸ   R¥   (    (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyR      sZ   															*	'		+				
				()   R¶   t   collectionsR    R   R   t	   functoolsR   R&   t   tornadoR   R   t   tornado.concurrentR   t   tornado.ioloopR   R   t   jupyter_client.sessionR	   t!   jupyter_client.multikernelmanagerR
   t	   traitletsR   R   R   R   R   R   R   R   R   R   R   t   notebook.utilsR   R   t   notebook._tzR   R   t   ipython_genutils.py3compatR   R   (    (    (    sF   lib/python2.7/site-packages/notebook/services/kernels/kernelmanager.pyt   <module>   s   L