o
    :a:*                  
   @   sL  d Z ddlmZ ddlZddlmZ ddlZddlZddlm	Z	 ddl
Z
ddlZddlZddlZddlZzddlZW n eyK Z zededZ[ww 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lmZm Z  G dd dej!Z"e" Z#G dd dej$Z%G dd dej&j'Z(dd Z)ej*G dd deZ+dS )z8
Displays Agg images in the browser, with interactivity
    )contextmanagerN)BytesIO)Pathz$The WebAgg backend requires Tornado.)_Backend)Gcf   )backend_webagg_core)TimerAsyncioTimerTornadoc                   @      e Zd Zdd ZdS )ServerThreadc                 C   s   t jj   d S N)tornadoioloopIOLoopinstancestartself r   D/usr/lib/python3/dist-packages/matplotlib/backends/backend_webagg.pyrun+      zServerThread.runN)__name__
__module____qualname__r   r   r   r   r   r   *       r   c                   @   s   e Zd ZdS )FigureCanvasWebAggN)r   r   r   r   r   r   r   r   2   s    r   c                       s   e Zd ZdZdZG dd dejjZG dd dejjZ	G dd dejjZ
G dd	 d	ejjZG d
d dejjZG dd dejjZd fdd	ZedddZedd Z  ZS )WebAggApplicationFc                   @   r   )zWebAggApplication.FavIconc                 C   s(   |  dd | tt d  d S )NContent-Typez	image/pngzimages/matplotlib.png)
set_headerwriter   mplget_data_pathZ
read_bytesr   r   r   r   get;   s   zWebAggApplication.FavIcon.getNr   r   r   r$   r   r   r   r   FavIcon:   r   r&   c                       *   e Zd Zdd fdd
Zdd Z  ZS )z"WebAggApplication.SingleFigurePage 
url_prefixc                       || _ t j||fi | d S r   r*   super__init__r   Zapplicationrequestr*   kwargs	__class__r   r   r.   A      z+WebAggApplication.SingleFigurePage.__init__c                 C   sF   t |}t|}dj| j| jd}| jd| j||tjj	|j
d d S )Nws://{req.host}{prefix}/Zreqprefixzsingle_figure.html)r7   ws_urifig_id	toolitemscanvas)intr   get_fig_managerformatr0   r*   rendercoreNavigationToolbar2WebAggr:   r;   )r   fignummanagerr8   r   r   r   r$   E   s   

z&WebAggApplication.SingleFigurePage.getr   r   r   r.   r$   __classcell__r   r   r2   r   SingleFigurePage@       rF   c                       r'   )z WebAggApplication.AllFiguresPager(   r)   c                   r+   r   r,   r/   r2   r   r   r.   T   r4   z)WebAggApplication.AllFiguresPage.__init__c                 C   s:   dj | j| jd}| jd| j|ttj tj	j
d d S )Nr5   r6   zall_figures.html)r7   r8   Zfiguresr:   )r>   r0   r*   r?   sortedr   Zfigsitemsr@   rA   r:   )r   r8   r   r   r   r$   X   s   
z$WebAggApplication.AllFiguresPage.getrD   r   r   r2   r   AllFiguresPageS   rG   rJ   c                   @   r   )zWebAggApplication.MplJsc                 C   s$   |  dd tj }| | d S )Nr   zapplication/javascript)r    r@   FigureManagerWebAggZget_javascriptr!   )r   Z
js_contentr   r   r   r$   c   s   
zWebAggApplication.MplJs.getNr%   r   r   r   r   MplJsb   r   rL   c                   @   r   )zWebAggApplication.Downloadc                 C   sR   t |}t|}| dtj|d t }|jj	j
||d | |  d S )Nr   binary)r>   )r<   r   r=   r    	mimetypesZ	types_mapr$   r   r;   figureZsavefigr!   getvalue)r   rB   ZfmtrC   Zbuffr   r   r   r$   k   s   
zWebAggApplication.Download.getNr%   r   r   r   r   Downloadj   r   rQ   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )zWebAggApplication.WebSocketTc                 C   s@   t || _t| j| _| j|  t| dr| d d S d S )Nset_nodelayT)r<   rB   r   r=   rC   Zadd_web_sockethasattrrR   )r   rB   r   r   r   openw   s   

z WebAggApplication.WebSocket.openc                 C   s   | j |  d S r   )rC   Zremove_web_socketr   r   r   r   on_close~   s   z$WebAggApplication.WebSocket.on_closec                 C   sJ   t |}|d dkr|d | _d S t| j}|d ur#|| d S d S )Ntypesupports_binaryvalue)jsonloadsrW   r   r=   rB   Zhandle_json)r   messagerC   r   r   r   
on_message   s   
z&WebAggApplication.WebSocket.on_messagec                 C   s   |  t| d S r   )write_messagerY   dumps)r   Zcontentr   r   r   	send_json   r   z%WebAggApplication.WebSocket.send_jsonc                 C   s>   | j r| j|dd d S d|ddd}| | d S )NT)rM   zdata:image/png;base64,{0}base64
r(   )rW   r]   r>   encodereplace)r   ZblobZdata_urir   r   r   send_binary   s   z'WebAggApplication.WebSocket.send_binaryN)	r   r   r   rW   rT   rU   r\   r_   rd   r   r   r   r   	WebSockett   s    re   r(   c              
      s   |r|d dkr|d dksJ dt  j|d tjjdtj if|d tjjdtt	
 dif|d	 | jf|d
 | jd|if|d | jd|if|d | jf|d | jf|d | jfgtj d d S )Nr   /z6url_prefix must start with a "/" and not end with one.z/_static/(.*)pathz/_images/(.*)Zimagesz/favicon.icoz	/([0-9]+)r*   z/?z
/js/mpl.jsz/([0-9]+)/wsz/([0-9]+)/download.([a-z0-9.]+))Ztemplate_path)r-   r.   r   webZStaticFileHandlerr@   rK   get_static_file_pathr   r"   r#   r&   rF   rJ   rL   re   rQ   )r   r*   r2   r   r   r.      s8   

 
zWebAggApplication.__init__Nc                 C   s   | j rd S | |d}|| _dd }|d u rtjd | _n|| _tjd | _|| jtjd D ]*}z	||| j W n tjyS } z|j	t	j
krI W Y d }~q.d }~ww || _ ntdd| _ d S )	Nr)   c                 s   sP    t td|D ]}| | V  qt |d D ]}| td| d|  V  qdS )z
            Generate a list of n random ports near the given port.

            The first 5 ports will be sequential, and the remaining n-5 will be
            randomly selected in the range [port-2*n, port+2*n].
                  N)rangeminrandomZrandint)portnir   r   r   random_ports   s   z2WebAggApplication.initialize.<locals>.random_portszwebagg.addresszwebagg.portzwebagg.port_retrieszSThe webagg server could not be started because an available port could not be foundT)initializedr*   r"   rcParamsaddressrq   ZlistensocketerrorerrnoZ
EADDRINUSE
SystemExit)clsr*   rq   rw   Zapprt   er   r   r   
initialize   s4   

zWebAggApplication.initializec                    s    j rd S 	 tjj  fddtfdd}d _ td tj	  |  
  W d    d S 1 s;w   Y  d S )Nc                      s$      td tj  d _d S )NzServer is stoppedF)stopprintsysstdoutflushstartedr   )r|   r   r   r   shutdown   s   

z)WebAggApplication.start.<locals>.shutdownc               
   3   sF    t  t j fdd} zd V  W t  t j|  d S t  t j|  w )Nc                    s
     S r   )Zadd_callback_from_signal)Zsigframer   r   r   r   <lambda>	  s   
 z?WebAggApplication.start.<locals>.catch_sigint.<locals>.<lambda>)signalSIGINT)Zold_handlerr   r   r   catch_sigint  s   "z-WebAggApplication.start.<locals>.catch_sigintTz"Press Ctrl+C to stop WebAgg server)r   r   r   r   r   r   r   r   r   r   r   )r|   r   r   )r|   r   r   r   r      s   


"zWebAggApplication.start)r(   )r(   NN)r   r   r   ru   r   r   ri   ZRequestHandlerr&   rF   rJ   rL   rQ   Z	websocketZWebSocketHandlerre   r.   classmethodr~   r   rE   r   r   r2   r   r   6   s    
'(-r   c                 C   sj   dd l }t  t st  | j}ttj	
 d }|j|}|jtj|tjj| jtjddS )Nr   zipython_inline_figure.html)r7   r9   r:   r;   rq   zutf-8)Ztornado.templater   r~   webagg_server_threadZis_aliver   Znumberr   r@   rK   rj   Z	read_texttemplateZTemplateZgenerater*   rA   r:   r;   rq   decode)rO   r   rB   Ztpltr   r   r   ipython_inline_display  s(   
r   c                   @   s"   e Zd ZeZejZedd Z	dS )_BackendWebAggc                  C   sd   t   djt jt jt jd} tjd r%dd l}|	| s$t
d|  nt
d|  t   d S )Nzhttp://{address}:{port}{prefix})rw   rq   r7   zwebagg.open_in_browserr   zTo view figure, visit {0})r   r~   r>   rw   rq   r*   r"   rv   
webbrowserrT   r   r   )Zurlr   r   r   r   show0  s   

z_BackendWebAgg.showN)
r   r   r   r   ZFigureCanvasr@   rK   ZFigureManagerstaticmethodr   r   r   r   r   r   +  s
    r   ),__doc__
contextlibr   rz   ior   rY   rN   Zpathlibr   rp   r   r   rx   Z	threadingr   ImportErrorerrRuntimeErrorZtornado.webZtornado.ioloopZtornado.websocketZ
matplotlibr"   Zmatplotlib.backend_basesr   Zmatplotlib._pylab_helpersr   r(   r   r@   r	   r
   ZThreadr   r   ZFigureCanvasWebAggCorer   ri   ZApplicationr   r   Zexportr   r   r   r   r   <module>   sD    
 c