3
 [ð]-  ã               @   s  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	 ddlm
Z
 ddlmZ dd	„ Zdd
d„Zdd„ Zdd„ ZG dd„ deƒZG dd„ deƒZG dd„ deƒZeedœZyedƒ W n  ek
rì   ed ed< Y nX ed ed< dd„ Zd dd„ZdS )!é    N)Úchainé   )Ú	iteritems)ÚPY2)Ú	text_type)Ú_logc              c   s¸   x²t tjjƒ ƒD ] } | dkrqt| ddƒ}|rtjj|ƒr^tjjtjj	|dƒƒr^tjj	|dƒ}d}xLtjj
|ƒsŒ|}tjj|ƒ}||krdP qdW |dd… d	krª|dd
… }|V  qW dS )zËThis iterates over all relevant Python files.  It goes through all
    loaded files from modules, all files in folders of already loaded modules
    as well as all files reachable through a package.
    NÚ__file__z__init__.pyé   ú.pycú.pyor   éüÿÿÿ)r
   r   éÿÿÿÿ)ÚlistÚsysÚmodulesÚvaluesÚgetattrÚosÚpathÚisdirÚexistsÚjoinÚisfileÚdirname)ÚmoduleÚfilenameÚold© r   ú6/tmp/pip-build-w1as9q70/Werkzeug/werkzeug/_reloader.pyÚ_iter_module_files   s"    r   c             C   s”   t dd„ tjD ƒƒ}x*| pf D ]}|jtjjtjj|ƒƒƒ qW xJttjj	ƒ ƒD ]8}t
|ddƒ}|dkrjqPtjj|ƒ}|jtjj|ƒƒ qPW t|ƒS )z(Finds all paths that should be observed.c             s   s:   | ]2}t jj|ƒr&t jjt jj|ƒƒn
t jj|ƒV  qd S )N)r   r   r   r   Úabspath)Ú.0Úxr   r   r   ú	<genexpr>.   s   z)_find_observable_paths.<locals>.<genexpr>r   N)Úsetr   r   Úaddr   r   r    r   r   r   r   Ú_find_common_roots)Úextra_filesÚrvr   r   Úfnr   r   r   Ú_find_observable_paths+   s    r*   c              C   sh  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rètjj	|ƒ rètjj	|d ƒrètjj
|ƒ}tjdkrÜtjj	|ƒ r¨tjj	|d ƒr¨|d7 }tjjt jƒd dkrÜtjj|ƒd dkrÜ| jdƒ | j|ƒ nrt jd d	krþt j}n\tjj|ƒ�rB|j}tjjtjj|ƒƒd }|dk�rF|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   Únamer,   r   r   r    ÚsplitextÚpopÚappendr   ÚbasenameÚextendÚlstrip)r(   Z	py_scriptÚargsr+   Z	py_moduler2   r   r   r   Ú_get_args_for_reloading?   s8    







r:   c                sr   dd„ | D ƒ} i }x<t | tdd�D ]*}|}x|D ]}|j|i ƒ}q0W |jƒ  q"W tƒ ‰‡ ‡fdd„‰ ˆ |f ƒ ˆS )zAOut of some paths it finds the common roots that need monitoring.c             S   s   g | ]}|j tjjƒ‘qS r   )Úsplitr   r   Úsep)r!   r"   r   r   r   ú
<listcomp>}   s    z&_find_common_roots.<locals>.<listcomp>T)ÚkeyÚreversec                s>   x$t | ƒD ]\}}ˆ |||f ƒ q
W | s:ˆjdj|ƒƒ d S )Nú/)r   r%   r   )Únoder   ÚprefixÚchild)Ú_walkr(   r   r   rD   ‡   s    z!_find_common_roots.<locals>._walk)ÚsortedÚlenÚ
setdefaultÚclearr$   )ÚpathsÚrootÚchunksrA   Úchunkr   )rD   r(   r   r&   {   s    

r&   c               @   sD   e Zd ZdZeejƒZddd„Zdd„ Z	dd„ Z
d	d
„ Zdd„ ZdS )ÚReloaderLoopNr   c             C   s"   t dd„ |pf D ƒƒ| _|| _d S )Nc             s   s   | ]}t jj|ƒV  qd S )N)r   r   r    )r!   r"   r   r   r   r#   š   s    z(ReloaderLoop.__init__.<locals>.<genexpr>)r$   r'   Úinterval)Úselfr'   rN   r   r   r   Ú__init__™   s    zReloaderLoop.__init__c             C   s   d S )Nr   )rO   r   r   r   Úrun�   s    zReloaderLoop.runc             C   sª   x¤t dd| j ƒ tƒ }tjdkrttrti }xRttjƒD ]8\}}t|tƒrR|j	dƒ}t|tƒrf|j	dƒ}|||< q6W n
tjj
ƒ }d|d< tj||dd�}|d	kr|S qW d
S )zuSpawn a new Python interpreter with the same arguments as this one,
        but running the reloader thread.
        Úinfoz * Restarting with %sr-   z
iso-8859-1ÚtrueÚWERKZEUG_RUN_MAINF)ÚenvÚ	close_fdsé   N)r   r2   r:   r   r   r   ÚenvironÚ
isinstancer   ÚencodeÚcopyÚ
subprocessÚcall)rO   r9   Znew_environr>   ÚvalueZ	exit_coder   r   r   Úrestart_with_reloader    s     




z"ReloaderLoop.restart_with_reloaderc             C   s   | j |ƒ tjdƒ d S )NrW   )Ú
log_reloadr   Úexit)rO   r   r   r   r   Útrigger_reload»   s    
zReloaderLoop.trigger_reloadc             C   s   t jj|ƒ}tdd| ƒ d S )NrR   z# * Detected change in %r, reloading)r   r   r    r   )rO   r   r   r   r   r`   ¿   s    zReloaderLoop.log_reload)Nr   )Ú__name__Ú
__module__Ú__qualname__r2   ÚstaticmethodÚtimeÚsleepÚ_sleeprP   rQ   r_   rb   r`   r   r   r   r   rM   ‘   s   

rM   c               @   s   e Zd ZdZdd„ ZdS )ÚStatReloaderLoopÚstatc             C   sŠ   i }x€xnt tƒ | jƒD ]\}ytj|ƒj}W n tk
r@   wY nX |j|ƒ}|d kr`|||< qq||kr| j|ƒ qW | j	| j
ƒ qW d S )N)r   r   r'   r   rk   Úst_mtimeÚOSErrorÚgetrb   ri   rN   )rO   Zmtimesr   ÚmtimeZold_timer   r   r   rQ   Ç   s    
zStatReloaderLoop.runN)rc   rd   re   r2   rQ   r   r   r   r   rj   Ä   s   rj   c               @   s$   e Zd Zdd„ Zdd„ Zdd„ ZdS )ÚWatchdogReloaderLoopc                s˜   t jˆf|ž|Ž ddlm} ddlm} tƒ ˆ_‡fdd„‰ G ‡ fdd„d|ƒ}|jj	ƒ }|j
dƒrr|d d… }|d
7 }|ˆ_|ˆ_|ƒ ˆ_dˆ_d S )Nr   )ÚObserver)ÚFileSystemEventHandlerc                sH   | ˆ j krˆ j| ƒ tjj| ƒ}|jtˆ jƒƒrD| jdƒrDˆ j| ƒ d S )Nú.pycú.pyoú.py)rs   rt   ru   )	r'   rb   r   r   r   Ú
startswithÚtupleÚobservable_pathsÚendswith)r   r   )rO   r   r   Ú_check_modificationá   s    


z:WatchdogReloaderLoop.__init__.<locals>._check_modificationc                   s<   e Zd Z‡ fdd„Z‡ fdd„Z‡ fdd„Z‡ fdd„Zd	S )
z5WatchdogReloaderLoop.__init__.<locals>._CustomHandlerc                s   ˆ |j ƒ d S )N)Úsrc_path)rO   Úevent)rz   r   r   Ú
on_createdê   s    z@WatchdogReloaderLoop.__init__.<locals>._CustomHandler.on_createdc                s   ˆ |j ƒ d S )N)r{   )rO   r|   )rz   r   r   Úon_modifiedí   s    zAWatchdogReloaderLoop.__init__.<locals>._CustomHandler.on_modifiedc                s   ˆ |j ƒ ˆ |jƒ d S )N)r{   Z	dest_path)rO   r|   )rz   r   r   Úon_movedð   s    
z>WatchdogReloaderLoop.__init__.<locals>._CustomHandler.on_movedc                s   ˆ |j ƒ d S )N)r{   )rO   r|   )rz   r   r   Ú
on_deletedô   s    z@WatchdogReloaderLoop.__init__.<locals>._CustomHandler.on_deletedN)rc   rd   re   r}   r~   r   r€   r   )rz   r   r   Ú_CustomHandleré   s   r�   Úobserveré   z	 reloaderFiøÿÿÿ)rM   rP   Zwatchdog.observersrq   Zwatchdog.eventsrr   r$   rx   rc   Úlowerry   r2   Úobserver_classÚevent_handlerÚshould_reload)rO   r9   Úkwargsrq   rr   r�   Zreloader_namer   )rz   rO   r   rP   Ú   s    

zWatchdogReloaderLoop.__init__c             C   s   d| _ | j|ƒ d S )NT)r‡   r`   )rO   r   r   r   r   rb     s    z#WatchdogReloaderLoop.trigger_reloadc             C   sî   i }| j ƒ }|jƒ  z¸x²| jsÈt|ƒ}t| jƒ}xV|D ]N}||krzy|j| j|dd�||< W n tk
rx   d ||< Y nX |j	|ƒ q6W x*|D ]"}|j
|d ƒ}|d k	rŽ|j|ƒ qŽW || _| j| jƒ qW W d |jƒ  |jƒ  X tjdƒ d S )NT)Ú	recursiverW   )r…   Ústartr‡   r$   r*   r'   Úscheduler†   rm   Údiscardr4   Z
unschedulerx   ri   rN   Ústopr   r   ra   )rO   Zwatchesr‚   Z	to_deleterI   r   Zwatchr   r   r   rQ   	  s0    



zWatchdogReloaderLoop.runN)rc   rd   re   rP   rb   rQ   r   r   r   r   rp   Ù   s   (rp   )rk   Úwatchdogzwatchdog.observersrk   ÚautorŽ   c              C   sr   t jjƒ sdS yddl} W n tk
r.   dS X | jt jƒ}|d | j@ sn|d  | jO  < | jt j| j|ƒ dS )zsEnsure that echo mode is enabled. Some tools such as PDB disable
    it which causes usability issues after reload.Nr   rW   )	r   ÚstdinÚisattyÚtermiosÚImportErrorÚ	tcgetattrÚECHOÚ	tcsetattrÚTCSANOW)r’   Ú
attributesr   r   r   Úensure_echo_on5  s    
r™   c             C   s”   ddl }t| ||ƒ}|j |jdd„ ƒ yRtjjdƒdkrjtƒ  tj| f d�}|j	dƒ |j
ƒ  |jƒ  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   ra   )r9   r   r   r   Ú<lambda>J  s    z#run_with_reloader.<locals>.<lambda>rT   rS   )Útargetr9   T)ÚsignalÚreloader_loopsÚSIGTERMr   rX   rn   r™   Ú	threadingÚThreadÚ	setDaemonrŠ   rQ   r   ra   r_   ÚKeyboardInterrupt)Z	main_funcr'   rN   Zreloader_typerœ   ZreloaderÚtr   r   r   Úrun_with_reloaderE  s    

r¤   )N)Nr   r�   )r   r\   r   rŸ   rg   Ú	itertoolsr   Ú_compatr   r   r   Z	_internalr   r   r*   r:   r&   ÚobjectrM   rj   rp   r�   Ú
__import__r“   r™   r¤   r   r   r   r   Ú<module>   s0   
<3R
