B
    F.\                 @   s
  d Z ddlmZ ddlZddlZyddlZW n ek
rH   ddlZY nX ddl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 dd
lmZ ddlmZmZ ddlmZ dZdd ZdddZdddZi e_dddZ dddZ!d ddZ"dS )!zUtilities for integrating with IPython

These functions should probably reside in Jupyter and IPython repositories,
after which we can import them instead of having our own definitions.
    )print_functionN)Popen)Thread)uuid4)TimeoutError)IOLoop)Event)get_ipython)BlockingKernelClientwrite_connection_file)jupyter_runtime_dir
   c             C   s0  | |}t| dd}|r2| jj}| jj}| jj}xy|jtd}W n tj	k
rb   t
dY nX |d d|krxq4|d d }	|d	 }
|	d
kr|
d dkrP q4|	dkrtt|
d }||
d  q4|	dkr4|r|j||	|
|d n<|	dkrtd|
d tjd ntj|
d dd q4q4W dS )ziRun a cell on a KernelClient

    Any output from the cell will be redisplayed in the local session.
    kernelF)timeoutz"Timeout waiting for IPython outputparent_headermsg_idheadermsg_typecontentZstatusZexecution_stateZidlestreamnametext)Zdisplay_dataZexecute_resulterror)parentr   
	traceback)filedataz
text/plain N)ZexecutegetattrZdisplay_pubZ
pub_socketsessionr   Zget_iopub_msgOUTPUT_TIMEOUTqueueZEmptyr   getsyswritesendprintjoinstderrstdout)ipkccellr   Z	in_kernelZsocketr    r   msgr   r   r    r/   9lib/python3.7/site-packages/distributed/_ipython_utils.pyrun_cell_remote!   s8    

r1   workerc                sl   t   t| }|d}tf | |j_  d fdd	}|_ j|d|d  j|d|d dS )	zRegister a %worker magic, given connection_info.

    Both a line and cell magic are registered,
    which run the given cell in a remote kernel.
    keyNc                s   |dkr| }t  | dS )z/Run the current cell on a remote IPython kernelN)r1   )liner-   )r+   r,   r/   r0   remoteX   s    z%register_worker_magic.<locals>.remoter4   )
magic_kind
magic_namer-   )N)	r	   dictpopr
   r    r3   start_channelsZclientregister_magic_function)connection_infor7   infor3   r5   r/   )r+   r,   r0   register_worker_magicK   s    

r>   c       	      C   s   t  }| dd}|d }||jkr,t|t|j| }|sZt|dkrRtd|d }dtt	t
| }|d}|tjkrtj| }n0tf |}||j_|  |jdd |tj|< t||| dS )	at  A magic for running code on a specified remote worker

    The connection_info dict of the worker will be looked up
    as the first positional arg to the magic.
    The rest of the line (or the entire cell for a %%cell magic)
    will be passed to the remote kernel.

    Usage:

        info = e.start_ipython(worker)[worker]
        %remote info print(worker.data)
    N   r   zI need some code to run!,r3   r   )r   )r	   splituser_ns	NameErrorr8   len
ValueErrorr(   mapstrsorteditemsr9   remote_magic_clientsr
   r    r3   r:   Zwait_for_readyr1   )	r4   r-   r+   Z
split_lineZ	info_namer<   r3   Zsession_keyr,   r/   r/   r0   rJ   d   s(    




rJ   r5   c             C   s6   t  }|dkrdS |jtd| d |jtd| d dS )zTDefine the parameterized %remote magic

    See remote_magic above for details.
    Nr4   )r6   r7   r-   )r	   r;   rJ   )r7   r+   r/   r/   r0   register_remote_magic   s
    rL   c                sl   t  }|dkrt j}tj||d  t f|  ddd g}|rN|| t| t	j
 fdd}dS )zOpen a QtConsole connected to a worker who has the given future

    - identify worker with who_has
    - start IPython kernel on the worker
    - start qtconsole connected to the kernel
    Nz.jsonZjupyterZ	qtconsolez
--existingc                  s(   yt   W n tk
r"   Y nX dS )z)Cleanup our connection file when we exit.N)osremoveOSErrorr/   )pathr/   r0   _cleanup_connection_file   s    z3connect_qtconsole.<locals>._cleanup_connection_file)r   r   hexrM   rP   r(   r   extendr   atexitregister)r<   r   Z
extra_argsZruntime_dircmdrQ   r/   )rP   r0   connect_qtconsole   s    
rW   c       	         s   ddl m} | dk	rtdddlm} ddlm} t }t	  | 
  |j|d d jj_| rt|  _d	d
  _ _t  fdd}t|d}d|_|  jddstdt	  |
   S )aU  Start an IPython kernel in a thread

    Parameters
    ----------

    ip: str
        The IP address to listen on (likely the parent object's ip).
    ns: dict
        Any names that should be injected into the IPython namespace.
    log: logger instance
        Hook up IPython's logging to an existing logger instead of the default.
    r   )r	   Nz+Cannot start IPython, it's already running.)	ZMQIOLoop)IPKernelApp)logz:memory:c               S   s   d S )Nr/   r/   r/   r/   r0   noop   s    zstart_ipython.<locals>.noopc                  sX     g   j_ j_ j  t  j_rD jjj	
     d S )N)Z
initializer   Zpre_handler_hookZpost_handler_hookstartr   instanceZloopshellrB   updatesetr/   )appevtr[   nszmq_loopr/   r0   _start   s    

zstart_ipython.<locals>._start)targetT   )r   z4IPython didn't start in a reasonable amount of time.)IPythonr	   RuntimeErrorZzmq.eventloop.iolooprX   Zipykernel.kernelapprY   r   r]   Zclear_instanceZinstallZconfigZHistoryManagerZ	hist_filer+   Zinit_signalZlog_connection_infor   r   Zdaemonr\   waitAssertionError)	r+   rc   rZ   r	   rX   rY   Z	save_instre   Zzmq_loop_threadr/   )ra   rb   r[   rc   rd   r0   start_ipython   s2    


rl   )r2   )N)r5   )NN)NNN)#__doc__Z
__future__r   rT   rM   r"   ImportErrorZQueue
subprocessr   r$   Z	threadingr   Zuuidr   Ztornado.genr   Ztornado.ioloopr   r   rh   r	   Zjupyter_clientr
   r   Zjupyter_core.pathsr   r!   r1   r>   rJ   rK   rL   rW   rl   r/   r/   r/   r0   <module>   s2   *

,

