+
    i=                     p   ^ RI t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H
t
 ^ RIHt ^ RIHt ^ RIHt ^ RIHt ^ RIHtHtHtHtHtHtHtHtHtHt ^ RIt^RIH t  ^R	I!H"t"H#t#H$t$H%t% ]'       d   ^ R
IH&t& R6t']PP                  ! R4      t)RR7RRRRRRR] ! 4       R^ RRR^2RRR^R^RRRR/R R llt*RR7RRRRRRR] ! 4       R^ RRR^2RRRRRR/R R  llt+]! R!4      t,R" R# lt-R8R$ R% llt.R& R' lt/ ! R( R)4      t0R* R+ lt1R, R- lt2R. R/ lt3] Ph                  R0 R1 l4       t5R2 R3 lt6R4 R5 lt7R# )9    N)import_module)get_context)SpawnProcess)Path)sleep)
TYPE_CHECKINGAnyCallableDict	GeneratorListOptionalSetTupleUnion)DefaultFilter)Change
FileChangeawatchwatch)Literalzwatchfiles.mainargskwargstarget_typeautocallbackwatch_filtergrace_perioddebouncei@  stepdebugsigint_timeoutsigkill_timeout	recursiveTignore_permission_deniedFc                 "   V ^8  d   QhR\         \        \        3,          R\         \        \        R\        3,          3,          R\
        \        R3,          R\        \        \        \        3,          ,          RRR\        \        \        \        ,          .R	3,          ,          R
\        \        \        \        .\        3,          ,          R\        R\        R\        R\        \        ,          R\        R\        R\        R\        R\        /# )   pathstarget.r   r   r   &Literal['function', 'command', 'auto']r   Nr   r   r   r    r!   r"   r#   r$   r%   returnr   r   strr
   r	   r   r   r   r   r   r   boolfloatint)formats   "wC:\Users\petid\OneDrive\Desktop\Maestro\MAESTRO CLAUDE\MAESTRO\maestro-backend\venv\Lib\site-packages\watchfiles\run.py__annotate__r3      s    } }$)}#xS))*} S/} T#s(^$	}
 :} xZ 14 789} 8VSM4$789} } } } D>} } } } #}  	!}    c                   VR8X  d   \        V 4      p\        P                  RW4       \        4        \	        WW4      p^ pV'       d"   \        P                  RV4       \        V4        \        VRVRVRVRV	RR	R
VRV/  F=  pT;'       d	    V! V4       VP                  WR7       \	        WWV4      pV^,          pK?  	  VP                  4        V#   TP                  4        i ; i)u  
Run a process and restart it upon file changes.

`run_process` can work in two ways:

* Using `multiprocessing.Process` † to run a python function
* Or, using `subprocess.Popen` to run a command

!!! note

    **†** technically `multiprocessing.get_context('spawn').Process` to avoid forking and improve
    code reload/import.

Internally, `run_process` uses [`watch`][watchfiles.watch] with `raise_interrupt=False` so the function
exits cleanly upon `Ctrl+C`.

Args:
    *paths: matches the same argument of [`watch`][watchfiles.watch]
    target: function or command to run
    args: arguments to pass to `target`, only used if `target` is a function
    kwargs: keyword arguments to pass to `target`, only used if `target` is a function
    target_type: type of target. Can be `'function'`, `'command'`, or `'auto'` in which case
        [`detect_target_type`][watchfiles.run.detect_target_type] is used to determine the type.
    callback: function to call on each reload, the function should accept a set of changes as the sole argument
    watch_filter: matches the same argument of [`watch`][watchfiles.watch]
    grace_period: number of seconds after the process is started before watching for changes
    debounce: matches the same argument of [`watch`][watchfiles.watch]
    step: matches the same argument of [`watch`][watchfiles.watch]
    debug: matches the same argument of [`watch`][watchfiles.watch]
    sigint_timeout: the number of seconds to wait after sending sigint before sending sigkill
    sigkill_timeout: the number of seconds to wait after sending sigkill before raising an exception
    recursive: matches the same argument of [`watch`][watchfiles.watch]

Returns:
    number of times the function was reloaded.

```py title="Example of run_process running a function"
from watchfiles import run_process

def callback(changes):
    print('changes detected:', changes)

def foobar(a, b):
    print('foobar called with:', a, b)

if __name__ == '__main__':
    run_process('./path/to/dir', target=foobar, args=(1, 2), callback=callback)
```

As well as using a `callback` function, changes can be accessed from within the target function,
using the `WATCHFILES_CHANGES` environment variable.

```py title="Example of run_process accessing changes"
from watchfiles import run_process

def foobar(a, b, c):
    # changes will be an empty list "[]" the first time the function is called
    changes = os.getenv('WATCHFILES_CHANGES')
    changes = json.loads(changes)
    print('foobar called due to changes:', changes)

if __name__ == '__main__':
    run_process('./path/to/dir', target=foobar, args=(1, 2, 3))
```

Again with the target as `command`, `WATCHFILES_CHANGES` can be used
to access changes.

```bash title="example.sh"
echo "changers: ${WATCHFILES_CHANGES}"
```

```py title="Example of run_process running a command"
from watchfiles import run_process

if __name__ == '__main__':
    run_process('.', target='./example.sh')
```
r   running "%s" as %s3sleeping for %s seconds before watching for changesr   r   r    r!   raise_interruptFr$   r%   )r"   r#   )detect_target_typeloggerr!   catch_sigtermstart_processr   r   stop)r)   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r(   processreloadschangess   $$$$$$$$$$$$$$*   r2   run_processrA      s   @ f(0
LL%v;OF>GGJLYl	
%	
 	
 		

 	
 "	
  	
 &>	
G **'*LLLX#FwOGqLG	
 	N 	s   +"C 5C C'c                   V ^8  d   QhR\         \        \        3,          R\         \        \        R\        3,          3,          R\
        \        R3,          R\        \        \        \        3,          ,          RRR\        \        \        \        ,          .\        3,          ,          R	\        \        \        \        .\        3,          ,          R
\        R\        R\        R\        \        ,          R\        R\        R\        /# )r'   r(   r)   .r   r   r   r*   r   r   r   r   r    r!   r$   r%   r+   r,   )r1   s   "r2   r3   r3      s    M M$)M#xS))*M S/M T#s(^$	M
 :M xZ 13 678M 8VSM4$789M M M M D>M M #M 	Mr4   c                :  "   ^ RI pVR8X  d   \        V 4      p\        P                  RW4       \	        4        \
        P                  P                  \        WW4      G Rj  xL
 p^ pV'       d5   \        P                  RV4       \
        P                  ! V4      G Rj  xL
  \        VRVRVRVRV	R	V
R
V/   Rj  xL
  pVe*   V! V4      pVP                  V4      '       d   VG Rj  xL
  \
        P                  P                  VP                  4      G Rj  xL
  \
        P                  P                  \        WWV4      G Rj  xL
 pV^,          pK   L L L Lt LE LD\
        P                  P                  TP                  4      G Rj  xL 
  T# 5i)a  
Async equivalent of [`run_process`][watchfiles.run_process], all arguments match those of `run_process` except
`callback` which can be a coroutine.

Starting and stopping the process and watching for changes is done in a separate thread.

As with `run_process`, internally `arun_process` uses [`awatch`][watchfiles.awatch], however `KeyboardInterrupt`
cannot be caught and suppressed in `awatch` so these errors need to be caught separately, see below.

```py title="Example of arun_process usage"
import asyncio
from watchfiles import arun_process

async def callback(changes):
    await asyncio.sleep(0.1)
    print('changes detected:', changes)

def foobar(a, b):
    print('foobar called with:', a, b)

async def main():
    await arun_process('.', target=foobar, args=(1, 2), callback=callback)

if __name__ == '__main__':
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print('stopped via KeyboardInterrupt')
```
Nr   r6   r7   r   r   r    r!   r$   r%   )inspectr9   r:   r!   r;   anyio	to_threadrun_syncr<   r   r   isawaitabler=   )r)   r   r   r   r   r   r   r   r    r!   r$   r%   r(   rD   r>   r?   r@   rs   $$$$$$$$$$$$*     r2   arun_processrJ      sx    Z f(0
LL%v;OOO,,]FQU^^GGJLYkk,'''	!  	
   ":  g !A""1%%oo&&w||44400UYcjkk1/ _
 	( 4k" //
"
"7<<
000Ns   AF!E"F0/FE F9E&=E>E&$F&F+E ,0FE"-F
E$FFE& F"F$F&-FFFspawnc                F    V ^8  d   QhR\         R\        \         ,          /# )r'   cmdr+   )r-   r   )r1   s   "r2   r3   r3      s     ) )3 )49 )r4   c                     ^ RI pVP                  4       P                  P                  4       R8g  p\        P
                  ! WR7      # )r   Nwindows)posix)platformunamesystemlowershlexsplit)rM   rQ   rP   s   &  r2   	split_cmdrW      s4    NN##))+y8E;;s((r4   c                
   V ^8  d   QhR\         \        \        R\        3,          3,          RRR\        \        R3,          R\
        \        \        \        3,          ,          R\
        \        \        ,          ,          RR	/# )
r'   r)   .r   Literal['function', 'command']r   r   r@   r+   CombinedProcess)	r   r-   r
   r	   r   r   r   r   r   )r1   s   "r2   r3   r3      su     !$ !$#xS))*!$1!$ S/!$ T#s(^$	!$
 c*o&!$ !$r4   c                 d   Vf   RpM:\         P                  ! V UUu. uF  w  rgVP                  4       V.NK  	  upp4      pV\        P                  R&   VR8X  dc   T;'       g    / p\        V \        4      '       d   V \        4       W#3p\        p/ pMT p\        P                  WVR7      p	V	P                  4        McV'       g	   V'       d   \        P                  R4       \        V \        4      '       g   Q R4       h\        V 4      p
\        P                   ! V
4      p	\#        V	4      # u uppi )Nz[]WATCHFILES_CHANGESfunction)r)   r   r   z-ignoring args and kwargs for "command" targetz+target must be a string to run as a command)jsondumpsraw_strosenviron
isinstancer-   get_tty_pathrun_functionspawn_contextProcessstartr:   warningrW   
subprocessPopenrZ   )r)   r   r   r   r@   changes_env_varcptarget_r>   
popen_argss   &&&&&      r2   r<   r<      s     **7%K741qyy{A&67%KL'6BJJ#$ j 2fc""<>47D"GFG''w&'Q6NNJK&#&&U(UU&v&
"":.7##/ &Ls   D,
c                d    V ^8  d   QhR\         \        \        R\        3,          3,          RR/# )r'   r)   .r+   rY   )r   r-   r
   r	   )r1   s   "r2   r3   r3     s.      uS(38*<%<= Bb r4   c                    \        V \        4      '       g   R# V P                  R4      '       d   R# \        P                  ! RV 4      '       d   R# R# )a&  
Used by [`run_process`][watchfiles.run_process], [`arun_process`][watchfiles.arun_process]
and indirectly the CLI to determine the target type with `target_type` is `auto`.

Detects the target type - either `function` or `command`. This method is only called with `target_type='auto'`.

The following logic is employed:

* If `target` is not a string, it is assumed to be a function
* If `target` ends with `.py` or `.sh`, it is assumed to be a command
* Otherwise, the target is assumed to be a function if it matches the regex `[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)+`

If this logic does not work for you, specify the target type explicitly using the `target_type` function argument
or `--target-type` command line argument.

Args:
    target: The target value

Returns:
    either `'function'` or `'command'`
r]   commandz[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)+)z.pyz.sh)rc   r-   endswithre	fullmatch)r)   s   &r2   r9   r9     s>    , fc""		(	(	8&	A	Ar4   c                      a  ] tR tRt o V 3R lR ltRV 3R lR lltV 3R lR lt]V 3R lR	 l4       tV 3R
 lR lt	]V 3R lR l4       t
RtV tR# )rZ   i=  c                   < V ^8  d   QhRR/# )r'   rn   z,Union[SpawnProcess, subprocess.Popen[bytes]] )r1   __classdict__s   "r2   r3   CombinedProcess.__annotate__>  s     ? ?H ?r4   c                <    Wn         V P                  f   Q R4       hR # )Nzprocess not yet spawned_ppid)selfrn   s   &&r2   __init__CombinedProcess.__init__>  s    xx#>%>>#r4   c                *   < V ^8  d   QhRS[ RS[ RR/# )r'   r"   r#   r+   Nr0   )r1   rz   s   "r2   r3   r{   B  s'     Q Q3 QS Q Qr4   c                   \         P                  P                  R R4       V P                  4       '       d   \        P                  R4       \         P                  ! V P                  \        P                  4        V P                  V4       V P                  fX   \        P                  R4       \         P                  ! V P                  \        P                  4       V P                  V4       R# \        P                  R4       R# \        P                  RV P                  4       R#   \        P                   d    \        P                  RT4        Li ; i)r\   Nzstopping process...z!SIGINT timed out after %r secondsz+process has not terminated, sending SIGKILLzprocess stoppedz#process already dead, exit code: %d)ra   rb   popis_aliver:   r!   killr   signalSIGINTjoinrj   TimeoutExpiredri   exitcodeSIGKILL)r   r"   r#   s   &&&r2   r=   CombinedProcess.stopB  s    


+T2==??LL./GGDHHfmm,		.) }}$LM&..1		/*./NN@$--P ,,  BNS	s   <D+ ++EEc                    < V ^8  d   QhRS[ /# r'   r+   )r.   )r1   rz   s   "r2   r3   r{   Z  s     * *$ *r4   c                    \        V P                  \        4      '       d   V P                  P                  4       # V P                  P	                  4       R J # N)rc   r~   r   r   pollr   s   &r2   r   CombinedProcess.is_aliveZ  s;    dgg|,,77##%%77<<>T))r4   c                    < V ^8  d   QhRS[ /# r   r   )r1   rz   s   "r2   r3   r{   a  s      S r4   c                .    V P                   P                  # r   r}   r   s   &r2   r   CombinedProcess.pid`  s     ww{{r4   c                $   < V ^8  d   QhRS[ RR/# )r'   timeoutr+   Nr   )r1   rz   s   "r2   r3   r{   e  s     " "C "D "r4   c                    \        V P                  \        4      '       d   V P                  P                  V4       R # V P                  P	                  V4       R # r   )rc   r~   r   r   wait)r   r   s   &&r2   r   CombinedProcess.joine  s3    dgg|,,GGLL!GGLL!r4   c                0   < V ^8  d   QhRS[ S[,          /# r   )r   r0   )r1   rz   s   "r2   r3   r{   l  s     & &(3- &r4   c                    \        V P                  \        4      '       d   V P                  P                  # V P                  P                  # r   )rc   r~   r   r   
returncoder   s   &r2   r   CombinedProcess.exitcodek  s3    dgg|,,77###77%%%r4   )r~   N)      )__name__
__module____qualname____firstlineno__r   r=   r   propertyr   r   r   __static_attributes____classdictcell__)rz   s   @r2   rZ   rZ   =  sW     ? ?Q Q0* *  " " & &r4   rZ   c          
          V ^8  d   QhR\         R\        \         ,          R\        \        R3,          R\        \         \        3,          RR/# )r'   r]   tty_pathr   .r   r+   N)r-   r   r   r	   r   )r1   s   "r2   r3   r3   s  sI      3 (3- uS#X X\]`be]eXf ko r4   c                     \        V4      ;_uu_ 4        \        V 4      pV! V/ VB  R R R 4       R #   + '       g   i     R # ; ir   )set_ttyimport_string)r]   r   r   r   funcs   &&&& r2   re   re   s  s3    			X&df 
			s	   2A	c                0    V ^8  d   QhR\         R\        /# )r'   dotted_pathr+   )r-   r	   )r1   s   "r2   r3   r3   y  s     g gs gs gr4   c                
    V P                  R4      P                  R^4      w  r\	        T4      p \        YB4      #   \         d   p\        RT  R24      ThRp?ii ; i  \         d   p\        RT RT R24      ThRp?ii ; i)	z
Stolen approximately from django. Import a dotted module path and return the attribute/class designated by the
last name in the path. Raise ImportError if the import fails.
 ."z!" doesn't look like a module pathNzModule "z" does not define a "z" attribute)striprsplit
ValueErrorImportErrorr   getattrAttributeError)r   module_path
class_nameemodules   &    r2   r   r   y  s    
V"-"3"3C"8"?"?Q"G ;'Fgv**  VAk]*LMNTUUV  gH[M1FzlR]^_effgs,   #< 
A AAAB*A==Bc                :    V ^8  d   QhR\         \        ,          /# r   )r   r-   )r1   s   "r2   r3   r3     s      hsm r4   c                      \         P                  ! \        P                  P	                  4       4      #   \
         d     R# \         d     R# i ; i)zf
Return the path to the current TTY, if any.

Virtually impossible to test in pytest, hence no cover.
z/dev/ttyN)ra   ttynamesysstdinfilenoOSErrorr   ry   r4   r2   rd   rd     s@    zz#))**,--  s   14 AAAAc                T    V ^8  d   QhR\         \        ,          R\        R,          /# )r'   r   r+   )NNN)r   r-   r   )r1   s   "r2   r3   r3     s$      hsm 	2B(C r4   c              #      "   V '       d/    \        V 4      ;_uu_ 4       pV\        n        R x  R R R 4       R # R x  R #   + '       g   i     R # ; i  \         d	    R x   R # i ; i5ir   )openr   r   r   )r   ttys   & r2   r   r     sJ     	h3	   	    		sG   	A)A ?A A)A	
A A)A A&"A)%A&&A)c                4    V ^8  d   QhR\         R\        RR/# )r'   signum_framer+   N)r0   r	   )r1   s   "r2   r3   r3     s!      S # $ r4   c                 b    \         P                  R \        P                  ! V 4      4       \        h)z-received signal %s, raising KeyboardInterrupt)r:   ri   r   SignalsKeyboardInterrupt)r   r   s   &&r2   raise_keyboard_interruptr     s!    
NNBFNNSYDZ[
r4   c                    V ^8  d   QhRR/# )r'   r+   Nry   )r1   s   "r2   r3   r3     s     < <t <r4   c                     \         P                  R\        P                  ! 4       4       \        P                  ! \        P
                  \        4       R# )a  
Catch SIGTERM and raise KeyboardInterrupt instead. This means watchfiles will stop quickly
on `docker compose stop` and other cases where SIGTERM is sent.

Without this the watchfiles process will be killed while a running process will continue uninterrupted.
z8registering handler for SIGTERM on watchfiles process %dN)r:   r!   ra   getpidr   SIGTERMr   ry   r4   r2   r;   r;     s,     LLKRYY[Y
MM&..":;r4   )rA   rJ   r9   r   ry   r   )8
contextlibr^   loggingra   ru   rU   r   rj   r   	importlibr   multiprocessingr   multiprocessing.contextr   pathlibr   timer   typingr   r	   r
   r   r   r   r   r   r   r   rE   filtersr   mainr   r   r   r   r   __all__	getLoggerr:   rA   rJ   rf   rW   r<   r9   rZ   re   r   rd   contextmanagerr   r   r;   ry   r4   r2   <module>r      s      	 	    
 # ' 0   c c c  " 3 3
N			,	-} } (,	}
 =C} =A} =JO} } } } !} } } } &+}@M M (,	M
 =CM <@M =JOM M M M !M M &+Md G$)!$H@3& 3&lg"   
<r4   