B
    }hb7                 @   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ejejhZeejejhZeedreej eeZ[ddd	d
dddh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 e*d%< 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j0e1e2f edd,d-d.Z3dS )0    N)chain)PurePath   )_logreal_prefix__pycache__z.gitz.hgz.toxz.noxz.pytest_cachez.mypy_cache)returnc              c   sn   xht tj D ]V} t| dd}|dks|tr4qx0tj	|s^|}tj
|}||kr6P q6W |V  qW dS )z;Find the filesystem paths associated with imported modules.__file__N)listsysmodulesvaluesgetattr
startswith_ignore_alwaysospathisfiledirname)modulenameold r   1lib/python3.7/site-packages/werkzeug/_reloader.py_iter_module_paths&   s    r   )pathsexclude_patternsr   c             C   s$   x|D ]}|  t| | 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|}tj|r@|| qtj	|di}xt
|D ]\}}}|tstj|tkr|  q\d}x.|D ]&}	|	drd}|tj||	 qW |s|tj	| s|  q\|||< q\W qW |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.
    TF)z.pyz.pyc)setr   r
   r   r   r   abspathr   addr   walkr   _stat_ignore_scanbasename_ignore_common_dirsclearendswithjoinupdater   r!   )
r"   r   r   r   Zparent_has_pyrootdirsfilesZhas_pyr   r   r   r   _find_stat_paths?   s0    




r1   c             C   s   t  }xFtttj| D ]2}tj|}tj|r@tj|}|	| qW x t
 D ]}|	t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   r/   r   r   r   r   _find_watchdog_pathsu   s    
r3   )r   r   c                s   i }xFt dd | D tddD ]*}|}x|D ]}||i }q,W |  qW t tjttf tj	tdf d d fdd  |d	 S )
Nc             s   s   | ]}t |jV  qd S )N)r   parts).0xr   r   r   	<genexpr>   s    z%_find_common_roots.<locals>.<genexpr>T)keyreverse.)noder   r   c                s@   x$|   D ]\}} |||f  q
W | s<tjj|  d S )N)itemsr%   r   r   r,   )r:   r   prefixZchild)_walkrvr   r   r=      s    z!_find_common_roots.<locals>._walkr   )
sortedlen
setdefaultr*   r#   tMappingstrdictZTuple)r   r.   Zchunksr:   chunkr   )r=   r>   r   r2      s    
,
r2   c              C   s\  t jg} t jd }t jdd }t jd }t|dddksltjdkr|jdkrtj	|stj	| drtj
|}tjdkrtj	|stj	| dr|d7 }tjt jd dkrtj|d dkr| d | | nftj|r6tt|j}tjtj|d }|dkr:|d	| 7 }n|}| d
|d	f | | | 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.exe.z-m)r   
executableargvr   r   r   r   rH   r   existsr$   splitextpopappendr   rB   castrD   r(   extendlstrip)r>   Z	py_scriptargsrG   Z	py_moduler   r   r   r   _get_args_for_reloading   s4    







rV   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 )ReloaderLooprJ   Nr   )r"   r   intervalr   c             C   s,   dd |pdD | _ t|pd| _|| _d S )Nc             S   s   h | ]}t j|qS r   )r   r   r$   )r5   r6   r   r   r   	<setcomp>   s    z(ReloaderLoop.__init__.<locals>.<setcomp>r   )r"   r#   r   rX   )selfr"   r   rX   r   r   r   __init__   s    zReloaderLoop.__init__)r   c             C   s   |    | S )zgDo any setup, then run one step of the watch to populate the
        initial filesystem state.
        )run_step)rZ   r   r   r   	__enter__   s    zReloaderLoop.__enter__c             C   s   dS )z4Clean up any resources associated with the reloader.Nr   )rZ   exc_typeexc_valexc_tbr   r   r   __exit__   s    zReloaderLoop.__exit__c             C   s   x|    t| j qW dS )zfContinually run the watch step, sleeping for the configured
        interval after each step.
        N)r\   timesleeprX   )rZ   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   )rZ   r   r   r   r\      s    zReloaderLoop.run_stepc             C   sP   xJt dd| j  t }t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)envZ	close_fds   N)r   r   rV   r   environcopy
subprocessZcall)rZ   rU   Znew_environZ	exit_coder   r   r   restart_with_reloader  s    
z"ReloaderLoop.restart_with_reloader)filenamer   c             C   s   |  | td d S )Nri   )
log_reloadr   exit)rZ   rn   r   r   r   trigger_reload  s    
zReloaderLoop.trigger_reloadc             C   s"   t j|}tdd|d d S )Nre   z * Detected change in z, reloading)r   r   r$   r   )rZ   rn   r   r   r   ro     s    zReloaderLoop.log_reload)NNr   )__name__
__module____qualname__r   rB   OptionalIterablerD   Unionintfloatr[   r]   ra   rd   r\   rm   rq   ro   r   r   r   r   rW      s     *rW   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  S )N)mtimessuperr]   )rZ   )	__class__r   r   r]     s    zStatReloaderLoop.__enter__Nc          	   C   sv   xpt | j| jD ]^}yt|j}W n tk
r:   wY nX | j|}|d kr\|| j|< q||kr| 	| qW d S )N)
r1   r"   r   r   r{   st_mtimeOSErrorr|   getrq   )rZ   r   mtimeZold_timer   r   r   r\     s    
zStatReloaderLoop.run_step)rr   rs   rt   r   rW   r]   r\   __classcell__r   r   )r~   r   rz     s   rz   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)rU   kwargsr   c                s   ddl m} ddlm} t j|| | j G  fddd|}|j }|	dr`|d d }d| d	| _
| | _d
d | jD }|d|dd t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)rZ   Zevent)rq   r   r   on_any_event9  s    z@WatchdogReloaderLoop.__init__.<locals>.EventHandler.on_any_eventN)rr   rs   rt   r   r   )rq   r   r   EventHandler8  s   r   observeriz
watchdog ()c             S   s   g | ]}t j|s|qS r   )r   r   isdir)r5   pr   r   r   
<listcomp>H  s    z1WatchdogReloaderLoop.__init__.<locals>.<listcomp>*.py*.pyc*.zipc             S   s   g | ]}d | dqS )z*/z/*r   )r5   dr   r   r   r   L  s    )ZpatternsZignore_patternsF)r   r   r   )Zwatchdog.observersr   Zwatchdog.eventsr   r}   r[   rq   rr   lowerr+   r   r   r"   r)   r   event_handlershould_reload)rZ   rU   r   r   r   r   Zreloader_nameZextra_patterns)r~   )rq   r   r[   1  s     

zWatchdogReloaderLoop.__init__)rn   r   c             C   s   d| _ | | d S )NT)r   ro   )rZ   rn   r   r   r   rq   R  s    z#WatchdogReloaderLoop.trigger_reload)r   c                s   i | _ | j  t  S )N)watchesr   startr}   r]   )rZ   )r~   r   r   r]   Y  s    
zWatchdogReloaderLoop.__enter__c             C   s   | j   | j   d S )N)r   stopr,   )rZ   r^   r_   r`   r   r   r   ra   ^  s    
zWatchdogReloaderLoop.__exit__c             C   s.   x| j s|   t| j qW td d S )Nri   )r   r\   rb   rc   rX   r   rp   )rZ   r   r   r   rd   b  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 |	| qW x.|D ]&}| j
|d }|d k	rz| j| qzW d S )NT)	recursive)r#   r   r3   r"   r   r   Zscheduler   r   discardrP   Z
unschedule)rZ   Z	to_deleter   Zwatchr   r   r   r\   i  s    


zWatchdogReloaderLoop.run_step)rr   rs   rt   rB   ZAnyr[   rD   rq   rW   r]   ra   rd   r\   r   r   r   )r~   r   r   0  s   !r   )r{   watchdogreloader_loopszwatchdog.observersr{   autor   c              C   s|   t jdkst j sdS yddl} W n tk
r8   dS X | t j}|d | j@ sx|d  | jO  < | 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   ri   )	r   stdinisattytermiosImportErrorZ	tcgetattrZECHOZ	tcsetattrZTCSANOW)r   Z
attributesr   r   r   ensure_echo_on  s    r   )	main_funcr"   r   rX   reloader_typer   c          	   C   s   ddl }| |jdd  t| |||d}y^tjddkrzt  tj| dd	}d
|_	| |
  |  W dQ R X nt|  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 dS )Nr   )r   rp   )rU   r   r   r   <lambda>      z#run_with_reloader.<locals>.<lambda>)r"   r   rX   rg   rf   r   )targetrU   T)signalSIGTERMr   r   rj   r   r   	threadingZThreadZdaemonr   rd   r   rp   rm   KeyboardInterrupt)r   r"   r   rX   r   r   ZreloaderrB   r   r   r   run_with_reloader  s    r   )NNr   r   )4r   r   rl   r   r   rb   typingrB   	itertoolsr   Zpathlibr   Z	_internalr   tuplebase_prefixbase_exec_prefixr   r<   exec_prefixhasattrr%   r   r'   r)   IteratorrD   r   Setr!   rv   r1   r3   r2   ZListrV   rW   rz   r   r   ZDictZType__annotations__
__import__r   r   Callableru   rw   rx   ry   r   r   r   r   r   <module>   s^    
56=R    8