o
    Q `A!                     @   s   d dl mZ d dlmZ d dlZd dlZddlmZ ddlm	Z	 ddl
mZ ddlmZ ed	d
dgZedg dZedddgZejrZd dlmZmZmZmZmZmZ ddlmZ edZdddZdd Zdd ZG dd deZG dd deZ dS )     )unicode_literals)
namedtupleN   )LRUCache)	make_repr)iteratepath)wildcard	GlobMatchpathinfoCounts)filesdirectoriesdata
LineCountslines	non_blank)IteratorListOptionalPatternTextTuple)FSi  Tc                 C   s   d}d}dg}t | D ]}|dkr|d d}n|dtj||d  |d	7 }qd
d| | dr7dnd }||t||rEdfS tjfS )Nr   F z**z.*/?T/case_sensitiver   z(?ms)^z/$$)	r   appendr   Z
_translatejoinendswithrecompile
IGNORECASE)patternr   levels	recursiveZre_patternsZ	componentZre_glob r(   )/usr/lib/python3/dist-packages/fs/glob.py_translate_glob   s$   

 r*   c                 C   s\   zt | df \}}}W n ty&   t| dd\}}}|||ft | df< Y nw t||S )aA  Compare a glob pattern with a path (case sensitive).

    Arguments:
        pattern (str): A glob pattern.
        path (str): A path.

    Returns:
        bool: ``True`` if the path matches the pattern.

    Example:

        >>> from fs.glob import match
        >>> match("**/*.py", "/fs/glob.py")
        True

    Tr   _PATTERN_CACHEKeyErrorr*   boolmatchr%   r
   r&   r'   
re_patternr(   r(   r)   r/   0   s   r/   c                 C   s\   zt | df \}}}W n ty&   t| dd\}}}|||ft | df< Y nw t||S )zCompare a glob pattern with a path (case insensitive).

    Arguments:
        pattern (str): A glob pattern.
        path (str): A path.

    Returns:
        bool: ``True`` if the path matches the pattern.

    FTr   r+   r0   r(   r(   r)   imatchJ   s   r2   c                   @   sT   e Zd ZdZ				dddZdd Zdd
dZdd Zdd Zdd Z	dd Z
dS )Globbera  A generator of glob results.

        Arguments:
            fs (~fs.base.FS): A filesystem object
            pattern (str): A glob pattern, e.g. ``"**/*.py"``
            path (str): A path to a directory in the filesystem.
            namespaces (list): A list of additional info namespaces.
            case_sensitive (bool): If ``True``, the path matching will be
                case *sensitive* i.e. ``"FOO.py"`` and ``"foo.py"`` will
                be different, otherwise path matching will be case *insensitive*.
            exclude_dirs (list): A list of patterns to exclude when searching,
                e.g. ``["*.git"]``.

    r   NTc                 C   s(   || _ || _|| _|| _|| _|| _d S N)fsr%   r
   
namespacesr   exclude_dirs)selfr5   r%   r
   r6   r   r7   r(   r(   r)   __init__n   s   

zGlobber.__init__c              	   C   s6   t | jj| j| j| jdf| jd f| jdf| jd fdS )Nr   T)r
   r6   r   r7   )	r   	__class____name__r5   r%   r
   r6   r   r7   r8   r(   r(   r)   __repr__   s   zGlobber.__repr__breadthc                 c   s    zt | j| jf \}}}W n ty"   t| j| jd\}}}Y nw | jjj| j|p-| j	|r1d n||| j
dD ]\}}|jrC|d7 }||rNt||V  q8d S )Nr   )r
   r6   Z	max_depthsearchr7   r   )r,   r%   r   r-   r*   r5   walkr   r
   r6   r7   is_dirr/   r	   )r8   r?   r6   r&   r'   r1   r
   r   r(   r(   r)   
_make_iter   s.   


zGlobber._make_iterc                 C   s   |   S )z2An iterator of :class:`fs.glob.GlobMatch` objects.)rB   r<   r(   r(   r)   __iter__   s   zGlobber.__iter__c                 C   sT   d}d}d}| j dgdD ]\}}|jr|d7 }n|d7 }||j7 }qt|||dS )a3  Count files / directories / data in matched paths.

        Example:
            >>> import fs
            >>> fs.open_fs('~/projects').glob('**/*.py').count()
            Counts(files=18519, directories=0, data=206690458)

        Returns:
            `~Counts`: A named tuple containing results.

        r   Zdetails)r6   r   )r   r   r   )rB   rA   sizer   )r8   r   r   r   _pathr   r(   r(   r)   count   s   
zGlobber.countc                 C   sX   d}d}|   D ]\}}|jr%| j|dD ]}|d7 }| r$|d7 }qqt||dS )a.  Count the lines in the matched files.

        Returns:
            `~LineCounts`: A named tuple containing line counts.

        Example:
            >>> import fs
            >>> fs.open_fs('~/projects').glob('**/*.py').count_lines()
            LineCounts(lines=5767102, non_blank=4915110)

        r   rbr   )r   r   )rB   is_filer5   openrstripr   )r8   r   r   r
   r   liner(   r(   r)   count_lines   s   zGlobber.count_linesc                 C   sF   d}| j ddD ]\}}|jr| j| n| j| |d7 }q|S )zRemoved all matched paths.

        Returns:
            int: Number of file and directories removed.

        Example:
            >>> import fs
            >>> fs.open_fs('~/projects/my_project').glob('**/*.pyc').remove()
            29

        r   depth)r?   r   )rB   rA   r5   Z
removetreeremove)r8   Zremovesr
   r   r(   r(   r)   rN      s   
zGlobber.remover   NTN)r>   N)r;   
__module____qualname____doc__r9   r=   rB   rC   rF   rL   rN   r(   r(   r(   r)   r3   ^   s    

r3   c                   @   s2   e Zd ZdZdgZdd Zdd Z	dd
dZdS )BoundGlobberzA :class:`~Globber` object bound to a filesystem.

    An instance of this object is available on every Filesystem object
    as ``.glob``.

    Arguments:
        fs (FS): A filesystem object.

    r5   c                 C   s
   || _ d S r4   )r5   )r8   r5   r(   r(   r)   r9      s   
zBoundGlobber.__init__c                 C   s   t | jj| jS r4   )r   r:   r;   r5   r<   r(   r(   r)   r=      s   zBoundGlobber.__repr__r   NTc                 C   s   t | j|||||dS )a  Match resources on the bound filesystem againsts a glob pattern.

        Arguments:
            pattern (str): A glob pattern, e.g. ``"**/*.py"``
            namespaces (list): A list of additional info namespaces.
            case_sensitive (bool): If ``True``, the path matching will be
                case *sensitive* i.e. ``"FOO.py"`` and ``"foo.py"`` will
                be different, otherwise path matching will be case **insensitive**.
            exclude_dirs (list): A list of patterns to exclude when searching,
                e.g. ``["*.git"]``.

        Returns:
            `~Globber`:
                An object that may be queried for the glob matches.


        )r6   r   r7   )r3   r5   )r8   r%   r
   r6   r   r7   r(   r(   r)   __call__  s   zBoundGlobber.__call__rO   )r;   rP   rQ   rR   	__slots__r9   r=   rT   r(   r(   r(   r)   rS      s    
rS   )T)!Z
__future__r   collectionsr   r"   typingZlrucacher   Z_reprr   r
   r   r   r   r	   r   r   ZTYPE_CHECKINGr   r   r   r   r   r   baser   r,   r*   r/   r2   objectr3   rS   r(   r(   r(   r)   <module>   s.     
 