3
d~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-icgu1mr8/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dictZ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   rL   r   existsr&   splitextpopappendr   rE   castrG   r+   extendlstrip)rA   Z	py_scriptargsrK   Z	py_moduler   r   r   r   _get_args_for_reloading   s8    




 


rZ   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 )ReloaderLooprN   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)r`   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   r`      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   rZ   r   environcopy
subprocesscall)r^   rY   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 )Nrn   )
log_reloadr
   exit)r^   rt   r   r   r   trigger_reload   s    
zReloaderLoop.trigger_reloadc             C   s"   t jj|}tdd|d d S )Nri   z * Detected change in z, reloading)r   r   r&   r   )r^   rt   r   r   r   ru     s    zReloaderLoop.log_reload)NNr   )__name__
__module____qualname__r   rE   OptionalIterablerG   Unionintfloatr_   ra   re   rh   r`   rs   rw   ru   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superra   )r^   )	__class__r   r   ra   	  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   getrw   )r^   r   mtimeZold_timer   r   r   r`     s    
zStatReloaderLoop.run_step)rx   ry   rz   r   r[   ra   r`   __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)rY   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)rw   r   r   on_any_event'  s    z@WatchdogReloaderLoop.__init__.<locals>.EventHandler.on_any_eventN)rx   ry   rz   r   r   )rw   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_   rw   rx   lowerr-   r   r   r   r   event_handlershould_reload)r^   rY   r   r   r   r   Zreloader_nameZextra_patterns)r   )rw   r   r_     s$    

  zWatchdogReloaderLoop.__init__)rt   r   c             C   s   d| _ | j| d S )NT)r   ru   )r^   rt   r   r   r   rw   B  s    z#WatchdogReloaderLoop.trigger_reload)r   c                s   i | _ | jj  t j S )N)watchesr   startr   ra   )r^   )r   r   r   ra   I  s    
zWatchdogReloaderLoop.__enter__c             C   s   | j j  | j j  d S )N)r   stopr.   )r^   rb   rc   rd   r   r   r   re   N  s    
zWatchdogReloaderLoop.__exit__c             C   s.   x| j s| j  tj| j qW tjd d S )Nrn   )r   r`   rf   rg   r\   r
   rv   )r^   r   r   r   rh   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   discardrT   Z
unschedule)r^   Z	to_deleter   Zwatchr   r   r   r`   Y  s    


zWatchdogReloaderLoop.run_step)rx   ry   rz   rE   ZAnyr_   rG   rw   r[   ra   re   rh   r`   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   rn   )	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
   rv   )rY   r   r   r   <lambda>  s    z#run_with_reloader.<locals>.<lambda>)r   r   r\   rk   rj   )targetrY   T)signalSIGTERMreloader_loopsr   ro   r   r   	threadingThreaddaemonr   rh   r
   rv   rs   KeyboardInterrupt)r   r   r   r\   r   r   ZreloaderrE   r   r   r   run_with_reloader  s    r   )NNr   r   )1r   r   rq   r
   r   rf   ZtypingrE   	itertoolsr   Zpathlibr   Z	_internalr   r>   base_prefixexec_prefixbase_exec_prefixhasattrr'   r   tupler*   IteratorrG   r   Setr   r|   r3   r5   r4   ZListrZ   r[   r   r   r   DictType
__import__r   r   Callabler{   r}   r~   r   r   r   r   r   r   <module>   sN    
)<=T   8