o
    l>j0                     @  sF  U d dl m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
Z
d dlZd dlZd dlZd dlZd dlmZmZmZ d dlmZ d dlmZmZmZmZ es^ejdkrcd dlZnd dlmZ erd dlmZ d d	lm Z m!Z!m"Z" d d
l#m$Z$m%Z%m&Z& ede dZ'e$dZ(e)e*e+ dB e+dB edB f Z,de-d< edZ.edddZ/edddZ0ej1dLddZ2ej1dMdNdd Z3d!d" Z4dOd'd(Z5e4ej6e5Z7dPd,d-Z8e8e2e3Z9	 dQd3d4Z:dRd6d7Z;ej1e	j<fdSd;d<Z=ej>e=e; d=Z?ej1dde?fdTdDdEZ@G dFdG dGZAG dHdI dIejBejCZBG dJdK dKejCZDdS )U    )annotationsN)Callable	GeneratorIterator)TracebackType)TYPE_CHECKINGLiteralTypeVarcast)      )tarfile)	TypeAlias)FileDescriptorOrPath
OptExcInfoStrPath)	ParamSpecSelfUnpack_FileDescriptorOrPathT)bound_Pr   _UnpackableOptExcInfo_R_T1_coT)	covariant_T2_codirr   returnIterator[StrPath]c              	   c  s8    t  }t |  z| V  W t | dS t | w )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)r   orig r$   L/home/thesage/.local/lib/python3.10/site-packages/jaraco/context/__init__.pypushd4   s   	
r&   urlstr
target_dirStrPath | Nonec              	   c  s    |du rt j| dddd}t | z/tj| }tj	|dd}|j
|td W d   n1 s8w   Y  |V  W t| dS t| w )au  
    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)r'   r)   reqtfr$   r$   r%   tarballE   s    
r=   c                  G  s   dd }t || dd S )Nc                   s    fddS )Nc                   s    | ||S Nr$   memberr.   f1f2r$   r%   <lambda>s   s    z?_compose_tarfile_filters.<locals>.compose_two.<locals>.<lambda>r$   rA   r$   rA   r%   compose_twor   s   z-_compose_tarfile_filters.<locals>.compose_twoc                 S     | S r>   r$   r?   r$   r$   r%   rD   u   s    z*_compose_tarfile_filters.<locals>.<lambda>)	functoolsreduce)filtersrE   r$   r$   r%   _compose_tarfile_filtersq   s   rJ   r@   tarfile.TarInfor.   objectc                 C  s   | j dd\}| _ | S )N/   )namesplit)r@   r.   _r$   r$   r%   strip_first_componentx   s   rR   cmgrsUnpack[tuple[Callable[[_T1_co], contextlib.AbstractContextManager[_T2_co]], Callable[_P, contextlib.AbstractContextManager[_T1_co]]]]9Callable[_P, contextlib._GeneratorContextManager[_T2_co]]c                  G  s   d
dd}t |t| S )a  
    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)
    inner7Callable[_P, contextlib.AbstractContextManager[_T1_co]]outer=Callable[[_T1_co], contextlib.AbstractContextManager[_T2_co]]r   rU   c                   s   d	 fdd}t |S )
Nargs_P.argskwargs	_P.kwargsr   Generator[_T2_co]c               	   ?  st     | i |(}|}|V  W d    n1 sw   Y  W d    d S W d    d S 1 s3w   Y  d S r>   r$   )rZ   r\   savedresrV   rX   r$   r%   composed   s   Pz/_compose.<locals>.compose_two.<locals>.composed)rZ   r[   r\   r]   r   r^   )
contextlibcontextmanager)rV   rX   rb   r$   ra   r%   rE      s   
z_compose.<locals>.compose_twoN)rV   rW   rX   rY   r   rU   )rG   rH   reversed)rS   rE   r$   r$   r%   _compose   s   
rf   func*Callable[[_FileDescriptorOrPathT], object]exc_infotuple[object, OSError, object]Nonec                 C  sR   |\}}}| t jt jt jfv r(|jtjkr(t |tjtj	B tj
B  | | dS  )z>
    Add support for removing read-only files on Windows.
    N)r    rmdirremoveunlinkerrnoEACCESchmodstatS_IRWXUS_IRWXGS_IRWXO)rg   r.   ri   rQ   excr$   r$   r%   remove_readonly   s
   
 rw   Callable[..., None]c                   C  s(   t  dkrtjtdtjtdS tjS )NWindowsrx   )onerror)platformsystemrG   partialr
   r9   r:   rw   r$   r$   r$   r%   robust_remover   s   
r~   removerCallable[[str], object]Generator[str]c                 c  s*    t  }z
|V  W | | dS | | w )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)r   temp_dirr$   r$   r%   r      s
   r   )r   branch
str | Nonequietbooldest_ctx4Callable[[], contextlib.AbstractContextManager[str]]c                 c  s    d| v rdnd}| ,}|d| |g}| d|gt|  |r#tjnd}tj|||d |V  W d   dS 1 s;w   Y  dS )a  
    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)extendr   
subprocessDEVNULL
check_call)r'   r   r   r   exerepo_dircmdstreamr$   r$   r%   repo_context   s   "r   c                   @  s   e Zd ZU dZdZded< effd(ddZd)ddZe	d*ddZ
e	d+ddZe	d,ddZd-ddZd.ddZedd/d#d$Zd0d%d&Zd'S )1ExceptionTrapa  
    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
    )NNNr   ri   
exceptionstuple[type[BaseException], ...]c                 C  s
   || _ d S r>   )r   )selfr   r$   r$   r%   __init__+     
zExceptionTrap.__init__r   r   c                 C  rF   r>   r$   r   r$   r$   r%   	__enter__.     zExceptionTrap.__enter__type[BaseException] | Nonec                 C  
   | j d S Nr   ri   r   r$   r$   r%   type1     
zExceptionTrap.typeBaseException | Nonec                 C  r   )NrN   r   r   r$   r$   r%   value5  r   zExceptionTrap.valueTracebackType | Nonec                 C  r   )N   r   r   r$   r$   r%   tb9  r   zExceptionTrap.tbUnpack[_UnpackableOptExcInfo]*builtins.type[BaseException] | None | boolc                 G  s&   |d }|ot || j}|r|| _|S r   )
issubclassr   ri   )r   ri   exc_typematchesr$   r$   r%   __exit__=  s
   zExceptionTrap.__exit__r   c                 C  s
   t | jS r>   )r   r   r   r$   r$   r%   __bool__G  r   zExceptionTrap.__bool___testrg   Callable[_P, _R]r   Callable[[ExceptionTrap], bool]$functools._Wrapped[_P, _R, _P, bool]c                  s    t d
 fdd}|S )a>  
        Wrap func and replace the result with the truth
        value of the trap (True if an exception occurred).

        Decorate a function that always fails.

        >>> @ExceptionTrap(ValueError).raises
        ... def fail():
        ...     raise ValueError('failed')
        >>> fail()
        True
        rZ   r[   r\   r]   r   r   c                    sF   t j}| i | W d     |S 1 sw   Y   |S r>   )r   r   )rZ   r\   trapr   rg   r   r$   r%   wrapperZ  s   
z%ExceptionTrap.raises.<locals>.wrapperN)rZ   r[   r\   r]   r   r   )rG   wraps)r   rg   r   r   r$   r   r%   raisesJ  s   zExceptionTrap.raisesc                 C  s   | j |tjdS )a7  
        Wrap func and replace the result with the truth
        value of the trap (True if no exception).

        Decorate a function that always fails.

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

        >>> fail()
        False
        r   )r   operatornot_)r   rg   r$   r$   r%   passesb  s   zExceptionTrap.passesN)r   r   r   r   )r   r   )r   r   )r   r   )ri   r   r   r   )r   r   )rg   r   r   r   r   r   )rg   r   r   r   )__name__
__module____qualname____doc__ri   __annotations__	Exceptionr   r   propertyr   r   r   r   r   r   r   r   r$   r$   r$   r%   r     s    
 !



r   c                   @  s   e Zd ZdZdS )suppressz
    A version of contextlib.suppress with decorator support.

    >>> @suppress(KeyError)
    ... def key_error():
    ...     {}['']
    >>> key_error()
    N)r   r   r   r   r$   r$   r$   r%   r   s  s    r   c                   @  s2   e Zd ZdZ	dddd	ZdddZdddZdS )on_interruptaF  
    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)()
    errorrN   codeintaction&Literal['ignore', 'suppress', 'error']c                C  s   || _ || _d S r>   )r   r   )r   r   r   r$   r$   r%   r     s   
zon_interrupt.__init__r   r   c                 C  rF   r>   r$   r   r$   r$   r%   r     r   zon_interrupt.__enter__exctyper   excinstr   exctbr   None | boolc                 C  s6   |t us	| jdkrd S | jdkrt| j|| jdkS )Nignorer   r   )KeyboardInterruptr   
SystemExitr   )r   r   r   r   r$   r$   r%   r     s
   

zon_interrupt.__exit__N)r   rN   )r   r   r   r   r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r$   r$   r$   r%   r   ~  s    
r   )r   r   r   r   r>   )r'   r(   r)   r*   r   r   )r@   rK   r.   rL   r   rK   )rS   rT   r   rU   )rg   rh   r.   r   ri   rj   r   rk   )r   rx   )r   r   r   r   )
r'   r(   r   r   r   r   r   r   r   r   )E
__future__r   builtinsrc   ro   rG   r   r    r{   r9   rr   r   sysr   urllib.requestr3   collections.abcr   r   r   typesr   typingr   r   r	   r
   version_infor   	backportsr   	_typeshedr   r   r   typing_extensionsr   r   r   r   r   tupler   BaseExceptionr   r   r   r   r   rd   r&   r=   rJ   rR   data_filterr8   rf   tarball_cwdrw   r~   r:   r   r}   robust_temp_dirr   r   r   ContextDecoratorr   r$   r$   r$   r%   <module>   sx    

+


-

l