U
    :xgE<                     @  s  U d dl m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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ddddZddddddZddddddZddddddZddddd Zd!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$d+e%d,< ze&d- W n" e'k
r   e$d. e$d/< Y nX e$d0 e$d/< ddd1d2Z(d:d3d4d4d5d6dd7d8d9Z)dS );    )annotationsN)chain)PurePath   )_logreal_prefix__pycache__z.gitz.hgz.toxz.noxz.pytest_cachez.mypy_cachezt.Iterator[str]returnc                  c  sf   t tj D ]R} t| dd}|dks|tr2qtj	|sZ|}tj
|}||kr2qq2|V  q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   6/tmp/pip-unpacked-wheel-5ifiwx3z/werkzeug/_reloader.py_iter_module_paths(   s    r   zset[str]None)pathsexclude_patternsr
   c                 C  s    |D ]}|  t| | qd S N)difference_updatefnmatchfilter)r   r   patternr   r   r   _remove_by_pattern<   s    r%   zt.Iterable[str])extra_filesr   r
   c           
   	   C  s   t  }tttj| D ]}tj|}tj|r>|| qtj	|di}t
|D ]\}}}|ts|tj|tkr|  qXd}|D ]&}	|	drd}|tj||	 q|s|tj	| s|  qX|||< qXq|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_pathsA   s4    


r5   c                 C  sz   t  }tttj| D ]2}tj|}tj|r>tj|}|	| qt
 D ]}|	tj| qPt|| 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   r3   r   r   r   r   _find_watchdog_pathsw   s    

r7   )r   r
   c                   sp   i }t dd | D tddD ]&}|}|D ]}||i }q(|  qt dddd fd	d
  |d S )Nc                 s  s   | ]}t |jV  qd S r    )r   parts.0xr   r   r   	<genexpr>   s     z%_find_common_roots.<locals>.<genexpr>T)keyreversez t.Mapping[str, dict[str, t.Any]]ztuple[str, ...]r   )noder   r
   c                   s@   |   D ]\}} |||f  q| s<|r<tjj|  d S r    )itemsr)   r   r   r0   )r?   r   prefixchild_walkrvr   r   rD      s    z!_find_common_roots.<locals>._walkr   )sortedlen
setdefaultr.   r'   )r   r2   chunksr?   chunkr   rC   r   r6      s    
	
r6   z	list[str]c                  C  s  t jdkr t jft jdd S t jg} t jd }t jdd }t jd }t|dddkstjdkr|j	dkrtj
|stj
| d	rtj
|}tjdkr
tj
|stj
| d	r|d	7 }tj
t jd d	kr
tj
|d d	kr
| d | | nftj
|rdtt|j	}tj
tj
|d }|dkrh|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   Nr   __main____package__nt z.exe.z-m)r   version_info
executableZ	orig_argvargvr   r   r   r   rN   r   existsr(   splitextpopappendr   tcaststrr,   extendlstrip)rE   Z	py_scriptargsrM   Z	py_moduler   r   r   r   _get_args_for_reloading   sD    






r_   c                   @  s   e Zd ZdZdddddddd	Zd d
ddZdd Zdd
ddZdd
ddZdd
ddZ	dddddZ
dddddZdS )ReloaderLooprP   Nr   t.Iterable[str] | Noneint | floatr   )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(   r9   r   r   r   	<setcomp>   s     z(ReloaderLoop.__init__.<locals>.<setcomp>r   )r&   r'   r   rc   )selfr&   r   rc   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re   r   r   r   	__enter__   s    zReloaderLoop.__enter__c                 C  s   dS )z4Clean up any resources associated with the reloader.Nr   re   exc_typeexc_valexc_tbr   r   r   __exit__   s    zReloaderLoop.__exit__c                 C  s   |    t| j q dS )zfContinually run the watch step, sleeping for the configured
        interval after each step.
        N)rg   timesleeprc   rh   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   rh   r   r   r   rg     s    zReloaderLoop.run_stepintc                 C  sL   t dd| j  t }tj }d|d< tj||dd}|dkr |S q 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_fdsrK   N)r   r   r_   r   environcopy
subprocesscall)re   r^   Znew_environZ	exit_coder   r   r   restart_with_reloader
  s    
z"ReloaderLoop.restart_with_reloaderr[   filenamer
   c                 C  s   |  | td d S NrK   )
log_reloadr   exitre   r~   r   r   r   trigger_reload  s    
zReloaderLoop.trigger_reloadstr | bytesc                 C  s"   t j|}tdd|d d S )Nrs   z * Detected change in z, reloading)r   r   r(   r   r   r   r   r   r     s    zReloaderLoop.log_reload)NNr   )__name__
__module____qualname__r   rf   ri   rn   rq   rg   r|   r   r   r   r   r   r   r`      s      
r`   c                      s4   e Zd ZdZdd fddZddddZ  ZS )	StatReloaderLoopstatr`   r	   c                   s   i | _ t  S r    )mtimessuperri   rh   	__class__r   r   ri   $  s    zStatReloaderLoop.__enter__r   c              	   C  st   t | j| jD ]`}zt|j}W n tk
r:   Y qY nX | j|}|d kr\|| j|< q||kr| 	| qd S r    )
r5   r&   r   r   r   st_mtimeOSErrorr   getr   )re   r   mtimeZold_timer   r   r   rg   (  s    

zStatReloaderLoop.run_step)r   r   r   r   ri   rg   __classcell__r   r   r   r   r   !  s   r   c                      sl   e Zd Zdddd fddZddddd	Zd
d fddZdd ZddddZddddZ  Z	S )WatchdogReloaderLoopzt.Anyr   )r^   kwargsr
   c                   s  ddl m  ddl m ddl m ddl m ddl m ddl m 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   )EVENT_TYPE_CLOSED)EVENT_TYPE_CREATED)EVENT_TYPE_DELETED)EVENT_TYPE_MODIFIED)EVENT_TYPE_MOVED)FileModifiedEvent)PatternMatchingEventHandler)Observerc                      s(   e Zd Zdd fddZdS )z3WatchdogReloaderLoop.__init__.<locals>.EventHandlerr   )eventc                   s&   |j  hkrd S |j d S r    )Z
event_typeZsrc_path)re   r   )r   r   r   r   r   r   r   r   on_any_eventH  s    z@WatchdogReloaderLoop.__init__.<locals>.EventHandler.on_any_eventN)r   r   r   r   r   r   r   r   r   r   r   r   r   r   EventHandlerG  s   r   observeriz
watchdog ()c                 S  s   g | ]}t j|s|qS r   )r   r   isdir)r:   pr   r   r   
<listcomp>a  s      z1WatchdogReloaderLoop.__init__.<locals>.<listcomp>*.py*.pyc*.zipc                 S  s   g | ]}d | dqS )z*/z/*r   )r:   dr   r   r   r   e  s     )patternsignore_patternsF)r   r   r   )Zwatchdog.eventsr   r   r   r   r   r   r   Zwatchdog.observersr   r   rf   r   r   lowerr/   r   r   r&   r-   r   event_handlershould_reload)re   r^   r   r   r   r   Zreloader_nameZextra_patternsr   r   r   rf   :  s0     

zWatchdogReloaderLoop.__init__r   r}   c                 C  s   d| _ | | d S )NT)r   r   r   r   r   r   r   k  s    z#WatchdogReloaderLoop.trigger_reloadr`   r	   c                   s   i | _ | j  t  S r    )watchesr   startr   ri   rh   r   r   r   ri   r  s    
zWatchdogReloaderLoop.__enter__c                 C  s   | j   | j   d S r    )r   stopr0   rj   r   r   r   rn   w  s    
zWatchdogReloaderLoop.__exit__c                 C  s*   | j s|   t| j q td d S r   )r   rg   ro   rp   rc   r   r   rh   r   r   r   rq   {  s    zWatchdogReloaderLoop.runc              	   C  s   t | j}t| j| jD ]V}|| jkrdz| jj| j|dd| j|< W n tk
rb   d | j|< Y nX |	| q|D ]&}| j
|d }|d k	rt| j| qtd S )NT)	recursive)r'   r   r7   r&   r   r   scheduler   r   discardrW   Z
unschedule)re   Z	to_deleter   Zwatchr   r   r   rg     s     

  zWatchdogReloaderLoop.run_step)
r   r   r   rf   r   ri   rn   rq   rg   r   r   r   r   r   r   9  s   1r   )r   watchdogzdict[str, type[ReloaderLoop]]reloader_loopszwatchdog.observersr   autor   c                  C  s~   t jdkst j sdS zddl} W n tk
r:   Y dS X | t j}|d | j@ sz|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   rK   )	r   stdinisattytermiosImportError	tcgetattrECHO	tcsetattrTCSANOW)r   
attributesr   r   r   ensure_echo_on  s    r   zt.Callable[[], None]ra   rb   r[   )	main_funcr&   r   rc   reloader_typer
   c              	   C  s   ddl }| |jdd  t| |||d}z^tjddkrzt  tj| dd	}d
|_	| |
  |  W 5 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   r   )r^   r   r   r   <lambda>      z#run_with_reloader.<locals>.<lambda>)r&   r   rc   ru   rt   r   )targetr^   T)signalSIGTERMr   r   rx   r   r   	threadingThreaddaemonr   rq   r   r   r|   KeyboardInterrupt)r   r&   r   rc   r   r   ZreloaderrY   r   r   r   run_with_reloader  s$      r   )NNr   r   )*
__future__r   r"   r   rz   r   r   ro   typingrY   	itertoolsr   pathlibr   	_internalr   tuplebase_prefixbase_exec_prefixr   rA   exec_prefixhasattrr)   r   r+   r-   r   r%   r5   r7   r6   r_   r`   r   r   r   __annotations__
__import__r   r   r   r   r   r   r   <module>   s`    
6;=b    