
    obc4                     F   d Z ddlmZ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j                  dej                        j                  Zd	 Zd
 ZddZd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$ e%d      Z&d Z'y) aA  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                 T   | dv r| S t        |       s| j                  d      S | j                  d      rdnd}g }	 | j                  d      D ].  }|dv r|dk(  s|j	                          |j                  |       0 	 |dj                  |      z   S # t        $ r t        |       w xY w)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):
            ...
        fs.errors.IllegalBackReference: path 'foo/../../bar' contains back-references outside of filesystem

    / ..)	_requires_normalizationrstrip
startswithr   popappend
IndexErrorr   r   )pathprefix
components	components       )/usr/lib/python3/dist-packages/fs/path.pyr   r   2   s    , s{ #4({{3OOC(SbFJ	)C 	-ID $NN$!!),	- CHHZ(((  )"4(()s   B $B B'c                 T    t        t        |             } | sg S | j                  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)   s    r-   r   r   ^   s(     8D>"D	::c?    c                     | dv rdgS t        t        |             dz   } dg}| j                  }|j                  }d}t	        |       }||k  r |d|      } || d|        |dz  }||k  r|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pathsr3   r'   poslen_paths          r-   r   r   s   s    " s{u8D>"S(DEE99D\\F
C4yH
.3ntDSzq .
 TrT{Lr0   c                 $    | j                  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/   s    r-   r   r      s     ??3r0   c                 2    | j                  d      sd| z   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    r:   r/   s    r-   r
   r
      s     ??3TzKr0   c                 $    | j                  d      S )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/   s    r-   r   r      s    $ ;;sr0   c                      d}g }| D ]%  }|s|d   dk(  r|dd= d}|j                  |       ' t        dj                  |            }|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
   )r6   absoluterelpathspr)   s        r-   r   r      si    & HH ts{QKOOA CHHX&'Dt}Kr0   c                     | s|j                         S dj                  | j                  d      |j                  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    )r=   formatr$   path1path2s     r-   r   r      s6    ( ||~>>%,,s+U\\#->??r0   c                     t        |       }|j                  d      }|j                  d      rdndg}|r||j                  d      z  }|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+   _partss       r-   r   r     sO     TNES!J%%c*c5F*""3''Mr0   c                 R    d| vrd| fS | j                  dd      }|d   xs 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   s     r-   r   r   $  s<    , $DzKKQE!HOU1X&&r0   c                     t        |       \  }}|j                  d      r|j                  d      dk(  r| dfS d|vr| dfS |j                  dd      \  }}t	        ||      } | d|z   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%   countrL   r   )r)   parent_pathpathnameexts       r-   r   r   @  sx    & "$KK3HNN3$71$<Rx
(RxOOC+MHcX&Ds?r0   c                 6    t        |       j                  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

    rN   )r   r%   r/   s    r-   r   r   ]  s    & D>$$S))r0   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/   s    r-   r   r   s      , ;q>r0   c                     t        |       d   S )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   rU   r/   s    r-   r   r     rV   r0   c                 T    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   rD   s     r-   r   r     s!    $ 8E?#wx'???r0   c                 t    t        t        |             }t        t        |            }|j                  |      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%   )rE   rF   _path1_path2s       r-   r   r     s1      gen%Fgen%FV$$r0   c                     | j                  d      }|j                  d      }|r#|d   dk(  r|j                          |r	|d   dk(  rt        |      t        |      kD  ryt        ||      D ]  \  }}||k7  s y y)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    r2   r!   FT)r   r&   r4   zip)rE   rF   bits1bits2bit1bit2s         r-   r   r     s    , KKEKKE
E"IO		 E"IO
5zCJE5) t4< r0   c                 2    | j                  d      s| dz   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/   s    r-   r   r     s    & ==czKr0   c                 L    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   
ValueErrorr4   rD   s     r-   r   r   	  s+      E5!:;;Ur0   c                     t        t        |             }t        t        |            }d}t        ||      D ]  \  }}||k7  r n|dz  } dj                  dgt	        |      |z
  z  ||d z         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   r]   r   r4   )baser)   
base_parts
path_partscommoncomponent_acomponent_bs          r-   r   r     s    " k$'(Jk$'(JF$'
J$?  [+%!
 88TFc*o67*VW:MMNNr0   z*?[]!{}c                 6    | J t         j                  |        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

    )_WILD_CHARS
isdisjointr/   s    r-   r   r   >  s$    " %%d+++r0   )F)(__doc__
__future__r   r   typingreerrorsr   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   	frozensetro   r    r0   r-   <module>r}      s    8  	 (	((0 %"**%:BJJGNN ))X*#L (*D@20'8:*,22@*%*D0*O: 	",r0   