3
e~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re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-3irwxpxt/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  }xt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 )zFind 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rtjj	| rtjj	| drtjj
|}tjdkrtjj	| rtjj	| dr|d7 }tjjt jd dkrt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