
_-                 @   sw  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 Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z d e d e i Z y e d  Wn  e k
 rCe d e d <Yn Xe d e d <d d   Z d d 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 } xf t j j
 |  s | } t j j |  } | | k r Pq W| d d  d	 k r | d d
  } | Vq Wd S)zThis 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-5gj8f0j9/Werkzeug/werkzeug/_reloader.py_iter_module_files   s"    r   c             C   s   t  d d   t j D  } x9 |  p( f  D]+ } | j t j j t j j |    q) Wxi t t j j	    D]R } t
 | d d  } | d k r qn t j j |  } | j t j j |   qn Wt |  S)z(Finds all paths that should be observed.c             s   sQ   |  ]G } t  j j |  r9 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   s  t  j g }  t  j d } t  j d d  } t  j d } t | d d  d k s t j d k rD| j d k rDt j j	 |  rDt j j	 | d  rDt j j
 |  } t j d k r4t j j	 |  r t j j	 | d  r | d 7} t j j t  j  d d k r4t j j |  d d k r4|  j d  |  j |  n t  j d d	 k rct  j } n| t j j |  r| j } t j j t j j |   d } | d k r| 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                s   d d   |  D }  i  } xS t  |  d t d d D]9 } | } x  | D] } | j | i   } qE W| j   q2 Wt       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 Sr   )splitr   r   sep)r!   r"   r   r   r   
<listcomp>}   s   	 z&_find_common_roots.<locals>.<listcomp>keyreverseTc                sQ   x. t  |   D]  \ } }   | | | f  q W|  sM  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               @   sg   e  Z d  Z d Z e e j  Z d 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 r t r i  } xu t t j  D]R \ } } t | t  ru | j	 d  } t | t  r | j	 d  } | | | <qK Wn t j j
   } d | d <t j | d | d d	 } | d
 k r | Sq Wd 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_MAINenv	close_fdsF   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)__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 x t  t   |  j  D]x } y t j |  j } Wn t k
 rR w Yn X| j |  } | d  k r~ | | | <q q | | k r |  j |  q W|  j	 |  j
  q	 Wd  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               @   s4   e  Z d  Z d d   Z d d   Z d d   Z d S)WatchdogReloaderLoopc                s   t  j  | |  d d l m } d d l m } t    _  f d d     G  f d d   d |  } | j j	   } | j
 d  r | d  d  } | d
 7} |  _ |  _ |    _ d  _ d  S)Nr   )Observer)FileSystemEventHandlerc                sf   |    j  k r   j |   t j j |   } | j t   j   rb |  j d  rb   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                   sX   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   s5  i  } |  j    } | j   z x |  j s
t |  } t |  j  } xi | D]a } | | k r y# | j |  j | d d | | <Wn t k
 r d  | | <Yn X| j	 |  qM Wx9 | D]1 } | j
 | d   } | d  k	 r | j |  q W| |  _ |  j |  j  q" WWd  | j   | j   Xt j d  d  S)N	recursiveTrW   )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   Zwatchdogzwatchdog.observersZautoc              C   s   t  j j   s d Sy d d l }  Wn t k
 r; d SYn X|  j t  j  } | d |  j @s | 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    yr t j j d  d k r t   t j d |  d f   } | j	 d	  | j
   | j   n t j | j    Wn t k
 r Yn Xd 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   )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