o
    Q `,4                     @   s   d Z ddlmZ ddlmZ ddlZddlZddlmZ ejr)ddlm	Z	m
Z
mZ g dZed	ejjZd
d Zdd Zd6ddZdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Z d+d, Z!d-d. Z"d/d0 Z#d1d2 Z$e%d3Z&d4d5 Z'dS )7aA  Useful functions for working with PyFilesystem paths.

This is broadly similar to the standard `os.path` module but works
with paths in the canonical format expected by all FS objects (that is,
separated by forward slashes and with an optional leading slash).

See :ref:`paths` for an explanation of PyFilesystem paths.

    )print_function)unicode_literalsN   )IllegalBackReference)ListTextTuple)abspathbasenamecombinedirnameforcedirfrombaseisabsisbase	isdotfileisparent	issamedir
iswildcarditeratepathjoinnormpathpartsrecursepathrelativefromrelpathsplitsplitextz(^|/)\.\.?($|/)|//c                 C   s   | dv r| S t | s| dS | drdnd}g }z| dD ]}|dv r/|dkr.|  q || q W n tyA   t| w |d| S )a  Normalize a path.

    This function simplifies a path by collapsing back-references
    and removing duplicated separators.

    Arguments:
        path (str): Path to normalize.

    Returns:
        str: A valid FS path.

    Example:
        >>> normpath("/foo//bar/frob/../baz")
        '/foo/bar/baz'
        >>> normpath("foo/../../bar")
        Traceback (most recent call last)
            ...
        IllegalBackReference: path 'foo/../../bar' contains back-references outside of filesystem"

    / ..)	_requires_normalizationrstrip
startswithr   popappend
IndexErrorr   r   )pathprefix
componentsZ	component r*   )/usr/lib/python3/dist-packages/fs/path.pyr   2   s$   
r   c                 C   s   t t| } | s
g S | dS )zIterate over the individual components of a path.

    Arguments:
        path (str): Path to iterate over.

    Returns:
        list: A list of path components.

    Example:
        >>> iteratepath('/foo/bar/baz')
        ['foo', 'bar', 'baz']

    r   )r   r   r   r'   r*   r*   r+   r   ]   s   
r   Fc                 C   s   | dv rdgS t t| d } dg}| j}|j}d}t| }||k r7|d|}|| d|  |d7 }||k s"|r@|ddd S |S )aN  Get intermediate paths from the root to the given path.

    Arguments:
        path (str): A PyFilesystem path
        reverse (bool): Reverses the order of the paths
            (default `False`).

    Returns:
        list: A list of paths.

    Example:
        >>> recursepath('a/b/c')
        ['/', '/a', '/a/b', '/a/b/c']

    r   r   N)r	   r   findr%   len)r'   reversepathsr.   r%   posZlen_pathr*   r*   r+   r   r   s    
r   c                 C   
   |  dS )zCheck if a path is an absolute path.

    Arguments:
        path (str): A PyFilesytem path.

    Returns:
        bool: `True` if the path is absolute (starts with a ``'/'``).

    r   r#   r,   r*   r*   r+   r      s   
r   c                 C   s   |  ds	d|  S | S )a/  Convert the given path to an absolute path.

    Since FS objects have no concept of a *current directory*, this
    simply adds a leading ``/`` character if the path doesn't already
    have one.

    Arguments:
        path (str): A PyFilesytem path.

    Returns:
        str: An absolute path.

    r   r4   r,   r*   r*   r+   r	      s   
r	   c                 C   r3   )a1  Convert the given path to a relative path.

    This is the inverse of `abspath`, stripping a leading ``'/'`` from
    the path if it is present.

    Arguments:
        path (str): A path to adjust.

    Returns:
        str: A relative path.

    Example:
        >>> relpath('/a/b')
        'a/b'

    r   )lstripr,   r*   r*   r+   r      s   
r   c                  G   sX   d}g }| D ]}|r|d dkr|dd= d}| | qtd|}|r*t|}|S )a]  Join any number of paths together.

    Arguments:
        *paths (str): Paths to join, given as positional arguments.

    Returns:
        str: The joined path.

    Example:
        >>> join('foo', 'bar', 'baz')
        'foo/bar/baz'
        >>> join('foo/bar', '../baz')
        'foo/baz'
        >>> join('foo/bar', '/baz')
        '/baz'

    Fr   r   NT)r%   r   r   r	   )r1   ZabsoluteZrelpathspr'   r*   r*   r+   r      s   

r   c                 C   s$   | s|  S d| d| dS )a  Join two paths together.

    This is faster than :func:`~fs.path.join`, but only works when the
    second path is relative, and there are no back references in either
    path.

    Arguments:
        path1 (str): A PyFilesytem path.
        path2 (str): A PyFilesytem path.

    Returns:
        str: The joint path.

    Example:
        >>> combine("foo/bar", "baz")
        'foo/bar/baz'

    z{}/{}r   )r5   formatr"   path1path2r*   r*   r+   r      s   r   c                 C   s<   t | }|d}|drdndg}|r||d7 }|S )zSplit a path in to its component parts.

    Arguments:
        path (str): Path to split in to parts.

    Returns:
        list: List of components

    Example:
        >>> parts('/foo/bar/baz')
        ['/', 'foo', 'bar', 'baz']

    r   z./)r   stripr#   r   )r'   _pathr)   Z_partsr*   r*   r+   r     s   
r   c                 C   s0   d| vrd| fS |  dd}|d pd|d fS )a  Split a path into (head, tail) pair.

    This function splits a path into a pair (head, tail) where 'tail' is
    the last pathname component and 'head' is all preceding components.

    Arguments:
        path (str): Path to split

    Returns:
        (str, str): a tuple containing the head and the tail of the path.

    Example:
        >>> split("foo/bar")
        ('foo', 'bar')
        >>> split("foo/bar/baz")
        ('foo/bar', 'baz')
        >>> split("/foo/bar/baz")
        ('/foo/bar', 'baz')

    r   r   r   r   )rsplit)r'   r   r*   r*   r+   r   #  s   r   c                 C   sb   t | \}}|dr|ddkr| dfS d|vr| dfS |dd\}}t||} | d| fS )a~  Split the extension from the path.

    Arguments:
        path (str): A path to split.

    Returns:
        (str, str): A tuple containing the path and the extension.

    Example:
        >>> splitext('baz.txt')
        ('baz', '.txt')
        >>> splitext('foo/bar/baz.txt')
        ('foo/bar/baz', '.txt')
        >>> splitext('foo/bar/.foo')
        ('foo/bar/.foo', '')

    .r   r   )r   r#   countr=   r   )r'   parent_pathpathnameextr*   r*   r+   r   ?  s   
r   c                 C   s   t | dS )aN  Detect if a path references a dot file.

    Arguments:
        path (str): Path to check.

    Returns:
        bool: `True` if the resource name starts with a ``'.'``.

    Example:
        >>> isdotfile('.baz')
        True
        >>> isdotfile('foo/bar/.baz')
        True
        >>> isdotfile('foo/bar.baz')
        False

    r>   )r
   r#   r,   r*   r*   r+   r   \  s   r   c                 C      t | d S )a  Return the parent directory of a path.

    This is always equivalent to the 'head' component of the value
    returned by ``split(path)``.

    Arguments:
        path (str): A PyFilesytem path.

    Returns:
        str: the parent directory of the given path.

    Example:
        >>> dirname('foo/bar/baz')
        'foo/bar'
        >>> dirname('/foo/bar')
        '/foo'
        >>> dirname('/foo')
        '/'

    r   r   r,   r*   r*   r+   r   r     r   c                 C   rC   )a  Return the basename of the resource referenced by a path.

    This is always equivalent to the 'tail' component of the value
    returned by split(path).

    Arguments:
        path (str): A PyFilesytem path.

    Returns:
        str: the name of the resource at the given path.

    Example:
        >>> basename('foo/bar/baz')
        'baz'
        >>> basename('foo/bar')
        'bar'
        >>> basename('foo/bar/')
        ''

    r   rD   r,   r*   r*   r+   r
     rE   r
   c                 C   s   t t| t t|kS )a  Check if two paths reference a resource in the same directory.

    Arguments:
        path1 (str): A PyFilesytem path.
        path2 (str): A PyFilesytem path.

    Returns:
        bool: `True` if the two resources are in the same directory.

    Example:
        >>> issamedir("foo/bar/baz.txt", "foo/bar/spam.txt")
        True
        >>> issamedir("foo/bar/baz/txt", "spam/eggs/spam.txt")
        False

    )r   r   r8   r*   r*   r+   r     s   r   c                 C   s"   t t| }t t|}||S )a(  Check if ``path1`` is a base of ``path2``.

    Arguments:
        path1 (str): A PyFilesytem path.
        path2 (str): A PyFilesytem path.

    Returns:
        bool: `True` if ``path2`` starts with ``path1``

    Example:
        >>> isbase('foo/bar', 'foo/bar/baz/egg.txt')
        True

    )r   r	   r#   )r9   r:   Z_path1Z_path2r*   r*   r+   r     s   
r   c                 C   sv   |  d}| d}|r|d dkr|  |r|d dkst|t|kr(dS t||D ]\}}||kr8 dS q-dS )a  Check if ``path1`` is a parent directory of ``path2``.

    Arguments:
        path1 (str): A PyFilesytem path.
        path2 (str): A PyFilesytem path.

    Returns:
        bool: `True` if ``path1`` is a parent directory of ``path2``

    Example:
        >>> isparent("foo/bar", "foo/bar/spam.txt")
        True
        >>> isparent("foo/bar/", "foo/bar")
        True
        >>> isparent("foo/barry", "foo/baz/bar")
        False
        >>> isparent("foo/bar/baz/", "foo/baz/bar")
        False

    r   r-   r   FT)r   r$   r/   zip)r9   r:   Zbits1Zbits2Zbit1Zbit2r*   r*   r+   r     s   

r   c                 C   s   |  ds	| d S | S )a]  Ensure the path ends with a trailing forward slash.

    Arguments:
        path (str): A PyFilesytem path.

    Returns:
        str: The path, ending with a slash.

    Example:
        >>> forcedir("foo/bar")
        'foo/bar/'
        >>> forcedir("foo/bar/")
        'foo/bar/'
        >>> forcedir("foo/spam.txt")
        'foo/spam.txt/'

    r   )endswithr,   r*   r*   r+   r     s   
r   c                 C   s"   t | |s	td|t| d S )a,  Get the final path of ``path2`` that isn't in ``path1``.

    Arguments:
        path1 (str): A PyFilesytem path.
        path2 (str): A PyFilesytem path.

    Returns:
        str: the final part of ``path2``.

    Example:
        >>> frombase('foo/bar/', 'foo/bar/baz/egg')
        'baz/egg'

    zpath1 must be a prefix of path2N)r   
ValueErrorr/   r8   r*   r*   r+   r     s   
r   c                 C   sh   t t| }t t|}d}t||D ]\}}||kr n|d7 }qddgt||  ||d  S )aj  Return a path relative from a given base path.

    Insert backrefs as appropriate to reach the path from the base.

    Arguments:
        base (str): Path to a directory.
        path (str): Path to make relative.

    Returns:
        str: the path to ``base`` from ``path``.

    >>> relativefrom("foo/bar", "baz/index.html")
    '../../baz/index.html'

    r   r   r   r    N)listr   rF   r   r/   )baser'   Z
base_parts
path_partscommonZcomponent_aZcomponent_br*   r*   r+   r     s   
$r   z*?[]!{}c                 C   s   | dusJ t |  S )a  Check if a path ends with a wildcard.

    Arguments:
        path (str): A PyFilesystem path.

    Returns:
        bool: `True` if path ends with a wildcard.

    Example:
        >>> iswildcard('foo/bar/baz.*')
        True
        >>> iswildcard('foo/bar')
        False

    N)_WILD_CHARS
isdisjointr,   r*   r*   r+   r   =  s   r   )F)(__doc__Z
__future__r   r   retypingerrorsr   ZTYPE_CHECKINGr   r   r   __all__compileUNICODEsearchr!   r   r   r   r   r	   r   r   r   r   r   r   r   r   r
   r   r   r   r   r   r   	frozensetrM   r   r*   r*   r*   r+   <module>   s@    
+
&""