a
    bbE                     @   sF  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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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%m&Z&m'Z' ddl(m)Z) e*e+Z,dd Z-dd Z.dd Z/G dd deZ0G dd de
Z	dS )zN
Subclasses the bokeh serve commandline handler to extend it in various
ways.
    N)glob)
ModuleType)Serve)!build_single_handler_applications)Application)DocumentLifecycleHandler)FunctionHandler)ApplicationContext)PeriodicCallbackIOLoop)StaticFileHandler   )OAuthProvider)config)fullpath)REST_PROVIDERS)record_moduleswatch)
INDEX_HTMLget_static_routes
set_curdoc)statec              	   C   sF   | j D ]$}z|d  W q ty(   Y q0 qi | jjd < | d  d S N)Zsession_destroyed_callbacks	ExceptionZ	callbacksZ_change_callbacksZdestroy)doccallback r   2lib/python3.9/site-packages/panel/command/serve.py_cleanup_doc#   s    
r   c                 C   s<   |  d}|d  }t|dkr4d|dd }||fS )z
    Parse a key, value pair, separated by '='
    That's the reverse of ShellArgs.

    On the command line (argparse) a declaration will typically look like:
        foo=hello
    or
        foo="hello world"
    =r      N)splitstriplenjoin)sitemskeyvaluer   r   r   	parse_var-   s
    

r)   c                 C   s   t dd | D S )zC
    Parse a series of key-value pairs and return a dictionary
    c                 s   s   | ]}t |V  qd S r   )r)   ).0itemr   r   r   	<genexpr>C       zparse_vars.<locals>.<genexpr>)dict)r&   r   r   r   
parse_vars?   s    r/   c                       s>   e Zd Zd
 fdd	Zdd Z fddZ fdd	Z  ZS )AdminApplicationContext:  c                    s:   t  j|fdt i| || _d | _| j| j d S )NZio_loop)	super__init__r   Zcurrent_unused_timeout_cleanup_cbZ_loopZadd_callbackrun_load_hook)selfZapplicationunused_timeoutkwargs	__class__r   r   r3   H   s    z AdminApplicationContext.__init__c                    s   |  | jI d H  d S r   )Z_cleanup_sessionsr4   r7   r   r   r   cleanup_sessionsN   s    z(AdminApplicationContext.cleanup_sessionsc                    s(   t | j| j| _| j  t   d S r   )r
   r=   r4   r5   startr2   r6   r<   r:   r   r   r6   Q   s    
z%AdminApplicationContext.run_load_hookc                    s   | j r| j   t   d S r   )r5   stopr2   run_unload_hookr<   r:   r   r   r@   V   s    
z'AdminApplicationContext.run_unload_hook)r1   )__name__
__module____qualname__r3   r=   r6   r@   __classcell__r   r   r:   r   r0   F   s   r0   c                       sv  e Zd Zejdeddddfdededd	fd
ededd	fdededd	fdededd	fdededd	fdededd	fdededd	fdededd	fdededddfdededd	fdededddfd ed!d"d#fd$eded%d&dfd'ed!d(d#fd)ed!d*d#fd+eded,d	fd-ed!d.d#fd/eded0d1dfd2eded3d1dff Zd4gZ	 fd5d6Z
d7d8 Z  ZS )9r   z--static-dirsz	KEY=VALUE+ziStatic directories to serve specified as key=value pairs mapping from URL route to static file directory.)metavarnargshelpz--oauth-providerZstorezThe OAuth2 provider to use.)actiontyperH   z--oauth-keyzThe OAuth2 key to usez--oauth-secretzThe OAuth2 secret to usez--oauth-redirect-urizThe OAuth2 redirect URIz--oauth-extra-paramszAdditional parameters to use.z--oauth-jwt-userz1The key in the ID JWT token to consider the user.z--oauth-encryption-keyz4A random string used to encode the user information.z--oauth-error-templatez--oauth-expiry-daysz.Expiry off the OAuth cookie in number of days.r    )rI   rJ   rH   defaultz--rest-providerz&The interface to use to serve REST APIz--rest-endpointzEndpoint to store REST API on.restz--rest-session-info
store_truez-Whether to serve session info on the REST API)rI   rH   z--session-historyz,The length of the session history to record.r   z--warmz<Whether to execute scripts on startup to warm up the server.z--adminzWhether to add an admin panel.z
--profilerz>The profiler to use by default, e.g. pyinstrument or snakeviz.z--autoreloadz1Whether to autoreload source when script changes.z--num-threadsz>Whether to start a thread pool which events are dispatched to.Nz--setupz3Path to a setup script to run before server starts.z.pyc                    s|   |j rn|j dsn|j tjjd }| jD ] }||r,|d t|  }q,d| |v rn|d|  |d< t 	||S )N.html/)
indexendswithr!   ospathsep_extensionsr#   r2   customize_applications)r7   argsapplicationsrQ   extr:   r   r   rW      s    

zServe.customize_applicationsc           %   
      s  t |}d|vrt|d< |dg  |d< } jr<t jni }|t|7 }g } jD ]$} jrp|t| qV|	| qV j
r j
dsd}| jD ]>}	 j
|	r j
n j
 |	 tfdd|D rd}q|stdd	 jtv rt j | j}
||
 n jd
ur0td j  jt_tjrT|D ]}t| qD jr j}t|}| }W d
   n1 s0    Y  t|t|}t||ddd}d}t|}t||jd< t ||j |t!_" j#s jr fdd|D }t$||} jrt% d |& D ]J}|' }t(| t!)d
 W d
   n1 s\0    Y  t*| q&W d
   n1 s0    Y  nT|& D ]J}|' }t(| t!)d
 W d
   n1 s0    Y  t*| q j+}|d
u rd}|,d}|rd| } j-t_- j.rrddl/m0} ddl1m2} dt_3t4t5|} j6pXd}t7||dd}t8dd |j9D r|:t;  g }|D ]6}d|d  }d|i}|| }|	||d |f qd
}|D ]}|d dr|d }q|s t<d|D ]}||d d < qz:dd
l=} tj>?tj>@| jAd!}!|	d"tBt |!d#f W n tCyf   Y n0 ||  jDt_D jErtd$ |d%}
||
 t!Fd&t!d&g  jGd
urtjHd
urtd' jGt_H jIr҈ jIt_I jJt_KtjLr jLrtd(n" jLr jLt_LntjLs&td)tjMr@ jMr@td*n" jMrR jMt_MntjMsbtd+ jNrxtO jNt_NtjPr jPrtd,nf jPr jPQd-}"ztRS|"}#W n tCy   td.Y n0 tT|#d/krtd0|"t_PntUd1 tjPr:zdd2lVmW}$ W n tXy,   tXd3Y n0 |$tjPt!_Y jZrTtjZrTtd4n jZrf jZt_Zntd5t[ j\d6|d7<  j]rtj]rtd8n j]r j]t_] j^rtj^rtd9n j^r҈ j^t_^tjZrtjZ|d:< |S );zAllows subclasses to customize ``server_kwargs``.

        Should modify and return a copy of the ``server_kwargs`` dictionary.
        rQ   Zextra_patternsrN   Fc                 3   s   | ]}|  V  qd S r   )rR   r*   f)rQ   r   r   r,      r-   z)Serve.customize_kwargs.<locals>.<genexpr>TzThe --index argument must either specify a jinja2 template with a .html file extension or select one of the applications being served as the default. The specified application z could not be found.Nz rest-provider %r not recognized.exec)filenamemodedont_inheritZpanel_setup_module__file__c                    s   i | ]}| j qS r   rX   r[   rb   r   r   
<dictcomp>  r-   z*Serve.customize_kwargs.<locals>.<dictcomp> rP   r   )admin_panel)per_app_patternsr1   z/admin)r8   Zurlc                 s   s   | ]}t |t V  qd S r   )
isinstancer   )r*   Zhandlerr   r   r   r,   2  r-   r   Zapplication_contextr    z/wszCouldn't find websocket pathZbokeh_websocket_pathZstaticz/snakeviz/static/(.*))rT   ZparamrL   Zsession_infozpSupply num_threads either using the environment variable PANEL_NUM_THREADS or as an explicit argument, not both.zVSupply OAuth key either using environment variable or via explicit argument, not both.zWhen enabling an OAuth provider you must supply a valid oauth_key either using the --oauth-key CLI argument or PANEL_OAUTH_KEY environment variable.zYSupply OAuth secret either using environment variable or via explicit argument, not both.zWhen enabling an OAuth provider you must supply a valid OAuth secret either using the --oauth-secret CLI argument or PANEL_OAUTH_SECRET environment variable.zaSupply OAuth encryption key either using environment variable or via explicit argument, not both.asciizOAuth encryption key was not a valid base64 string. Generate an encryption key with `panel oauth-secret` and ensure you did not truncate the returned string.    z>OAuth encryption key must be 32 url-safe base64-encoded bytes.as  WARNING: OAuth has not been configured with an encryption key and will potentially leak credentials in cookies and a JWT token embedded in the served website. Use at your own risk or generate a key with the `panel oauth-key` CLI command and then provide it to `panel serve` using the PANEL_OAUTH_ENCRYPTION environment variable or the --oauth-encryption-key CLI argument.)FernetzUsing OAuth2 provider with Panel requires the cryptography library. Install it with `pip install cryptography` or `conda install cryptography`.zZSupply cookie secret either using environment variable or via explicit argument, not both.zWhen enabling an OAuth provider you must supply a valid cookie_secret either using the --cookie-secret CLI argument or the PANEL_COOKIE_SECRET environment variable.)Zerror_templateZauth_providerz_Supply OAuth redirect URI either using environment variable or via explicit argument, not both.z[Supply OAuth JWT user either using environment variable or via explicit argument, not both.cookie_secret)_r.   r   getstatic_dirsr/   r   filesr   extendappendrQ   rR   rV   any
ValueErrorZrest_providerr   Zrest_endpointZ
autoreloadr   r   ZsetupopenreadastparserS   fspathcompiler   r   __dict__r]   r   Z_setup_moduleZwarmr   r   valuesZcreate_documentr   Z_on_loadr   prefixr"   ZprofilerZadminZio.adminre   	io.serverrf   Z_adminr   r   Zcheck_unused_sessionsr0   allZ	_handlersaddr   RuntimeErrorsnakevizrT   r$   dirnamera   r   r   Zsession_historyZrest_session_infoZpublishZnum_threadsZnthreadsZoauth_providerZoauth_expiry_daysZoauth_expiryZ	oauth_keyZoauth_secretZoauth_extra_paramsZliteral_evalZoauth_encryption_keyencodebase64Zurlsafe_b64decoder#   printZcryptography.fernetrj   ImportErrorZ
encryptionrk   r   Zoauth_error_templateZoauth_redirect_uriZoauth_jwt_user)%r7   rX   Zserver_kwargsr9   patternsrm   rn   r\   foundrZ   patternZ
setup_pathZsetup_sourceZnodescodeZmodule_namemoduleZargvsrY   Zappr   r{   re   rf   r8   Zapp_ctxZapp_patternspZroutecontextZwebsocket_pathrr   ZSNAKEVIZ_PATHZencryption_keyr'   rj   r   )rX   rQ   r   customize_kwargs   sl   

 	
(

*.
*









zServe.customize_kwargs)rA   rB   rC   _BkServerX   r.   strfloatintrV   rW   r   rD   r   r   r:   r   r   \   s   j
r   )1__doc__ru   r   ZloggingrS   r   typesr   Zbokeh.command.subcommands.server   r   Zbokeh.command.utilr   Zbokeh.applicationr   Z-bokeh.application.handlers.document_lifecycler   Z#bokeh.application.handlers.functionr   Zbokeh.server.contextsr	   Ztornado.ioloopr
   r   Ztornado.webr   Zauthr   r   utilr   Zio.restr   Z	io.reloadr   r   r|   r   r   r   Zio.stater   Z	getLoggerrA   logr   r)   r/   r0   r   r   r   r   <module>   s6   

