o
    pfUk                     @   s  d Z ddlmZ ddlZddlmZmZmZ ddlm	Z	 ddl
mZ ddlmZmZmZ ejr[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mZ ddlmZ eeege f Z!ej"dddZ#eddZ$	 G dd de%Z&G dd dej'e# Z(e& Z)e)j*Z*e)j+Z,e)jZ-e)j.Z/dS )zMachinery for walking a filesystem.

*Walking* a filesystem means recursively visiting a directory and
any sub-directories. It is a fairly common requirement for copying,
searching etc. See :ref:`walking` for details.
    )unicode_literalsN)defaultdictdeque
namedtuple   )	make_repr)FSError)abspathcombinenormpath)
AnyCallable
CollectionIteratorListMutableMappingOptionalTextTupleType)FS)Info_Fr   )boundStepzpath, dirs, filesc                       s   e Zd ZdZ								d, fdd	Zedd Zed	d
 Zedd Zedd Z	dd Z
	d-ddZdd Zdd Zdd Zdd Zdd Z	d-ddZ		d.d d!Zd/d"d#Zd/d$d%Z		d.d&d'Z	d-d(d)Z	d-d*d+Z  ZS )0Walkerz>A walker object recursively lists directories in a filesystem.FNbreadthc	           	         s   |dvrt d|| _|r|rt dn|r| jn| j}t|s$td|| _|| _|| _|| _	|| _
|| _|| _tt|   dS )a-  Create a new `Walker` instance.

        Arguments:
            ignore_errors (bool): If `True`, any errors reading a
                directory will be ignored, otherwise exceptions will
                be raised.
            on_error (callable, optional): If ``ignore_errors`` is `False`,
                then this callable will be invoked for a path and the
                exception object. It should return `True` to ignore the error,
                or `False` to re-raise it.
            search (str): If ``"breadth"`` then the directory will be
                walked *top down*. Set to ``"depth"`` to walk *bottom up*.
            filter (list, optional): If supplied, this parameter should be
                a list of filename patterns, e.g. ``["*.py"]``. Files will
                only be returned if the final component matches one of the
                patterns.
            exclude (list, optional): If supplied, this parameter should be
                a list of filename patterns, e.g. ``["~*"]``. Files matching
                any of these patterns will be removed from the walk.
            filter_dirs (list, optional): A list of patterns that will be used
                to match directories paths. The walk will only open directories
                that match at least one of these patterns.
            exclude_dirs (list, optional): A list of patterns that will be
                used to filter out directories from the walk. e.g.
                ``['*.svn', '*.git']``.
            max_depth (int, optional): Maximum directory depth to walk.

        )r   depthz#search must be 'breadth' or 'depth'z,on_error is invalid when ignore_errors==Truezon_error must be callableN)
ValueErrorignore_errors_ignore_errors_raise_errorscallable	TypeErroron_errorsearchfilterexcludefilter_dirsexclude_dirs	max_depthsuperr   __init__)	selfr   r$   r%   r&   r'   r(   r)   r*   	__class__ @/home/ertert/spirit/venv/lib/python3.10/site-packages/fs/walk.pyr,   5   s$   (zWalker.__init__c                 C      dS )z#Ignore dir scan errors when called.Tr0   clspatherrorr0   r0   r1   r    q      zWalker._ignore_errorsc                 C   r2   )z%Re-raise dir scan errors when called.Fr0   r3   r0   r0   r1   r!   w   r7   zWalker._raise_errorsc                 C   s    | d}|r|dd S dS )zBCalculate the 'depth' of a directory path (i.e. count components)./r   r   )stripcount)r4   r5   _pathr0   r0   r1   _calculate_depth}   s   
zWalker._calculate_depthc                 C   s   t |S )a  Bind a `Walker` instance to a given filesystem.

        This *binds* in instance of the Walker to a given filesystem, so
        that you won't need to explicitly provide the filesystem as a
        parameter.

        Arguments:
            fs (FS): A filesystem object.

        Returns:
            ~fs.walk.BoundWalker: a bound walker.

        Examples:
            Use this method to explicitly bind a filesystem instance::

                >>> walker = Walker.bind(my_fs)
                >>> for path in walker.files(filter=['*.py']):
                ...     print(path)
                /foo.py
                /bar.py

            Unless you have written a customized walker class, you will
            be unlikely to need to call this explicitly, as filesystem
            objects already have a ``walk`` attribute which is a bound
            walker object::

                >>> for path in my_fs.walk.files(filter=['*.py']):
                ...     print(path)
                /foo.py
                /bar.py

        )BoundWalker)r4   fsr0   r0   r1   bind   s   #zWalker.bindc                 C   sN   t | jj| jdf| jd f| jdf| jd f| jd f| jd f| j	d f| j
d fd	S )NFr   )r   r$   r%   r&   r'   r(   r)   r*   )r   r/   __name__r   r$   r%   r&   r'   r(   r)   r*   r-   r0   r0   r1   __repr__   s   zWalker.__repr__c                 C   s*   | j dkr| j|||dS | j|||dS )zGet the walk generator.r   
namespaces)r%   _walk_breadth_walk_depth)r-   r>   r5   rD   r0   r0   r1   
_iter_walk   s   
zWalker._iter_walkc                 C   sJ   | j dur|| j |jrdS | jdur|| j|jsdS | |||S )z6Check if a directory should be considered in the walk.NF)r)   matchnamer(   check_open_dirr-   r>   r5   infor0   r0   r1   _check_open_dir   s
   zWalker._check_open_dirc                 C   r2   )ad  Check if a directory should be opened.

        Override to exclude directories from the walk.

        Arguments:
            fs (FS): A filesystem instance.
            path (str): Path to directory.
            info (Info): A resource info object for the directory.

        Returns:
            bool: `True` if the directory should be opened.

        Tr0   rK   r0   r0   r1   rJ      s   zWalker.check_open_dirc                 C   s&   | j dur|| j krdS | |||S )z0Check if a directory contents should be scanned.NF)r*   check_scan_dir)r-   r>   r5   rL   r   r0   r0   r1   _check_scan_dir   s   zWalker._check_scan_dirc                 C   r2   )a  Check if a directory should be scanned.

        Override to omit scanning of certain directories. If a directory
        is omitted, it will appear in the walk but its files and
        sub-directories will not.

        Arguments:
            fs (FS): A filesystem instance.
            path (str): Path to directory.
            info (Info): A resource info object for the directory.

        Returns:
            bool: `True` if the directory should be scanned.

        Tr0   rK   r0   r0   r1   rN      s   zWalker.check_scan_dirc                 C   s.   | j dur|| j |jrdS || j|jS )a  Check if a filename should be included.

        Override to exclude files from the walk.

        Arguments:
            fs (FS): A filesystem instance.
            info (Info): A resource info object.

        Returns:
            bool: `True` if the file should be included.

        NF)r'   rH   rI   r&   )r-   r>   rL   r0   r0   r1   
check_file   s   zWalker.check_filec              
   c   sX    z|j ||dD ]}|V  q	W dS  ty+ } z| ||s  W Y d}~dS d}~ww )a  Get an iterator of `Info` objects for a directory path.

        Arguments:
            fs (FS): A filesystem instance.
            dir_path (str): A path to a directory on the filesystem.
            namespaces (list): A list of additional namespaces to
                include in the `Info` objects.

        Returns:
            ~collections.Iterator: iterator of `Info` objects for
            resources within the given path.

        rC   N)scandirr   r$   )r-   r>   dir_pathrD   rL   r6   r0   r0   r1   _scan
  s   zWalker._scanr8   c                 c   s    t t|}tt}| j|||d}|D ]/\}}|du r=g }	g }
|| D ]}|jr,|	n|
| q%t||	|
V  ||= q|| | qdS )ab  Walk the directory structure of a filesystem.

        Arguments:
            fs (FS): A filesystem instance.
            path (str): A path to a directory on the filesystem.
            namespaces (list, optional): A list of additional namespaces
                to add to the `Info` objects.

        Returns:
            collections.Iterator: an iterator of `~fs.walk.Step` instances.

        The return value is an iterator of ``(<path>, <dirs>, <files>)``
        named tuples,  where ``<path>`` is an absolute path to a
        directory, and ``<dirs>`` and ``<files>`` are a list of
        `~fs.info.Info` objects for directories and files in ``<path>``.

        Example:
            >>> walker = Walker(filter=['*.py'])
            >>> for path, dirs, files in walker.walk(my_fs, namespaces=["details"]):
            ...    print("[{}]".format(path))
            ...    print("{} directories".format(len(dirs)))
            ...    total = sum(info.size for info in files)
            ...    print("{} bytes".format(total))
            [/]
            2 directories
            55 bytes
            ...

        rC   N)r	   r   r   listrG   is_dirappendr   )r-   r>   r5   rD   r;   dir_info_walkrR   rL   dirsfiles_infor0   r0   r1   walk%  s   $zWalker.walkc                 c   s>    t }| j||dD ]\}}|dur|js|||jV  q
dS )aD  Walk a filesystem, yielding absolute paths to files.

        Arguments:
            fs (FS): A filesystem instance.
            path (str): A path to a directory on the filesystem.

        Yields:
            str: absolute path to files on the filesystem found
            recursively within the given directory.

        r5   Nr
   rG   rU   rI   r-   r>   r5   _combiner;   rL   r0   r0   r1   rZ   W     zWalker.filesc                 c   s>    t }| j||dD ]\}}|dur|jr|||jV  q
dS )aP  Walk a filesystem, yielding absolute paths to directories.

        Arguments:
            fs (FS): A filesystem instance.
            path (str): A path to a directory on the filesystem.

        Yields:
            str: absolute path to directories on the filesystem found
            recursively within the given directory.

        r]   Nr^   r_   r0   r0   r1   rY   i  ra   zWalker.dirsc                 c   sB    t }| j|||d}|D ]\}}|dur|||j|fV  qdS )a  Walk a filesystem, yielding tuples of ``(<path>, <info>)``.

        Arguments:
            fs (FS): A filesystem instance.
            path (str): A path to a directory on the filesystem.
            namespaces (list, optional): A list of additional namespaces
                to add to the `Info` objects.

        Yields:
            (str, Info): a tuple of ``(<absolute path>, <resource info>)``.

        r5   rD   N)r
   rG   rI   )r-   r>   r5   rD   r`   rX   r;   rL   r0   r0   r1   rL   {  s   zWalker.infoc                 c   s    t |g}|j}|j}t}| j}| j}	| j}
| j}| j}|	|}|ri| }||||dD ]2}|j	rU|	|| d }|
|||rT||fV  |||||rT||||j
 q-|||r_||fV  q-|dfV  |s#dS dS )z*Walk files using a *breadth first* search.rC   r   N)r   
appendleftpopr
   rS   r<   rM   rO   rP   rU   rI   )r-   r>   r5   rD   queuepushrd   r`   rS   r<   rM   rO   _check_filer   rR   rL   _depthr0   r0   r1   rE     s4   




zWalker._walk_breadthc                 c   s   t }| j}| j}| j}| j}| j}	||}
|||||ddfg}|j}|r|d \}}}t|d}|du rF|dur=|V  |dfV  |d= n=|jry|||
 d }||||rx|||||rs|||j	}||||||d||ff n||fV  n
|	||r||fV  |s&dS dS )z(Walk files using a *depth first* search.rC   Nr   )
r
   rS   r<   rM   rO   rP   rV   nextrU   rI   )r-   r>   r5   rD   r`   rS   r<   rM   rO   rg   r   stackrf   rR   
iter_filesparentrL   rh   r;   r0   r0   r1   rF     sF   





zWalker._walk_depth)FNr   NNNNN)Nr8   Nr8   )r@   
__module____qualname____doc__r,   classmethodr    r!   r<   r?   rB   rG   rM   rJ   rO   rN   rP   rS   r\   rZ   rY   rL   rE   rF   __classcell__r0   r0   r.   r1   r   2   sR    <



$
	


2


'r   c                   @   s`   e Zd ZdZefddZdd Zdd Z			dd
dZeZ	dddZ
dddZ			dddZd	S )r=   a  A class that binds a `Walker` instance to a `FS` instance.

    You will typically not need to create instances of this class
    explicitly. Filesystems have a `~FS.walk` property which returns a
    `BoundWalker` object.

    Example:
        >>> tmp_fs = fs.tempfs.TempFS()
        >>> tmp_fs.walk
        BoundWalker(TempFS())

    A `BoundWalker` is callable. Calling it is an alias for the
    `~fs.walk.BoundWalker.walk` method.

    c                 C   s   || _ || _dS )zCreate a new walker bound to the given filesystem.

        Arguments:
            fs (FS): A filesystem instance.
            walker_class (type): A `~fs.walk.WalkerBase`
                sub-class. The default uses `~fs.walk.Walker`.

        N)r>   walker_class)r-   r>   ru   r0   r0   r1   r,     s   

zBoundWalker.__init__c                 C   s   d | jS )NzBoundWalker({!r}))formatr>   rA   r0   r0   r1   rB     s   zBoundWalker.__repr__c                 O   s   | j |i |}|S )zCreate a walker instance.)ru   )r-   argskwargswalkerr0   r0   r1   _make_walker  s   zBoundWalker._make_walkerr8   Nc                 K   "   | j di |}|j| j||dS )aY
  Walk the directory structure of a filesystem.

        Arguments:
            path (str):
            namespaces (list, optional): A list of namespaces to include
                in the resource information, e.g. ``['basic', 'access']``
                (defaults to ``['basic']``).

        Keyword Arguments:
            ignore_errors (bool): If `True`, any errors reading a
                directory will be ignored, otherwise exceptions will be
                raised.
            on_error (callable): If ``ignore_errors`` is `False`, then
                this callable will be invoked with a path and the exception
                object. It should return `True` to ignore the error, or
                `False` to re-raise it.
            search (str): If ``'breadth'`` then the directory will be
                walked *top down*. Set to ``'depth'`` to walk *bottom up*.
            filter (list): If supplied, this parameter should be a list
                of file name patterns, e.g. ``['*.py']``. Files will only be
                returned if the final component matches one of the
                patterns.
            exclude (list, optional): If supplied, this parameter should be
                a list of filename patterns, e.g. ``['~*', '.*']``. Files matching
                any of these patterns will be removed from the walk.
            filter_dirs (list, optional): A list of patterns that will be used
                to match directories paths. The walk will only open directories
                that match at least one of these patterns.
            exclude_dirs (list): A list of patterns that will be used
                to filter out directories from the walk, e.g. ``['*.svn',
                '*.git']``.
            max_depth (int, optional): Maximum directory depth to walk.

        Returns:
            ~collections.Iterator: an iterator of ``(<path>, <dirs>, <files>)``
            named tuples,  where ``<path>`` is an absolute path to a
            directory, and ``<dirs>`` and ``<files>`` are a list of
            `~fs.info.Info` objects for directories and files in ``<path>``.

        Example:
            >>> walker = Walker(filter=['*.py'])
            >>> for path, dirs, files in walker.walk(my_fs, namespaces=['details']):
            ...     print("[{}]".format(path))
            ...     print("{} directories".format(len(dirs)))
            ...     total = sum(info.size for info in files)
            ...     print("{} bytes".format(total))
            [/]
            2 directories
            55 bytes
            ...

        This method invokes `Walker.walk` with bound `FS` object.

        rb   Nr0   )rz   r\   r>   r-   r5   rD   rx   ry   r0   r0   r1   r\     s   =zBoundWalker.walkc                 K       | j di |}|j| j|dS )aA  Walk a filesystem, yielding absolute paths to files.

        Arguments:
            path (str): A path to a directory.

        Keyword Arguments:
            ignore_errors (bool): If `True`, any errors reading a
                directory will be ignored, otherwise exceptions will be
                raised.
            on_error (callable): If ``ignore_errors`` is `False`, then
                this callable will be invoked with a path and the exception
                object. It should return `True` to ignore the error, or
                `False` to re-raise it.
            search (str): If ``'breadth'`` then the directory will be
                walked *top down*. Set to ``'depth'`` to walk *bottom up*.
            filter (list): If supplied, this parameter should be a list
                of file name patterns, e.g. ``['*.py']``. Files will only be
                returned if the final component matches one of the
                patterns.
            exclude (list, optional): If supplied, this parameter should be
                a list of filename patterns, e.g. ``['~*', '.*']``. Files matching
                any of these patterns will be removed from the walk.
            filter_dirs (list, optional): A list of patterns that will be used
                to match directories paths. The walk will only open directories
                that match at least one of these patterns.
            exclude_dirs (list): A list of patterns that will be used
                to filter out directories from the walk, e.g. ``['*.svn',
                '*.git']``.
            max_depth (int, optional): Maximum directory depth to walk.

        Returns:
            ~collections.Iterator: An iterator over file paths (absolute
            from the filesystem root).

        This method invokes `Walker.files` with the bound `FS` object.

        r]   Nr0   )rz   rZ   r>   r-   r5   rx   ry   r0   r0   r1   rZ   T  s   'zBoundWalker.filesc                 K   r}   )au  Walk a filesystem, yielding absolute paths to directories.

        Arguments:
            path (str): A path to a directory.

        Keyword Arguments:
            ignore_errors (bool): If `True`, any errors reading a
                directory will be ignored, otherwise exceptions will be
                raised.
            on_error (callable): If ``ignore_errors`` is `False`, then
                this callable will be invoked with a path and the exception
                object. It should return `True` to ignore the error, or
                `False` to re-raise it.
            search (str): If ``'breadth'`` then the directory will be
                walked *top down*. Set to ``'depth'`` to walk *bottom up*.
            filter_dirs (list, optional): A list of patterns that will be used
                to match directories paths. The walk will only open directories
                that match at least one of these patterns.
            exclude_dirs (list): A list of patterns that will be used
                to filter out directories from the walk, e.g. ``['*.svn',
                '*.git']``.
            max_depth (int, optional): Maximum directory depth to walk.

        Returns:
            ~collections.Iterator: an iterator over directory paths
            (absolute from the filesystem root).

        This method invokes `Walker.dirs` with the bound `FS` object.

        r]   Nr0   )rz   rY   r>   r~   r0   r0   r1   rY   ~  s    zBoundWalker.dirsc                 K   r{   )a  Walk a filesystem, yielding path and `Info` of resources.

        Arguments:
            path (str): A path to a directory.
            namespaces (list, optional): A list of namespaces to include
                in the resource information, e.g. ``['basic', 'access']``
                (defaults to ``['basic']``).

        Keyword Arguments:
            ignore_errors (bool): If `True`, any errors reading a
                directory will be ignored, otherwise exceptions will be
                raised.
            on_error (callable): If ``ignore_errors`` is `False`, then
                this callable will be invoked with a path and the exception
                object. It should return `True` to ignore the error, or
                `False` to re-raise it.
            search (str): If ``'breadth'`` then the directory will be
                walked *top down*. Set to ``'depth'`` to walk *bottom up*.
            filter (list): If supplied, this parameter should be a list
                of file name patterns, e.g. ``['*.py']``. Files will only be
                returned if the final component matches one of the
                patterns.
            exclude (list, optional): If supplied, this parameter should be
                a list of filename patterns, e.g. ``['~*', '.*']``. Files matching
                any of these patterns will be removed from the walk.
            filter_dirs (list, optional): A list of patterns that will be used
                to match directories paths. The walk will only open directories
                that match at least one of these patterns.
            exclude_dirs (list): A list of patterns that will be used
                to filter out directories from the walk, e.g. ``['*.svn',
                '*.git']``.
            max_depth (int, optional): Maximum directory depth to walk.

        Returns:
            ~collections.Iterable: an iterable yielding tuples of
            ``(<absolute path>, <resource info>)``.

        This method invokes `Walker.info` with the bound `FS` object.

        rb   Nr0   )rz   rL   r>   r|   r0   r0   r1   rL     s   /zBoundWalker.inforn   ro   )r@   rp   rq   rr   r   r,   rB   rz   r\   __call__rZ   rY   rL   r0   r0   r0   r1   r=     s    
@

*%r=   )0rr   
__future__r   typingcollectionsr   r   r   _reprr   errorsr   r5   r	   r
   r   TYPE_CHECKINGr   r   r   r   r   r   r   r   r   r   baser   rL   r   	ExceptionboolOnErrorTypeVarr   r   objectr   Genericr=   default_walkerr\   rZ   
walk_files	walk_inforY   	walk_dirsr0   r0   r0   r1   <module>   s4    0
   ; o
