Ë
    Ûqjô;  ã            !       ó.  — 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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lmZmZmZmZmZmZmZmZmZmZ d dlZdd	lm Z  dd
l!m"Z"m#Z#m$Z$m%Z% erd dlm&Z& dZ' ejP                  d«      Z)dddd e «       d ddddddddœdeee*f   dee*edef   f   deedf   deee*ef      dddeeee#   gdf      deee"e*ge+f      de,d e-d!e-d"ee+   d#e-d$e-d%e+d&e+d'e-f d(„Z.dddd e «       d dddddd)œdeee*f   dee*edef   f   deedf   deee*ef      dddeeee#   gef      deee"e*ge+f      de,d e-d!e-d"ee+   d%e+d&e+d'e-fd*„Z/ ed+«      Z0d,e*d'ee*   fd-„Z1	 d@dee*edef   f   dd.deedf   deee*ef      d/eee#      d'd0fd1„Z2dee*edef   f   d'd.fd2„Z3 G d3„ d0«      Z4d4e*d5ee*   deedf   dee*ef   d'df
d6„Z5d7e*d'efd8„Z6d'ee*   fd9„Z7e jp                  d5ee*   d'ed:   fd;„«       Z9d<e-d=ed'dfd>„Z:dAd?„Z;y)Bé    N)Úimport_module)Úget_context)ÚSpawnProcess)ÚPath)Úsleep)
ÚTYPE_CHECKINGÚAnyÚCallableÚDictÚ	GeneratorÚListÚOptionalÚSetÚTupleÚUnioné   )ÚDefaultFilter)ÚChangeÚ
FileChangeÚawatchÚwatch)ÚLiteral)Úrun_processÚarun_processÚdetect_target_typeÚimport_stringzwatchfiles.main© Úautoi@  é2   é   TF)ÚargsÚkwargsÚtarget_typeÚcallbackÚwatch_filterÚgrace_periodÚdebounceÚstepÚdebugÚsigint_timeoutÚsigkill_timeoutÚ	recursiveÚignore_permission_deniedÚpathsÚtarget.r!   r"   r#   z&Literal['function', 'command', 'auto']r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   Úreturnc                 ó®  — |dk(  rt        | «      }t        j                  d| |«       t        «        t	        | |||«      }d}|r!t        j                  d|«       t        |«       	 t        |||||	d||dœŽD ]5  }|xr  ||«       |j                  |
|¬«       t	        | ||||«      }|dz  }Œ7 	 |j                  «        |S # |j                  «        w xY w)	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 %sr   ú3sleeping for %s seconds before watching for changesF)r%   r'   r(   r)   Úraise_interruptr,   r-   )r*   r+   r   )r   Ú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                     úO/var/www/html/kelly-backend/venv/lib/python3.12/site-packages/watchfiles/run.pyr   r      sà   € ð@ �fÒÜ(¨Ó0ˆä
‡L�LÐ% v¨{Ô;Ü„OÜ˜F K°°vÓ>€GØ€GáÜ�‰ÐJÈLÔYÜˆlÔðÜØØ%ØØØØ!ØØ%=õ	
ˆGð Ò*™ 'Ó*øØ�L‰L¨ÈˆLÔXÜ# F¨K¸¸vÀwÓOˆGØ�q‰L‰Gñ	
ð 	�‰ŒØ€Nøð 	�‰�ús   Á&A	C ÃC)r!   r"   r#   r$   r%   r&   r'   r(   r)   r,   r-   c           
   ‡   ó  K  — ddl }|dk(  rt        | «      }t        j                  d| |«       t	        «        t
        j                  j                  t        | |||«      ƒ d{  –—† }d}|r3t        j                  d|«       t        j                  |«      ƒ d{  –—†  t        |||||	|
|dœŽ2 3 d{  –—† }|�# ||«      }|j                  |«      r
|ƒ d{  –—†  t
        j                  j                  |j                  «      ƒ d{  –—†  t
        j                  j                  t        | ||||«      ƒ d{  –—† }|dz  }Œ•7 Œà7 Œ«7 Œ”7 Œq7 ŒB7 Œ6 t
        j                  j                  |j                  «      ƒ d{  –—†7   |S ­w)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')
    ```
    r   Nr   r2   r3   )r%   r'   r(   r)   r,   r-   r   )Úinspectr   r5   r)   r6   ÚanyioÚ	to_threadÚrun_syncr7   r   r   Úisawaitabler8   )r/   r!   r"   r#   r$   r%   r&   r'   r(   r)   r,   r-   r.   r>   r9   r:   r;   Úrs                     r<   r   r   �   s[  è ø€ óZ à�fÒÜ(¨Ó0ˆä
‡L�LÐ% v¨{Ô;Ü„OÜ—O‘O×,Ñ,¬]¸FÀKÐQUÐW]Ó^×^€GØ€GáÜ�‰ÐJÈLÔYÜ�k‰k˜,Ó'×'Ð'äØ	Ø!ØØØØØ!9ó÷ ˆgð ÐÙ˜Ó!ˆAØ×"Ñ" 1Ô%Ø—�ä�o‰o×&Ñ& w§|¡|Ó4×4Ð4ÜŸ™×0Ñ0´ÀÈÐUYÐ[aÐcjÓk×kˆØ�1‰‰ð/ _øð
 	(øðøð øà4øØkøðô" �/‰/×
"Ñ
" 7§<¡<Ó
0×0Ñ0Ø€NùsŠ   ‚A FÁ"EÁ#6FÂEÂFÂ.EÂ2EÂ3EÂ6!FÃE	Ã0FÄEÄ	/FÄ8EÄ9FÅFÅEÅ	FÅFÅFÅ-FÅ<E?Å=FÚspawnÚcmdc                 óŽ   — dd l }|j                  «       j                  j                  «       dk7  }t	        j
                  | |¬«      S )Nr   Úwindows)Úposix)ÚplatformÚunameÚsystemÚlowerÚshlexÚsplit)rE   rI   rH   s      r<   Ú	split_cmdrO   ò   s6   € Ûà�N‰NÓ×#Ñ#×)Ñ)Ó+¨yÑ8€EÜ�;‰;�s %Ô(Ð(ó    zLiteral['function', 'command']r;   ÚCombinedProcessc                 ó2  — |€d}n8t        j                  |D ��cg c]  \  }}|j                  «       |g‘Œ c}}«      }|t        j                  d<   |dk(  rb|xs i }t        | t        «      r| t        «       ||f}t        }i }n| }t        j                  |||¬«      }	|	j                  «        t#        |	«      S |s|rt        j                  d«       t        | t        «      sJ d«       ‚t        | «      }
t        j                   |
«      }	t#        |	«      S c c}}w )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Ú
isinstanceÚstrÚget_tty_pathÚrun_functionÚspawn_contextÚProcessÚstartr5   ÚwarningrO   Ú
subprocessÚPopenrQ   )r/   r#   r!   r"   r;   Úchanges_env_varÚcÚpÚtarget_r9   Ú
popen_argss              r<   r7   r7   ù   s  € ð €Ø‰äŸ*™*Á7Ô%KÁ7¹4¸1¸a q§y¡y£{°AÒ&6À7Ò%KÓLˆà'6„B‡J�JÐ#Ñ$ð �jÒ Ø’˜2ˆÜ�fœcÔ"Øœ<›>¨4°Ð7ˆDÜ"ˆGØ‰FàˆGä×'Ñ'¨w¸TÈ&Ð'ÓQˆØ�‰Œô ˜7Ó#Ð#ñ ‘6Ü�N‰NÐJÔKä˜&¤#Ô&ÐUÐ(UÓUÐ&Ü˜vÓ&ˆ
Ü×"Ñ" :Ó.ˆÜ˜7Ó#Ð#ùó/ &Ls   šD
c                 óx   — t        | t        «      sy| j                  d«      ryt        j                  d| «      ryy)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'`
    rT   )z.pyz.shÚcommandz[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)+)rZ   r[   ÚendswithÚreÚ	fullmatch)r/   s    r<   r   r     s5   € ô, �fœcÔ"ØØ	�‰˜Ô	(ØÜ	�‰Ð8¸&Ô	AØàrP   c                   óx   — e Zd Zdd„Zddededdfd„Zdefd„Zedefd„«       Z	d	eddfd
„Z
edee   fd„«       Zy)rQ   c                 ó8   — || _         | j                  €J d«       ‚y )Nzprocess not yet spawned©Ú_pÚpid)Úselfrf   s     r<   Ú__init__zCombinedProcess.__init__>  s   € ØˆŒØ�x‰xÐ#Ð>Ð%>Ó>Ñ#rP   r*   r+   r0   Nc                 óš  — t         j                  j                  dd «       | j                  «       rÌt        j                  d«       t        j                  | j                  t        j                  «       	 | j                  |«       | j                  €Ut        j                  d«       t        j                  | j                  t        j                  «       | j                  |«       y t        j                  d«       y t        j                  d| j                  «       y # t        j                  $ r t        j                  d|«       Y ŒÃw xY w)NrS   zstopping process...z!SIGINT timed out after %r secondsz+process has not terminated, sending SIGKILLzprocess stoppedz#process already dead, exit code: %d)rX   rY   ÚpopÚis_aliver5   r)   Úkillrr   ÚsignalÚSIGINTÚjoinrb   ÚTimeoutExpiredra   ÚexitcodeÚSIGKILL)rs   r*   r+   s      r<   r8   zCombinedProcess.stopB  sØ   € Ü
�
‰
�‰Ð+¨TÔ2Ø�=‰=Œ?Ü�L‰LÐ.Ô/ä�G‰G�D—H‘HœfŸm™mÔ,ðØ—	‘	˜.Ô)ð �}‰}Ð$Ü—‘ÐLÔMÜ—‘˜Ÿ™¤&§.¡.Ô1Ø—	‘	˜/Õ*ä—‘Ð.Õ/ä�N‰NÐ@À$Ç-Á-ÕPøô ×,Ñ,ò ô —‘ÐBÀNÔSÙð	ús   Á5D Ä)E
Å	E
c                 ó¢   — t        | j                  t        «      r| j                  j                  «       S | j                  j	                  «       d u S ©N)rZ   rq   r   rw   Úpoll©rs   s    r<   rw   zCombinedProcess.is_aliveZ  s8   € Ü�d—g‘gœ|Ô,Ø—7‘7×#Ñ#Ó%Ð%à—7‘7—<‘<“> TÐ)Ð)rP   c                 ó.   — | j                   j                  S r€   rp   r‚   s    r<   rr   zCombinedProcess.pid`  s   € ð �w‰w�{‰{ÐrP   Útimeoutc                 ó¦   — t        | j                  t        «      r| j                  j                  |«       y | j                  j	                  |«       y r€   )rZ   rq   r   r{   Úwait)rs   r„   s     r<   r{   zCombinedProcess.joine  s0   € Ü�d—g‘gœ|Ô,Ø�G‰G�L‰L˜Õ!à�G‰G�L‰L˜Õ!rP   c                 óŽ   — t        | j                  t        «      r| j                  j                  S | j                  j                  S r€   )rZ   rq   r   r}   Ú
returncoder‚   s    r<   r}   zCombinedProcess.exitcodek  s0   € ä�d—g‘gœ|Ô,Ø—7‘7×#Ñ#Ð#à—7‘7×%Ñ%Ð%rP   )rf   z,Union[SpawnProcess, subprocess.Popen[bytes]])r    r   )Ú__name__Ú
__module__Ú__qualname__rt   Úintr8   Úboolrw   Úpropertyrr   r{   r   r}   r   rP   r<   rQ   rQ   =  s~   „ ó?ñQ 3ð Q¸Sð QÈó Qð0*˜$ó *ð ð�Sò ó ðð"˜Cð " Dó "ð ð&˜( 3™-ò &ó ñ&rP   rT   Útty_pathc                 ój   — t        |«      5  t        | «      } ||i |¤Ž d d d «       y # 1 sw Y   y xY wr€   )Úset_ttyr   )rT   r�   r!   r"   Úfuncs        r<   r]   r]   s  s-   € Ü	�Õ	Ü˜XÓ&ˆÙˆdÐ�fÒ÷ 
×	Ñ	ús   Œ)©2Údotted_pathc                 ó  — 	 | j                  d«      j                  dd«      \  }}t	        |«      }	 t        ||«      S # t        $ r}t        d| › d�«      |‚d}~ww xY w# t        $ r}t        d|› d|› d	�«      |‚d}~ww xY w)
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.
    Ú Ú.r   Ú"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        r<   r   r   y  s§   € ð
VØ"-×"3Ñ"3°CÓ"8×"?Ñ"?ÀÀQÓ"GÑˆ�Zô ˜;Ó'€FðgÜ�v˜zÓ*Ð*øô ò VÜ˜A˜k˜]Ð*LÐMÓNÐTUÐUûðVûô ò gÜ˜H [ MÐ1FÀzÀlÐR]Ð^Ó_ÐefÐfûðgús,   ‚$> ²A ¾	AÁAÁAÁ	B Á(A;Á;B c                  ó˜   — 	 t        j                  t        j                  j	                  «       «      S # t
        $ r Y yt        $ r Y yw xY w)zr
    Return the path to the current TTY, if any.

    Virtually impossible to test in pytest, hence no cover.
    z/dev/ttyN)rX   ÚttynameÚsysÚstdinÚfilenoÚOSErrorr�   r   rP   r<   r\   r\   Š  s@   € ðÜ�z‰zœ#Ÿ)™)×*Ñ*Ó,Ó-Ð-øÜò áÜò áðús   ‚03 ³	A	¾A	ÁA	)NNNc              #   ó¢   K  — | r&	 t        | «      5 }|t        _        d –— d d d «       y y d –— y # 1 sw Y   ŒxY w# t        $ r d –— Y y w xY w­wr€   )Úopenr¤   r¥   r§   )r�   Úttys     r<   r‘   r‘   š  sG   è ø€ áð	Ü�h” 3Ø””	Û÷  ‘ô 	÷  �ûô ò 	åð	üs5   ‚A†< ‘0¡< ©A°9µ< ¼AÁ	AÁAÁAÚsignumÚ_framec                 ó`   — t         j                  dt        j                  | «      «       t        ‚)Nz-received signal %s, raising KeyboardInterrupt)r5   ra   ry   ÚSignalsÚKeyboardInterrupt)r«   r¬   s     r<   Úraise_keyboard_interruptr°   ©  s!   € Ü
‡N�NÐBÄFÇNÁNÐSYÓDZÔ[Ü
ÐrP   c                  ó¤   — t         j                  dt        j                  «       «       t	        j                  t        j
                  t        «       y)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)r5   r)   rX   Úgetpidry   ÚSIGTERMr°   r   rP   r<   r6   r6   ®  s,   € ô ‡L�LÐKÌRÏYÉYË[ÔYÜ
‡M�M”&—.‘.Ô":Õ;rP   r€   )r0   N)<Ú
contextlibrU   ÚloggingrX   rl   rM   ry   rb   r¤   Ú	importlibr   Úmultiprocessingr   Úmultiprocessing.contextr   Úpathlibr   Útimer   Útypingr   r	   r
   r   r   r   r   r   r   r   r?   Úfiltersr   Úmainr   r   r   r   r   Ú__all__Ú	getLoggerr5   r[   r�   ÚfloatrŒ   r   r   r^   rO   r7   r   rQ   r]   r   r\   Úcontextmanagerr‘   r°   r6   r   rP   r<   Ú<module>rÂ      sA  ðÛ Û Û Û 	Û 	Û Û Û Û 
Ý #Ý 'Ý 0Ý Ý ß c× c× cã å "ß 3Ó 3áÝà
N€Ø	ˆ×	Ñ	Ð,Ó	-€ð Ø'+Ø<BØ<@Ù<I»OØØØØ ØØØØ%*ò}Ø�$˜�)Ñð}à�#�x  S Ñ)Ð)Ñ*ð}ð ��S�‰/ð}ð �T˜#˜s˜(‘^Ñ$ð	}ð
 :ð}ð �x  Z¡Ð 1°4Ð 7Ñ8Ñ9ð}ð ˜8 V¨S M°4Ð$7Ñ8Ñ9ð}ð ð}ð ð}ð ð}ð �D‰>ð}ð ð}ð ð}ð ð}ð #ð}ð  	ó!}ðF Ø'+Ø<BØ;?Ù<I»OØØØØ ØØ%*òMØ�$˜�)ÑðMà�#�x  S Ñ)Ð)Ñ*ðMð ��S�‰/ðMð �T˜#˜s˜(‘^Ñ$ð	Mð
 :ðMð �x  Z¡Ð 1°3Ð 6Ñ7Ñ8ðMð ˜8 V¨S M°4Ð$7Ñ8Ñ9ðMð ðMð ðMð ðMð �D‰>ðMð ðMð #ðMð 	óMñd ˜GÓ$€ð)�3ð )˜4 ™9ó )ð *.ñ!$Ø�#�x  S Ñ)Ð)Ñ*ð!$à1ð!$ð ��S�‰/ð!$ð �T˜#˜s˜(‘^Ñ$ð	!$ð
 �c˜*‘oÑ&ð!$ð ó!$ðH˜u S¨(°3¸°8Ñ*<Ð%<Ñ=ð ÐBbó ÷@3&ñ 3&ðl˜3ð ¨(°3©-ð ¸uÀSÈ#ÀX¹ð ÐX\Ð]`ÐbeÐ]eÑXfð Ðkoó ðg˜sð g só gð"�h˜s‘mó ð  ×Ñð�h˜s‘mð ¨	Ð2BÑ(Cò ó ðð Sð °#ð ¸$ó ô
<rP   