U
    /v¶hE<  ã                   @  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ƒr e 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-c3xdgso7/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¡rŽd}| 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 )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   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s”tjdk�r|j	dk�rtj
 |¡�stj
 |› d	�¡�rtj
 |¡}tjdk�r
tj
 |¡sÒt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    Úobserveriøÿÿÿz
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þ    û