B
    U[|                 @   sx  d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlmZm	Z	m
Z
 ddlZddlZddlZyddlmZ W n ek
r   ejZY nX ddlmZ dd	lmZ dd
lmZmZ ddl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)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 ddlm2Z2 ddl3m4Z4 dZ5dZ6dZ7G dd deZ8dS )z9Base class for a kernel that talks to frontends over 0MQ.    )print_function)datetime)partialN)signaldefault_int_handlerSIGINT)utcnow)ioloop)gen)PriorityQueue
QueueEmpty)	ZMQStream)SingletonConfigurable)StdinNotImplementedError)	py3compat)unicode_typestring_types)
json_clean)AnyInstanceFloatDictListSetIntegerUnicodeBoolobservedefault)Session   )kernel_protocol_version
      c            
       sB  e Zd ZedZeddd ZeeddZ	edddZ
e ZeeddZe Ze Ze ZeejddZedZe Zed	d
d Zi Ze ZedddjddZedZ e! Z"edZ#e$djddZ%e$djddZ&e$ddddZ'dZ(e! Z)e* Z+dZ,dddddddddd g
Z-e-d!d"g Z. fd#d$Z/e0j1d%d& Z2d'd( Z3e0j1d)d* Z4d+d, Z5d-d. Z6d/d0 Z7e0j1d1d2 Z8e0j1dd3d4Z9e0j1d5d6 Z:ed7dZ;ed8d9d: Z<d;d< Z=d=d> Z>d?d@ Z?dAdB Z@ddCdDZAdEdF ZBddGdHZCdIdJ ZDdKdL ZEe0j1dMdN ZFddOdPZGe0j1dQdR ZHdSdT ZIe0j1dUdV ZJddWdXZKe0j1dYdZ ZLdd[d\ZMd]d^ ZNeOd_d` ZPdadb ZQdcdd ZRe0j1dedf ZSdgdh ZTe0j1didj ZUdkdl ZVdmdn ZWdodp ZXdqdr ZYdsdt ZZdudv Z[dwdx Z\edZ]e0j1dydz Z^e0j1d{d| Z_e0j1d}d~ Z`dd ZadddZbdddZcdddZddd Ze  ZfS )KernelN	eventloopc             C   s$   t j }|jdk	r || j dS )z&schedule call to eventloop from IOLoopN)r	   IOLoopcurrentnewadd_callbackenter_eventloop)selfZchangeloop r-   3lib/python3.7/site-packages/ipykernel/kernelbase.py_update_eventloop:   s    

zKernel._update_eventloopT)Z
allow_nonez"IPython.core.profiledir.ProfileDiridentc             C   s   t t S )N)r   uuidZuuid4)r+   r-   r-   r.   _default_identN   s    zKernel._default_identzhWhether to use appnope for compatibility with OS X App Nap.

        Only affects OS X >= 10.9.
        )help)configF    gMb@?g{Gz?g?a  time (in seconds) to wait for messages to arrive
        when aborting queued requests after an error.

        Requests that arrive within this window after an error
        will be cancelled.

        Increase in the event of unusually slow network
        causing significant delays,
        which can manifest as e.g. "Run all" in a notebook
        aborting some, but not all, messages after an error.
        )r5   r4   r   execute_requestcomplete_requestinspect_requesthistory_requestcomm_info_requestkernel_info_requestconnect_requestshutdown_requestis_complete_requestapply_requestclear_requestabort_requestc                sb   t t| jf | i | _x| jD ]}t| || j|< q W i | _x| jD ]}t| || j|< qFW d S )N)superr$   __init__shell_handlers	msg_typesgetattrcontrol_handlerscontrol_msg_types)r+   kwargsmsg_type)	__class__r-   r.   rD      s    zKernel.__init__c             c   s(  | j j|dd\}}y| j j|ddd}W n   | jjddd dS | jd| | || | d	 | jr| 	| j
|| | d
 dS |d }|d }| j|d}|dkr| jd| nByt|| j
||V  W n& tk
r   | jjddd Y nX tj  tj  | d
 dS )zdispatch control requestsF)copyT)contentrM   zInvalid Control Message)exc_infoNzControl received: %sbusyidleheaderrK   z UNKNOWN CONTROL MESSAGE TYPE: %rzException in control handler:)sessionfeed_identitiesdeserializelogerrordebug
set_parent_publish_status	_aborting_send_abort_replycontrol_streamrH   getr
   maybe_future	Exceptionsysstdoutflushstderr)r+   msgidentsrR   rK   handlerr-   r-   r.   dispatch_control   s2    



zKernel.dispatch_controlc             C   sD   |d d }|| j kr@|d d }| j | | ||| dS dS )zCheck whether a shell-channel message should be handled

        Allows subclasses to prevent handling of certain messages (e.g. aborted requests).
        rR   msg_idrK   FT)abortedremover\   )r+   streamre   rf   ri   rK   r-   r-   r.   should_handle   s    
zKernel.should_handlec             c   s  | j r| j   | jj|dd\}}y| jj|ddd}W n   | jjddd dS | || | d | j	r| 
||| | d	 dS |d
 d }| jd| | jd|d  | |||sdS | j|d}|dkr| jd| n| jd|| y|   W n& tk
r4   | jjddd Y nX zDyt||||V  W n& tk
rv   | jjddd Y nX W dy|   W n& tk
r   | jjddd Y nX X tj  tj  | d	 dS )zdispatch shell requestsF)rM   T)rN   rM   zInvalid Message)rO   NrP   rQ   rR   rK   z
*** MESSAGE TYPE:%s***z   Content: %s
   --->
   rN   zUnknown message type: %rz%s: %sz%Unable to signal in pre_handler_hook:zException in message handler:z&Unable to signal in post_handler_hook:)r]   rc   rS   rT   rU   rV   rW   rY   rZ   r[   r\   rX   rm   rE   r^   warningpre_handler_hookr`   r
   r_   post_handler_hookra   rb   rd   )r+   rl   re   rf   rK   rg   r-   r-   r.   dispatch_shell   sL    




zKernel.dispatch_shellc             C   s   t tt| _dS )z.Hook to execute before calling message handlerN)r   r   r   saved_sigint_handler)r+   r-   r-   r.   ro     s    zKernel.pre_handler_hookc             C   s   t t| j dS )z-Hook to execute after calling message handlerN)r   r   rr   )r+   r-   r-   r.   rp     s    zKernel.post_handler_hookc                s>   j dj jfdd  fdd  dS )zenter eventloopzEntering eventloop %sc                  s   j  k	rjd  d S j r<jd   d S jd  y  W n  tk
rv   jd Y nX j  kr  d S )Nzexiting eventloop %sz*Delaying eventloop due to waiting messageszAdvancing eventloop %sz"KeyboardInterrupt caught in kernel)r%   rV   info	msg_queueZqsizerX   KeyboardInterruptrW   r-   )r%   schedule_nextr+   r-   r.   advance_eventloop&  s    


z1Kernel.enter_eventloop.<locals>.advance_eventloopc                  s   j d jd  dS )z*Schedule the next advance of the eventloopzScheduling eventloop advancer    N)rV   rX   io_loopZ
call_laterr-   )rw   r+   r-   r.   rv   ;  s    z-Kernel.enter_eventloop.<locals>.schedule_nextN)rV   rs   r%   )r+   r-   )rw   r%   rv   r+   r.   r*   !  s
    zKernel.enter_eventloopc             c   sD   x| j D ]}|  qW d}x"|dk	r>|tk r>| jddV }qW dS )zProcess a single shell message

        Any pending control messages will be flushed as well

        .. versionchanged:: 5
            This is now a coroutine
        r   NF)wait)shell_streamsrc   SHELL_PRIORITYprocess_one)r+   rl   priorityr-   r-   r.   do_one_iterationE  s
    
zKernel.do_one_iterationc             c   sZ   |r| j  V \}}}}n,y| j  \}}}}W n tk
rD   dS X t|| V  dS )z~Process one request

        Returns priority of the message handled.
        Returns None if no message was handled.
        N)rt   r^   Z
get_nowaitr   r
   r_   )r+   ry   r}   tdispatchargsr-   r-   r.   r|   W  s    zKernel.process_onec             c   s:   x4y|   V  W q tk
r0   | jd Y qX qW dS )zCoroutine to preserve order of message handling

        Ensures that only one message is processing at a time,
        even when the handler is async
        zError in message handlerN)r|   r`   rV   Z	exception)r+   r-   r-   r.   dispatch_queueg  s
    zKernel.dispatch_queuezsMonotonic counter of messages

        Ensures messages of the same priority are handled in arrival order.
        _message_counterc             C   s   t  S )N)	itertoolscount)r+   r-   r-   r.   _message_counter_default|  s    zKernel._message_counter_defaultc             G   s2   t | j}| j||||f | jdd  dS )zschedule a message for dispatchc               S   s   d S )Nr-   r-   r-   r-   r.   <lambda>  s    z*Kernel.schedule_dispatch.<locals>.<lambda>N)nextr   rt   Z
put_nowaitrx   r)   )r+   r}   r   r   idxr-   r-   r.   schedule_dispatch  s    
zKernel.schedule_dispatchc             C   s   t j | _t | _| j| j | jrD| jj	t
| jt| jdd x6| jD ],}|| jkr\qL|j	t
| jt| j|dd qLW | d dS )z register dispatchers for streamsF)rM   ZstartingN)r	   r&   r'   rx   r   rt   r)   r   r]   Zon_recvr   r   CONTROL_PRIORITYrh   rz   r{   rq   rZ   )r+   sr-   r-   r.   start  s*    
zKernel.startc             C   s
   || _ dS )zRecord the ports that this kernel is using.

        The creator of the Kernel instance must call this methods if they
        want the :meth:`connect_request` method to return the port numbers.
        N)_recorded_ports)r+   Zportsr-   r-   r.   record_ports  s    zKernel.record_portsc             C   s(   | j j| jd||d|| dd dS )z-Publish the code request on the iopub stream.Zexecute_input)codeexecution_count)parentr1   N)rS   sendiopub_socket_topic)r+   r   r   r   r-   r-   r.   _publish_execute_input  s    zKernel._publish_execute_inputc             C   s,   | j j| jdd|i|p| j| dd dS )z send status (busy/idle) on IOPubstatusZexecution_state)r   r1   N)rS   r   r   _parent_headerr   )r+   r   r   r-   r-   r.   rZ     s
    
zKernel._publish_statusc             C   s   || _ || _dS )a  Set the current parent_header

        Side effects (IOPub messages) and replies are associated with
        the request that caused them via the parent_header.

        The parent identity is used to route input_request messages
        on the stdin channel.
        N)_parent_identr   )r+   r1   r   r-   r-   r.   rY     s    	zKernel.set_parentc	       	      C   s   | j |||| j|||||	S )a  Send a response to the message we're currently processing.

        This accepts all the parameters of :meth:`jupyter_client.session.Session.send`
        except ``parent``.

        This relies on :meth:`set_parent` having been called for the current
        message.
        )rS   r   r   )	r+   rl   Zmsg_or_typerN   r1   buffersZtrackrR   metadatar-   r-   r.   send_response  s    
zKernel.send_responsec             C   s
   dt  iS )zRInitialize metadata.

        Run at the beginning of execution requests.
        Zstarted)now)r+   r   r-   r-   r.   init_metadata  s    zKernel.init_metadatac             C   s   |S )zXFinish populating metadata.

        Run after completing an execution request.
        r-   )r+   r   r   reply_contentr-   r-   r.   finish_metadata  s    zKernel.finish_metadatac          	   c   sN  yH|d }t |d }|d }|d| }|di }|dd}	W n$   | jd | jd	| d
S |dd}
| |}|s|  jd7  _| ||| j t	| 
|||||	V }tj  tj  | jrt| j t|}| |||}| jj|d||||d}| jd	| |sJ|d d dkrJ|
rJ|  V  d
S )zhandle an execute_requestrN   r   silentstore_historyuser_expressionsallow_stdinFzGot bad msg: z%sNstop_on_errorTr    Zexecute_reply)r   r1   r   rW   )r   Zcast_unicode_py2r^   rV   rW   r   r   r   r
   r_   
do_executera   rb   rc   rd   _execute_sleeptimesleepr   r   rS   r   rX   _abort_queues)r+   rl   r1   r   rN   r   r   r   r   r   r   r   r   	reply_msgr-   r-   r.   r7     s@    



zKernel.execute_requestc             C   s   t dS )z=Execute user code. Must be overridden by subclasses.
        N)NotImplementedError)r+   r   r   r   r   r   r-   r-   r.   r   0  s    zKernel.do_executec       	      c   sL   |d }|d }|d }t | ||V }t|}| j|d|||}d S )NrN   r   
cursor_posZcomplete_reply)r
   r_   do_completer   rS   r   )	r+   rl   r1   r   rN   r   r   matchesZcompletion_msgr-   r-   r.   r8   6  s    
zKernel.complete_requestc             C   s   g ||i ddS )z4Override in subclasses to find completions.
        ok)r   Z
cursor_endZcursor_startr   r   r-   )r+   r   r   r-   r-   r.   r   A  s
    zKernel.do_completec          
   c   s\   |d }t | |d |d |ddV }t|}| j|d|||}| jd| d S )NrN   r   r   detail_levelr   Zinspect_replyz%s)	r
   r_   
do_inspectr^   r   rS   r   rV   rX   )r+   rl   r1   r   rN   r   re   r-   r-   r.   r9   J  s    

zKernel.inspect_requestc             C   s   di i ddS )z7Override in subclasses to allow introspection.
        r   F)r   datar   foundr-   )r+   r   r   r   r-   r-   r.   r   Z  s    zKernel.do_inspectc             c   sJ   |d }t | jf |V }t|}| j|d|||}| jd| d S )NrN   Zhistory_replyz%s)r
   r_   
do_historyr   rS   r   rV   rX   )r+   rl   r1   r   rN   r   re   r-   r-   r.   r:   _  s    

zKernel.history_requestc
       
      C   s
   dg dS )z2Override in subclasses to access history.
        r   )r   historyr-   )
r+   Zhist_access_typeoutputrawrS   r   stopnpatternuniquer-   r-   r.   r   j  s    zKernel.do_historyc             C   sH   | j d k	r| j  }ni }d|d< | j|d|||}| jd| d S )Nr   r   Zconnect_replyz%s)r   rM   rS   r   rV   rX   )r+   rl   r1   r   rN   re   r-   r-   r.   r=   p  s    


zKernel.connect_requestc             C   s   t | j| j| j| j| jdS )N)Zprotocol_versionimplementationimplementation_versionlanguage_infobanner
help_links)r!   r   r   r   r   r   )r+   r-   r-   r.   kernel_infoz  s    zKernel.kernel_infoc             C   s:   ddi}| | j | j|d|||}| jd| d S )Nr   r   Zkernel_info_replyz%s)updater   rS   r   rV   rX   )r+   rl   r1   r   rN   re   r-   r-   r.   r<     s
    

zKernel.kernel_info_requestc                sp   |d }| dd  t| dr: fdd| jj D }ni }t|dd}| j|d|||}| j	d	| d S )
NrN   target_namecomm_managerc                s0   i | ](\}}|j  ks d krt|j d|qS )N)r   )r   dict).0kv)r   r-   r.   
<dictcomp>  s   z,Kernel.comm_info_request.<locals>.<dictcomp>r   )commsr   Zcomm_info_replyz%s)
r^   hasattrr   r   itemsr   rS   r   rV   rX   )r+   rl   r1   r   rN   r   r   re   r-   )r   r.   r;     s    



zKernel.comm_info_requestc             c   sn   t | |d d V }| jj|d|||d | jd||| _|   tj	
 }|t d |j d S )NrN   restartZshutdown_reply)r1   g?)r
   r_   do_shutdownrS   r   re   _shutdown_message_at_shutdownr	   r&   r'   Zadd_timeoutr   r   )r+   rl   r1   r   rN   r,   r-   r-   r.   r>     s    

zKernel.shutdown_requestc             C   s
   d|dS )z]Override in subclasses to do things when the frontend shuts down the
        kernel.
        r   )r   r   r-   )r+   r   r-   r-   r.   r     s    zKernel.do_shutdownc             c   sP   |d }|d }t | |V }t|}| j|d|||}| jd| d S )NrN   r   Zis_complete_replyz%s)r
   r_   do_is_completer   rS   r   rV   rX   )r+   rl   r1   r   rN   r   r   r   r-   r-   r.   r?     s    

zKernel.is_complete_requestc             C   s   ddiS )z4Override in subclasses to find completions.
        r   unknownr-   )r+   r   r-   r-   r.   r     s    zKernel.do_is_completec       
   	   C   s   | j d y |d }|d }|d d }W n   | j jd|dd d S | |}| ||||\}}	tj  tj  | 	|||}| j
j|d	||||	|d
 d S )NzBapply_request is deprecated in kernel_base, moving to ipyparallel.rN   r   rR   ri   zGot bad msg: %sT)rO   Zapply_reply)r   r1   r   r   )rV   rn   rW   r   do_applyra   rb   rc   rd   r   rS   r   )
r+   rl   r1   r   rN   bufsri   mdr   Z
result_bufr-   r-   r.   r@     s    


zKernel.apply_requestc             C   s   t dS )Z
DEPRECATEDN)r   )r+   rN   r   ri   Zreply_metadatar-   r-   r.   r     s    zKernel.do_applyc             C   s   | j d |d dd}t|tr,|g}|s8|   x|D ]}| jt| q>W t	dd}| j
j|d|||d}| j d	| dS )
zabort a specific msg by idzOabort_request is deprecated in kernel_base. It is only part of IPython parallelrN   msg_idsNr   )r   Zabort_reply)rN   r   r1   z%s)rV   rn   r^   
isinstancer   r   rj   addstrr   rS   r   rX   )r+   rl   r1   r   r   ZmidrN   r   r-   r-   r.   rB     s    



zKernel.abort_requestc             C   s.   | j d |  }| jj|d|||d dS )zClear our namespace.zOclear_request is deprecated in kernel_base. It is only part of IPython parallelZclear_reply)r1   r   rN   N)rV   rn   do_clearrS   r   )r+   rl   rf   r   rN   r-   r-   r.   rA     s    zKernel.clear_requestc             C   s   t dS )zDEPRECATED since 4.0.3N)r   )r+   r-   r-   r.   r     s    zKernel.do_clearc             C   s   d| j  }td||f S )z!prefixed topic for IOPub messagesz	kernel.%sz%s.%s)r1   r   Z
cast_bytes)r+   Ztopicbaser-   r-   r.   r     s    
zKernel._topicc             C   s0   x| j D ]}|  qW d| _| t| j d S )NT)rz   rc   r[   r   ABORT_PRIORITY_dispatch_abort)r+   rl   r-   r-   r.   r     s    zKernel._abort_queuesc             c   s$   | j d t| jV  d| _d S )NzFinishing abortF)rV   rs   r
   r   stop_on_error_timeoutr[   )r+   r-   r-   r.   r     s    zKernel._dispatch_abortc             C   sn   | j d | j d| |d d ddd d }d	d
i}d| ji}|| | jj||||||d dS )z"Send a reply to an aborted requestz	Aborting:z%srR   rK   _r    r   Z_replyr   rj   Zengine)r   rN   r   r1   N)rV   rs   rsplitr1   r   rS   r   )r+   rl   re   rf   Z
reply_typer   r   r-   r-   r.   r\     s    

zKernel._send_abort_replyc             C   s   t ddS )zNRaise StdinNotImplentedError if active frontend doesn't support
        stdin.z?raw_input was called, but this frontend does not support stdin.N)r   )r+   r-   r-   r.   _no_raw_input,  s    zKernel._no_raw_input c             C   sD   | j std|dk	r.ddl}|jdtdd | j|| j| jddS )	zForward getpass to frontends

        Raises
        ------
        StdinNotImplentedError if active frontend doesn't support stdin.
        zFgetpass was called, but this frontend does not support input requests.Nr   zTThe `stream` parameter of `getpass.getpass` will have no effect when using ipykernel   )
stacklevelT)password)_allow_stdinr   warningswarnUserWarning_input_requestr   r   )r+   promptrl   r   r-   r-   r.   getpass2  s    
zKernel.getpassc             C   s(   | j std| jt|| j| jddS )zForward raw_input to frontends

        Raises
        ------
        StdinNotImplentedError if active frontend doesn't support stdin.
        zHraw_input was called, but this frontend does not support input requests.F)r   )r   r   r   r   r   r   )r+   r   r-   r-   r.   	raw_inputG  s    
zKernel.raw_inputc       	   
   C   s0  t j  t j  xNy| jtj W q tjk
r^ } z|j	tj
krLP n W d d }~X Y qX qW tt||d}| jj| jd|||d xZy| j| jd\}}W n: tk
r   | jjddd Y q tk
r   tY qX P qW yt|d d	 }W n   | jd
| d}Y nX |dkr,t|S )N)r   r   Zinput_request)r1   r   zInvalid Message:T)rO   rN   valuezBad input_reply: %sr   )ra   rd   rc   rb   stdin_socketZrecv_multipartzmqZNOBLOCKZZMQErrorerrnoZEAGAINr   r   rS   r   Zrecvr`   rV   rn   ru   r   Zunicode_to_strrW   EOFError)	r+   r   r1   r   r   erN   Zreplyr   r-   r-   r.   r   X  s8    




zKernel._input_requestc             C   sJ   | j dk	r6| jj| j| j | dd | jd| j  dd | jD  dS )zLActions taken at shutdown by the kernel, called by python's atexit.
        NZshutdown)r1   z%sc             S   s   g | ]}| tjqS r-   )rc   r   ZPOLLOUT)r   r   r-   r-   r.   
<listcomp>  s    z'Kernel._at_shutdown.<locals>.<listcomp>)r   rS   r   r   r   rV   rX   rz   )r+   r-   r-   r.   r     s    
zKernel._at_shutdown)T)N)NNNFNN)TNF)r   )NNNNNF)r   N)r   )F)g__name__
__module____qualname__r   r%   r   r/   r   r   rS   Zprofile_dirr   rz   r   r]   r   Ziopub_threadr   loggingZLoggerrV   r   Zint_idr   r1   r   r3   r   r   r   tagZ_darwin_app_napr   r   r   r   r   r   Z_poll_intervalr   r   r   r   rj   r   rF   rI   rD   r
   	coroutinerh   rm   rq   ro   rp   r*   r~   r|   r   r   r   r   r   r   r   rZ   rY   r   r   r   r7   r   r8   r   r9   r   r:   r   r=   propertyr   r<   r;   r>   r   r?   r   r@   r   rB   rA   r   r   r[   r   r   r\   r   r   r   r   r   __classcell__r-   r-   )rL   r.   r$   1   s   $9$"
	 
7 
	
 





(r$   )9__doc__Z
__future__r   r   	functoolsr   r   r   r   r   r   ra   r   r2   Zjupyter_client.sessionr   r   ImportErrorZtornador	   r
   Ztornado.queuesr   r   r   Zzmq.eventloop.zmqstreamr   Ztraitlets.config.configurabler   ZIPython.core.errorr   Zipython_genutilsr   Zipython_genutils.py3compatr   r   Zipykernel.jsonutilr   Z	traitletsr   r   r   r   r   r   r   r   r   r   r   r   Z_versionr!   r   r{   r   r$   r-   r-   r-   r.   <module>   s<   4