3
¥Yði~6  ã               @   s  U d dl Z d dlZd dl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 ejejejejhZeedƒrˆejejƒ eeƒZ[eje dœdd	„Zeje eje dd
œdd„Zeje eje eje dœdd„Zeje eje eje dœdd„Zeje eje dœdd„Zej e dœdd„Z!G dd„ dƒZ"G dd„ de"ƒZ#G dd„ de"ƒZ$e#e$dœZ%ej&eej'e" f %ye(dƒ W n" e)k
�r¶   e%d e%d < Y nX e%d! e%d < ddœd"d#„Z*d'ej+g df ej,eje  ej,eje  ej-e.e/f edd$œd%d&„Z0dS )(é    N)Úchain)ÚPurePathé   )Ú_logÚreal_prefix)Úreturnc              c   sd   x^t tjjƒ ƒD ]L} t| ddƒ}|dkr*qx0tjj|ƒsT|}tjj|ƒ}||kr,P q,W |V  qW dS )z;Find the filesystem paths associated with imported modules.Ú__file__N)	ÚlistÚsysÚmodulesÚvaluesÚgetattrÚosÚpathÚisfileÚdirname)ÚmoduleÚnameÚold© r   ú6/tmp/pip-build-8om4l6ph/Werkzeug/werkzeug/_reloader.pyÚ_iter_module_paths   s    r   )ÚpathsÚexclude_patternsr   c             C   s$   x|D ]}| j tj| |ƒƒ qW d S )N)Údifference_updateÚfnmatchÚfilter)r   r   Úpatternr   r   r   Ú_remove_by_pattern.   s    
r   )Úextra_filesr   r   c             C   sÆ   t ƒ }x¤tttjƒ| ƒD ]�}tjj|ƒ}tjj|ƒr>|j|ƒ xhtj	|ƒD ]Z\}}}|j
tƒsntjj|ƒdkrx|jƒ  qJx*|D ]"}|jdƒr~|jtjj||ƒƒ q~W qJW qW |jtƒ ƒ t||ƒ |S )ax  Find paths for the stat reloader to watch. Returns imported
    module files, Python files under non-system paths. Extra files and
    Python files under extra directories can also be scanned.

    System paths have to be excluded for efficiency. Non-system paths,
    such as a project root or ``sys.path.insert``, should be the paths
    of interest to the user anyway.
    Ú__pycache__ú.gitú.hgú.pyú.pyc>   r!   r    r"   )r#   r$   )Úsetr   r	   r
   r   r   Úabspathr   ÚaddÚwalkÚ
startswithÚ_ignore_prefixesÚbasenameÚclearÚendswithÚjoinÚupdater   r   )r   r   r   r   ÚrootÚdirsÚfilesr   r   r   r   Ú_find_stat_paths3   s$    
  

 
r3   c             C   s‚   t ƒ }xFtttjƒ| ƒD ]2}tjj|ƒ}tjj|ƒr@tjj|ƒ}|j	|ƒ qW x t
ƒ D ]}|j	tjj|ƒƒ qVW t||ƒ t|ƒS )z­Find paths for the stat reloader to watch. Looks at the same
    sources as the stat reloader, but watches everything under
    directories instead of individual files.
    )r%   r   r	   r
   r   r   r&   r   r   r'   r   r   Ú_find_common_roots)r   r   r1   r   r   r   r   Ú_find_watchdog_paths]   s    
r5   )r   r   c                sŒ   i }xFt dd„ | D ƒtdd�D ]*}|}x|D ]}|j|i ƒ}q,W |jƒ  qW tƒ ‰tjttf tj	tdf d dœ‡ ‡fdd„‰ ˆ |f ƒ ˆS )	Nc             s   s   | ]}t |ƒjV  qd S )N)r   Úparts)Ú.0Úxr   r   r   ú	<genexpr>x   s    z%_find_common_roots.<locals>.<genexpr>T)ÚkeyÚreverse.)Únoder   r   c                s@   x$| j ƒ D ]\}}ˆ |||f ƒ q
W | s<ˆjtjj|Ž ƒ d S )N)Úitemsr'   r   r   r.   )r<   r   ÚprefixÚchild)Ú_walkÚrvr   r   r@   ‚   s    z!_find_common_roots.<locals>._walk)
ÚsortedÚlenÚ
setdefaultr,   r%   ÚtÚMappingÚstrÚdictÚTuple)r   r0   Úchunksr<   Úchunkr   )r@   rA   r   r4   u   s    
,
r4   c              C   sx  t jg} t jd }t jdd… }t jd }t|ddƒdksntjdkrì|jdkrìtjj	|ƒ rìtjj	|› d�ƒrìtjj
|ƒ}tjdkràtjj	|ƒ r¬tjj	|› d�ƒr¬|d7 }tjjt jƒd dkràtjj|ƒd dkrà| jdƒ | j|ƒ n~t jd d	k�rt j}nftjj|ƒ�rRtjt|jƒ}tjjtjj|ƒƒd }|dk�rV|d
|› �7 }n|}| jd	|jd
ƒfƒ | j|ƒ | S )zpDetermine how the script was executed, and return the args needed
    to execute it again in a new process.
    r   r   NÚ__main__Ú__package__ÚntÚ z.exez-mÚ.)r
   Ú
executableÚargvr   r   r   r   rM   r   Úexistsr&   ÚsplitextÚpopÚappendr   rE   ÚcastrG   r+   ÚextendÚlstrip)rA   Z	py_scriptÚargsrL   Z	py_moduler   r   r   r   Ú_get_args_for_reloading�   s8    




 


r[   c               @   s¨   e Zd ZdZdejeje  ejeje  eje	e
f ddœdd„Zd dœdd	„Zd
d„ Zddœdd„Zddœdd„Ze	dœdd„Zeddœdd„Zeddœdd„ZdS )ÚReloaderLooprO   Nr   )r   r   Úintervalr   c             C   s,   dd„ |pf D ƒ| _ t|pf ƒ| _|| _d S )Nc             S   s   h | ]}t jj|ƒ’qS r   )r   r   r&   )r7   r8   r   r   r   ú	<setcomp>Ò   s    z(ReloaderLoop.__init__.<locals>.<setcomp>)r   r%   r   r]   )Úselfr   r   r]   r   r   r   Ú__init__Ì   s    zReloaderLoop.__init__)r   c             C   s   | j ƒ  | S )zgDo any setup, then run one step of the watch to populate the
        initial filesystem state.
        )Úrun_step)r_   r   r   r   Ú	__enter__Ö   s    zReloaderLoop.__enter__c             C   s   dS )z4Clean up any resources associated with the reloader.Nr   )r_   Úexc_typeÚexc_valÚexc_tbr   r   r   Ú__exit__Ý   s    zReloaderLoop.__exit__c             C   s   x| j ƒ  tj| jƒ qW dS )zfContinually run the watch step, sleeping for the configured
        interval after each step.
        N)ra   ÚtimeÚsleepr]   )r_   r   r   r   Úruná   s    zReloaderLoop.runc             C   s   dS )z}Run one step for watching the filesystem. Called once to set
        up initial state, then repeatedly to update it.
        Nr   )r_   r   r   r   ra   é   s    zReloaderLoop.run_stepc             C   sP   xJt dd| j› �ƒ tƒ }tjjƒ }d|d< tj||dd�}|dkr|S qW dS )	z|Spawn a new Python interpreter with the same arguments as the
        current one, but running the reloader thread.
        Úinfoz * Restarting with ÚtrueÚWERKZEUG_RUN_MAINF)ÚenvÚ	close_fdsé   N)r   r   r[   r   ÚenvironÚcopyÚ
subprocessÚcall)r_   rZ   Znew_environZ	exit_coder   r   r   Úrestart_with_reloaderï   s    
z"ReloaderLoop.restart_with_reloader)Úfilenamer   c             C   s   | j |ƒ tjdƒ d S )Nro   )Ú
log_reloadr
   Úexit)r_   ru   r   r   r   Útrigger_reloadý   s    
zReloaderLoop.trigger_reloadc             C   s"   t jj|ƒ}tdd|›d�ƒ d S )Nrj   z * Detected change in z, reloading)r   r   r&   r   )r_   ru   r   r   r   rv     s    zReloaderLoop.log_reload)NNr   )Ú__name__Ú
__module__Ú__qualname__r   rE   ÚOptionalÚIterablerG   ÚUnionÚintÚfloatr`   rb   rf   ri   ra   rt   rx   rv   r   r   r   r   r\   É   s     *r\   c                   s4   e Zd ZdZedœ‡ fdd„Zddœdd„Z‡  ZS )ÚStatReloaderLoopÚstat)r   c                s   i | _ tƒ jƒ S )N)ÚmtimesÚsuperrb   )r_   )Ú	__class__r   r   rb   	  s    zStatReloaderLoop.__enter__Nc             C   sz   xtt t| j| jƒƒD ]^}ytj|ƒj}W n tk
r>   wY nX | jj	|ƒ}|d kr`|| j|< q||kr| j
|ƒ qW d S )N)r   r3   r   r   r   r‚   Úst_mtimeÚOSErrorrƒ   Úgetrx   )r_   r   ÚmtimeZold_timer   r   r   ra     s    
zStatReloaderLoop.run_step)ry   rz   r{   r   r\   rb   ra   Ú__classcell__r   r   )r…   r   r�     s   r�   c                   sp   e Zd Zejejddœ‡ fdd„Zeddœdd„Zedœ‡ fd	d
„Z	dd„ Z
ddœdd„Zddœdd„Z‡  ZS )ÚWatchdogReloaderLoopN)rZ   Úkwargsr   c                s¨   ddl m} ddlm} tƒ j||Ž | j‰ G ‡ fdd„d|ƒ}|jjƒ }|j	dƒr`|d d… }d|› d	�| _
|ƒ | _d
d„ | jD ƒ}|d|•d| j•d�| _d| _d S )Nr   )ÚObserver)ÚPatternMatchingEventHandlerc                   s   e Zd Z‡ fdd„ZdS )z3WatchdogReloaderLoop.__init__.<locals>.EventHandlerc                s   ˆ |j ƒ d S )N)Zsrc_path)r_   Úevent)rx   r   r   Úon_any_event'  s    z@WatchdogReloaderLoop.__init__.<locals>.EventHandler.on_any_eventN)ry   rz   r{   r�   r   )rx   r   r   ÚEventHandler&  s   r‘   Úobserveré   z
watchdog (ú)c             S   s   g | ]}t jj|ƒs|‘qS r   )r   r   Úisdir)r7   Úpr   r   r   ú
<listcomp>6  s    z1WatchdogReloaderLoop.__init__.<locals>.<listcomp>ú*.pyú*.pycú*.zipú*/__pycache__/*ú*/.git/*ú*/.hg/*)ÚpatternsÚignore_patternsFiøÿÿÿ)r˜   r™   rš   )r›   rœ   r�   )Zwatchdog.observersr�   Zwatchdog.eventsrŽ   r„   r`   rx   ry   Úlowerr-   r   r’   r   r   Úevent_handlerÚshould_reload)r_   rZ   rŒ   r�   rŽ   r‘   Zreloader_nameZextra_patterns)r…   )rx   r   r`     s$    

  zWatchdogReloaderLoop.__init__)ru   r   c             C   s   d| _ | j|ƒ d S )NT)r¢   rv   )r_   ru   r   r   r   rx   B  s    z#WatchdogReloaderLoop.trigger_reload)r   c                s   i | _ | jjƒ  tƒ jƒ S )N)Úwatchesr’   Ústartr„   rb   )r_   )r…   r   r   rb   I  s    
zWatchdogReloaderLoop.__enter__c             C   s   | j jƒ  | j jƒ  d S )N)r’   Ústopr.   )r_   rc   rd   re   r   r   r   rf   N  s    
zWatchdogReloaderLoop.__exit__c             C   s.   x| j s| jƒ  tj| jƒ qW tjdƒ d S )Nro   )r¢   ra   rg   rh   r]   r
   rw   )r_   r   r   r   ri   R  s    zWatchdogReloaderLoop.runc             C   s¨   t | jƒ}xht| j| jƒD ]V}|| jkrfy| jj| j|dd�| j|< W n tk
rd   d | j|< Y nX |j	|ƒ qW x.|D ]&}| jj
|d ƒ}|d k	rz| jj|ƒ qzW d S )NT)Ú	recursive)r%   r£   r5   r   r   r’   Úscheduler¡   r‡   ÚdiscardrU   Z
unschedule)r_   Z	to_deleter   Zwatchr   r   r   ra   Y  s    


zWatchdogReloaderLoop.run_step)ry   rz   r{   rE   ZAnyr`   rG   rx   r\   rb   rf   ri   ra   rŠ   r   r   )r…   r   r‹     s   #r‹   )r‚   Úwatchdogzwatchdog.observersr‚   Úautor©   c              C   s~   t jdkst jjƒ  rdS yddl} W n tk
r:   dS X | jt jƒ}|d | j@ sz|d  | jO  < | jt j| j|ƒ dS )zuEnsure that echo mode is enabled. Some tools such as PDB disable
    it which causes usability issues after a reload.Nr   ro   )	r
   ÚstdinÚisattyÚtermiosÚImportErrorÚ	tcgetattrÚECHOÚ	tcsetattrÚTCSANOW)r­   Ú
attributesr   r   r   Úensure_echo_on~  s    r´   )Ú	main_funcr   r   r]   Úreloader_typer   c             C   s¤   ddl }|j |jdd„ ƒ t| |||d�}y^tjjdƒdkrztƒ  tj| f d�}d	|_	|� |j
ƒ  |jƒ  W dQ R X ntj|jƒ ƒ W n tk
rž   Y nX dS )
z<Run the given function in an independent Python interpreter.r   Nc              W   s
   t jdƒS )Nr   )r
   rw   )rZ   r   r   r   Ú<lambda>›  s    z#run_with_reloader.<locals>.<lambda>)r   r   r]   rl   rk   )ÚtargetrZ   T)ÚsignalÚSIGTERMÚreloader_loopsr   rp   rˆ   r´   Ú	threadingÚThreadÚdaemonr¤   ri   r
   rw   rt   ÚKeyboardInterrupt)rµ   r   r   r]   r¶   r¹   ZreloaderrE   r   r   r   Úrun_with_reloader‘  s    rÀ   )NNr   rª   )1r   r   rr   r
   r¼   rg   ÚtypingrE   Ú	itertoolsr   Zpathlibr   Z	_internalr   r>   Úbase_prefixÚexec_prefixÚbase_exec_prefixÚhasattrr'   r   Útupler*   ÚIteratorrG   r   ÚSetr   r}   r3   r5   r4   ÚListr[   r\   r�   r‹   r»   ÚDictÚTypeÚ
__import__r®   r´   ÚCallabler|   r~   r   r€   rÀ   r   r   r   r   Ú<module>   sN    
)<=T   8