B
    a#                 @   s   d Z ddlZddlZddlZddlZddlmZ ddlm	Z	 ddl
mZ dd Zdd	 Zdddddd
Zdd Zedddd Zeddd Zeddd Zeddd Zeddd Zeddd Zed d!d" Zd%d#d$ZdS )&z4Event loop integration for the ZeroMQ-based kernels.    N)LooseVersion)Application)ioc               C   s"   t jdko tt d tdkS )zhShould we use appnope for dealing with OS X app nap?

    Checks if we are on OS X 10.9 or greater.
    darwinr   z10.9)sysplatformVmac_ver r
   r
   8/tmp/pip-unpacked-wheel-4kvctoso/ipykernel/eventloops.py_use_appnope   s    r   c                s~   ddl m} t r&jr&ddlm  nddlm} |dd   fdd}t	j
}|||jjj}|j| d S )	Nr   )QtCore)
nope_scope)contextmanagerc               s   s
   d V  d S )Nr
   r
   r
   r
   r   context    s    z"_notify_stream_qt.<locals>.contextc            	      s6   x0 tjtj@ r0     W d Q R X qW d S )N)
getsockoptzmqZEVENTSPOLLINdo_one_iterationr
   )r   kernelstreamr
   r   process_stream_events$   s    z0_notify_stream_qt.<locals>.process_stream_events)ZIPython.external.qt_for_kernelr   r   _darwin_app_napappnoper   
contextlibr   r   r   ZFDZQSocketNotifierZReadappZ	activatedconnect)r   r   r   r   r   fdZnotifierr
   )r   r   r   r   _notify_stream_qt   s    r   )inlineZnbaggZnotebookZipymplNc                 s    fdd}|S )a0  Decorator to register an event loop to integrate with the IPython kernel

    The decorator takes names to register the event loop as for the %gui magic.
    You can provide alternative names for the same toolkit.

    The decorated function should take a single argument, the IPython kernel
    instance, arrange for the event loop to call ``kernel.do_one_iteration()``
    at least every ``kernel._poll_interval`` seconds, and start the event loop.

    :mod:`ipykernel.eventloops` provides and registers such functions
    for a few common event loops.
    c                s   x D ]}| t |< qW | S )N)loop_map)funcname)toolkitnamesr
   r   	decoratorC   s    
z'register_integration.<locals>.decoratorr
   )r#   r$   r
   )r#   r   register_integration6   s    r%   ZqtZqt4c             C   sP   ddl m}m} |dg| _| jd x| jD ]}t| | q0W || j dS )z1Start a kernel with PyQt4 event loop integration.r   )get_app_qt4start_event_loop_qt4 FN)IPython.lib.guisupportr&   r'   r   ZsetQuitOnLastWindowClosedshell_streamsr   )r   r&   r'   sr
   r
   r   loop_qt4K   s    r,   Zqt5c             C   s   dt jd< t| S )z1Start a kernel with PyQt5 event loop integration.Zpyqt5ZQT_API)osenvironr,   )r   r
   r
   r   loop_qt5Y   s    
r/   wxc                s   ddl ddlm} t r2| jr2ddlm} |  | jtd| j	 G fdddj
 G  fdd	d	j}|d
d| _ddl}t||js||j|j || j dS )z*Start a kernel with wx event loop support.r   N)start_event_loop_wx)nopei  c                   s"   e Zd Z fddZdd ZdS )zloop_wx.<locals>.TimerFramec                sB   j | d d | | _| j  | j| j || _d S )N)	Frame__init__TimertimerZStartZBindZ	EVT_TIMERon_timerr!   )selfr!   )poll_intervalr0   r
   r   r5   t   s
    z$loop_wx.<locals>.TimerFrame.__init__c             S   s   |    d S )N)r!   )r9   eventr
   r
   r   r8   |   s    z$loop_wx.<locals>.TimerFrame.on_timerN)__name__
__module____qualname__r5   r8   r
   )r:   r0   r
   r   
TimerFrames   s   r?   c                   s   e Zd Z fddZdS )zloop_wx.<locals>.IPWxAppc                s    | _ | j d dS )NFT)frameZShow)r9   )r?   doir
   r   OnInit   s    
zloop_wx.<locals>.IPWxApp.OnInitN)r<   r=   r>   rB   r
   )r?   rA   r
   r   IPWxApp   s   rC   F)redirect)r0   r)   r1   r   r   r   r2   r   int_poll_intervalr4   ZAppr   signalcallable	getsignalSIGINTdefault_int_handler)r   r1   r2   rC   rG   r
   )r?   rA   r:   r0   r   loop_wx`   s    rL   tkc                st   yddl m  W n  tk
r0   ddlm  Y nX | j}td| j G  fdddt}||| _| j	  dS )z&Start a kernel with the Tk event loop.r   )Tki  c                   s,   e Zd Z fddZfddZdd ZdS )zloop_tk.<locals>.Timerc                s     | _ | j   || _d S )N)r   Zwithdrawr!   )r9   r!   )rN   r
   r   r5      s    
zloop_tk.<locals>.Timer.__init__c                s   |    | j | j d S )N)r!   r   afterr8   )r9   )r:   r
   r   r8      s    zloop_tk.<locals>.Timer.on_timerc             S   s   |    | j  d S )N)r8   r   mainloop)r9   r
   r
   r   start   s    zloop_tk.<locals>.Timer.startN)r<   r=   r>   r5   r8   rQ   r
   )rN   r:   r
   r   r6      s   r6   N)
tkinterrN   ImportErrorTkinterr   rE   rF   objectr7   rQ   )r   rA   r6   r
   )rN   r:   r   loop_tk   s    
rV   Zgtkc             C   s    ddl m} || }|  dS )z6Start the kernel, coordinating with the GTK event loop   )GTKEmbedN)Zgui.gtkembedrX   rQ   )r   rX   
gtk_kernelr
   r
   r   loop_gtk   s    rZ   Zgtk3c             C   s    ddl m} || }|  dS )z6Start the kernel, coordinating with the GTK event looprW   )rX   N)Zgui.gtk3embedrX   rQ   )r   rX   rY   r
   r
   r   	loop_gtk3   s    r[   Zosxc       	         s<  ddl }|jdk r&jd tS ddlm}m} tdj	 }t
jfdd  fd	d
}||}|| |  t }jr|jjtj xjD ]}||jtj qW xvzhyBy. t
_|  t
_|d|    W n    Y nX W n  tk
r&   td Y nX W dt
_X qW dS )znStart the kernel, coordinating with the Cocoa CFRunLoop event loop
    via the matplotlib MacOSX backend.
    r   Nz1.1.0a  MacOSX backend in matplotlib %s doesn't have a Timer, falling back on Tk for CFRunLoop integration.  Note that even this won't work if Tk is linked against X11 instead of Cocoa (e.g. EPD).  To use the MacOSX backend in the kernel, you must use matplotlib >= 1.1.0, or a native libtk.)TimerMacshowi  c                s$   | t krtd n | || dS )z.don't let KeyboardInterrupts look like crashesz%KeyboardInterrupt caught in CFRunLoopN)KeyboardInterruptr   	raw_print)etypevaluetb)real_excepthookr
   r   
handle_int   s    zloop_cocoa.<locals>.handle_intc                  s   t _   t _d S )N)r   
excepthookr   r
   )rd   r   rc   r
   r   rA      s    zloop_cocoa.<locals>.doi
   z"KeyboardInterrupt caught in kernel)
matplotlib__version__logwarnrV   Z"matplotlib.backends.backend_macosxr\   r]   rE   rF   r   re   Zadd_callbackrQ   r   ZPollerZcontrol_streamregistersocketr   r*   rP   pollr   r^   r   r_   )	r   rg   r\   r]   r:   rA   tZpollerr   r
   )rd   r   rc   r   
loop_cocoa   s>    

ro   c             C   s   | t kr d| t  f }t||dkrPt r@tt dd}|dkrPtdt |  }|rx|jdk	rx|j|k	rxtd||_dS )z#Enable integration with a given GUIz)Invalid GUI request %r, valid ones are:%sNr   z\You didn't specify a kernel, and no IPython Application with a kernel appears to be running.z'Cannot activate multiple GUI eventloops)	r    keys
ValueErrorr   ZinitializedgetattrinstanceRuntimeErrorZ	eventloop)guir   eZloopr
   r
   r   
enable_gui  s    rw   )N)__doc__r-   r   r   r   Zdistutils.versionr   r   Ztraitlets.config.applicationr   ZIPython.utilsr   r   r   r    r%   r,   r/   rL   rV   rZ   r[   ro   rw   r
   r
   r
   r   <module>   s.   5		I