
    xiQ&                       S SK Jr  S SKrS SKrS SKrS SKrS SKrS SKrS SKrS SK	r	S SK
r
S SKrS SKrS SKrS SKJr  \R"                  S:  a  S SKJr  OS SKr\R(                  SS j5       r\R(                   S   SS jj5       rS r    SS	 jr\" \R2                  \5      rS
 r\" \\5      r S rS r\R(                  \R>                  4S j5       r \RB                  " \ \" 5       S9r"\R(                  SS\"4   SS jj5       r# " S S5      r$ " S S\RJ                  \RL                  5      r% " S S\RL                  5      r'g)    )annotationsN)Iterator)      )tarfilec              #     #    [         R                  " 5       n[         R                  " U 5         U v   [         R                  " U5        g! [         R                  " U5        f = f7f)z
>>> tmp_path = getfixture('tmp_path')
>>> with pushd(tmp_path):
...     assert os.getcwd() == os.fspath(tmp_path)
>>> assert os.getcwd() != os.fspath(tmp_path)
N)osgetcwdchdir)dirorigs     7lib/python3.13/site-packages/jaraco/context/__init__.pypushdr      s=      99;DHHSM	
s   ,A%A
 A%
A""A%c              #    #    Uc?  [         R                  R                  U 5      R                  SS5      R                  SS5      n[         R                  " U5         [
        R                  R                  U 5      n[        R                  " USS9 nUR                  U[        S9  SSS5        Uv   [        R                  " U5        g! , (       d  f       N)= f! [        R                  " U5        f = f7f)a  
Get a URL to a tarball, download, extract, yield, then clean up.

Assumes everything in the tarball is prefixed with a common
directory. That common path is stripped and the contents
are extracted to ``target_dir``, similar to passing
``-C {target} --strip-components 1`` to the ``tar`` command.

Uses the streaming protocol to extract the contents from a
stream in a single pass without loading the whole file into
memory.

>>> import urllib.request
>>> url = getfixture('tarfile_served')
>>> target = getfixture('tmp_path') / 'out'
>>> tb = tarball(url, target_dir=target)
>>> import pathlib
>>> with tb as extracted:
...     contents = pathlib.Path(extracted, 'contents.txt').read_text(encoding='utf-8')
>>> assert not os.path.exists(extracted)

If the target is not specified, contents are extracted to a
directory relative to the current working directory named after
the name of the file as extracted from the URL.

>>> target = getfixture('tmp_path')
>>> with pushd(target), tarball(url):
...     target.joinpath('served').is_dir()
True
Nz.tar.gz z.tgzzr|*)fileobjmode)pathfilter)r	   r   basenamereplacemkdirurllibrequesturlopenr   open
extractall_default_filtershutilrmtree)url
target_dirreqtfs       r   tarballr%   (   s     D WW%%c*229bAII&RTU
HHZ"nn$$S)\\#E2bMMz/MB 3j!	 32 	j!s6   AC44C C%C 1C4
CC C11C4c                 8    S n[         R                  " XS 5      $ )Nc                   ^ ^ U U4S j$ )Nc                "   > T" T" X5      U5      $ N )memberr   f1f2s     r   <lambda>?_compose_tarfile_filters.<locals>.compose_two.<locals>.<lambda>X   s    Br&'7$>    r*   )r,   r-   s   ``r   compose_two-_compose_tarfile_filters.<locals>.compose_twoW   s	    >>r0   c                    U $ r)   r*   )r+   r   s     r   r.   *_compose_tarfile_filters.<locals>.<lambda>Z   s    vr0   )	functoolsreduce)filtersr1   s     r   _compose_tarfile_filtersr8   V   s    ? K2MNNr0   c                L    U R                   R                  SS5      u  o l         U $ )N/   )namesplit)r+   r   _s      r   strip_first_componentr?   ]   s#     [[&&sA.NA{Mr0   c                 H    S n[         R                  " U[        U 5      5      $ )aQ  
Compose any number of dependent context managers into a single one.

The last, innermost context manager may take arbitrary arguments, but
each successive context manager should accept the result from the
previous as a single parameter.

Like :func:`jaraco.functools.compose`, behavior works from right to
left, so the context manager should be indicated from outermost to
innermost.

Example, to create a context manager to change to a temporary
directory:

>>> temp_dir_as_cwd = _compose(pushd, temp_dir)
>>> with temp_dir_as_cwd() as dir:
...     assert os.path.samefile(os.getcwd(), dir)
c                @   ^ ^ U U4S jn[         R                  " U5      $ )Nc               ?     >#    T" U 0 UD6 nT" U5       nUv   S S S 5        S S S 5        g ! , (       d  f       N= f! , (       d  f       g = f7fr)   r*   )argskwargssavedresinnerouters       r   composed/_compose.<locals>.compose_two.<locals>.composed}   s8     ''5%,#	 3?'',,''s)   	A	<+<	A
9	<
A
A)
contextlibcontextmanager)rG   rH   rI   s   `` r   r1   _compose.<locals>.compose_two|   s    	 ((22r0   )r5   r6   reversed)cmgrsr1   s     r   _composerP   h   s     (3 K%99r0   c                P   Uu  p4nU [         R                  [         R                  [         R                  4;   an  UR                  [        R
                  :X  aP  [         R                  " U[        R                  [        R                  -  [        R                  -  5        U " U5        ge )z6
Add support for removing read-only files on Windows.
N)r	   rmdirremoveunlinkerrnoEACCESchmodstatS_IRWXUS_IRWXGS_IRWXO)funcr   exc_infor>   excs        r   remove_readonlyr_      se     IAA"))RYY//CII4M
t||dll2T\\ABT
r0   c                     [         R                  " 5       S:X  a'  [        R                  " [        R
                  [        S9$ [        R
                  $ )NWindows)onerror)platformsystemr5   partialr   r    r_   r*   r0   r   robust_removerrf      s<     ??	) 	&--A ]]r0   c              #  j   #    [         R                  " 5       n Uv   U " U5        g! U " U5        f = f7f)z
Create a temporary directory context. Pass a custom remover
to override the removal behavior.

>>> import pathlib
>>> with temp_dir() as the_dir:
...     assert os.path.isdir(the_dir)
>>> assert not os.path.exists(the_dir)
N)tempfilemkdtemp)removertemp_dirs     r   rk   rk      s/      !Hs   3& 	3
03)rj   Tc              #    #    SU ;   a  SOSnU" 5        nUSX/nUR                  SU/[        U5      -  5        U(       a  [        R                  OSn[        R                  " XgUS9  Uv   SSS5        g! , (       d  f       g= f7f)an  
Check out the repo indicated by url.

If dest_ctx is supplied, it should be a context manager
to yield the target directory for the check out.

>>> getfixture('ensure_git')
>>> getfixture('needs_internet')
>>> repo = repo_context('https://github.com/jaraco/jaraco.context')
>>> with repo as dest:
...     listing = os.listdir(dest)
>>> 'README.rst' in listing
True
githgclonez--branchN)stdoutstderr)extendbool
subprocessDEVNULL
check_call)r!   branchquietdest_ctxexerepo_dircmdstreams           r   repo_contextr~      sn     $ C<%TC	xGS+

J'$v,67',##$c@ 
s   BAA4+	B4
B>Bc                      \ rS rSrSrSr\44S jrS r\	S 5       r
\	S 5       r\	S 5       rS	 rS
 r\S.S jrS rSrg)ExceptionTrap   aA  
A context manager that will catch certain exceptions and provide an
indication they occurred.

>>> with ExceptionTrap() as trap:
...     raise Exception()
>>> bool(trap)
True

>>> with ExceptionTrap() as trap:
...     pass
>>> bool(trap)
False

>>> with ExceptionTrap(ValueError) as trap:
...     raise ValueError("1 + 1 is not 3")
>>> bool(trap)
True
>>> trap.value
ValueError('1 + 1 is not 3')
>>> trap.tb
<traceback object at ...>

>>> with ExceptionTrap(ValueError) as trap:
...     raise Exception()
Traceback (most recent call last):
...
Exception

>>> bool(trap)
False
)NNNc                    Xl         g r)   )
exceptions)selfr   s     r   __init__ExceptionTrap.__init__   s    $r0   c                    U $ r)   r*   r   s    r   	__enter__ExceptionTrap.__enter__       r0   c                     U R                   S   $ Nr   r]   r   s    r   typeExceptionTrap.type       }}Qr0   c                     U R                   S   $ )Nr;   r   r   s    r   valueExceptionTrap.value   r   r0   c                     U R                   S   $ )N   r   r   s    r   tbExceptionTrap.tb  r   r0   c                f    US   nU=(       a    [        X R                  5      nU(       a  Xl        U$ r   )
issubclassr   r]   )r   r]   r   matchess       r   __exit__ExceptionTrap.__exit__  s+    {<:dOO<$Mr0   c                ,    [        U R                  5      $ r)   )rs   r   r   s    r   __bool__ExceptionTrap.__bool__  s    DIIr0   _testc               N   ^ ^^ [         R                  " T5      UUU 4S j5       nU$ )aQ  
Wrap func and replace the result with the truth
value of the trap (True if an exception occurred).

First, give the decorator an alias to support Python 3.8
Syntax.

>>> raises = ExceptionTrap(ValueError).raises

Now decorate a function that always fails.

>>> @raises
... def fail():
...     raise ValueError('failed')
>>> fail()
True
c                    > [        TR                  5       nT" U 0 UD6  S S S 5        T" W5      $ ! , (       d  f       N= fr)   )r   r   )rC   rD   trapr   r\   r   s      r   wrapper%ExceptionTrap.raises.<locals>.wrapper%  s6    t/4d%f% 0; 0/s   	0
>)r5   wraps)r   r\   r   r   s   ``` r   raisesExceptionTrap.raises  s'    & 
		 
	
 r0   c                >    U R                  U[        R                  S9$ )aJ  
Wrap func and replace the result with the truth
value of the trap (True if no exception).

First, give the decorator an alias to support Python 3.8
Syntax.

>>> passes = ExceptionTrap(ValueError).passes

Now decorate a function that always fails.

>>> @passes
... def fail():
...     raise ValueError('failed')

>>> fail()
False
r   )r   operatornot_)r   r\   s     r   passesExceptionTrap.passes-  s    & {{4x}}{55r0   )r]   r   N)__name__
__module____qualname____firstlineno____doc__r]   	Exceptionr   r   propertyr   r   r   r   r   rs   r   r   __static_attributes__r*   r0   r   r   r      ss    B  H#,, %             %) 66r0   r   c                      \ rS rSrSrSrg)suppressiC  z
A version of contextlib.suppress with decorator support.

>>> @suppress(KeyError)
... def key_error():
...     {}['']
>>> key_error()
r*   N)r   r   r   r   r   r   r*   r0   r   r   r   C  s    r0   r   c                  .    \ rS rSrSrSS jrS rS rSrg)	on_interruptiN  a  
Replace a KeyboardInterrupt with SystemExit(1).

Useful in conjunction with console entry point functions.

>>> def do_interrupt():
...     raise KeyboardInterrupt()
>>> on_interrupt('error')(do_interrupt)()
Traceback (most recent call last):
...
SystemExit: 1
>>> on_interrupt('error', code=255)(do_interrupt)()
Traceback (most recent call last):
...
SystemExit: 255
>>> on_interrupt('suppress')(do_interrupt)()
>>> with __import__('pytest').raises(KeyboardInterrupt):
...     on_interrupt('ignore')(do_interrupt)()
c                   Xl         X l        g r)   actioncode)r   r   r   s      r   r   on_interrupt.__init__c  s    	r0   c                    U $ r)   r*   r   s    r   r   on_interrupt.__enter__g  r   r0   c                    U[         Ld  U R                  S:X  a  g U R                  S:X  a  [        U R                  5      UeU R                  S:H  $ )Nignoreerrorr   )KeyboardInterruptr   
SystemExitr   )r   exctypeexcinstexctbs       r   r   on_interrupt.__exit__j  sE    ++t{{h/F[[G#TYY'W4{{j((r0   r   N)r   r;   )	r   r   r   r   r   r   r   r   r   r*   r0   r   r   r   N  s    ()r0   r   )r   zstr | os.PathLikereturnIterator[str | os.PathLike]r)   )r"   zstr | os.PathLike | Noner   r   )r+   tarfile.TarInfor   r   )rw   z
str | Nonerx   rs   )(
__future__r   rK   rU   r5   r   r	   rc   r   rX   rt   sysrh   urllib.requestr   collections.abcr   version_info	backportsr   rL   r   r%   r8   r?   data_filterr   rP   tarball_cwdr_   rf   r    rk   re   robust_temp_dirr~   r   r   ContextDecoratorr   r*   r0   r   <module>r      s   "     	     
   $g!    04*"-*" *" *"ZO  +7+>+>@UV:< ug&
 ]]  " ##Hn6FG "$+/ 4n6 n6bz""J$?$? !):.. !)r0   