
    obP!                     6   d 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 dd	lmZ  ed
ddg      Z edg d      Z edddg      Zej$                  rddlmZmZmZmZmZmZ ddlmZ  ed      ZddZd Zd Z G d de      Z  G d de      Z!y)z1Useful functions for working with glob patterns.
    )unicode_literalsN)
namedtuple   )wildcard)	make_repr)LRUCache)iteratepath	GlobMatchpathinfoCounts)filesdirectoriesdata
LineCountslines	non_blank)IteratorListOptionalPatternTextTuple)FSi  c                 r   d}d}dg}t        |       D ]I  }|dk(  r|j                  d       d}n)|j                  dt        j                  ||      z          |d	z  }K d
dj	                  |      z   | j                  d      rdndz   }||t        j                  ||rd      fS t        j                        fS )Nr   F z**z.*/?T/case_sensitiver   z(?ms)^z/$$)	r	   appendr   
_translatejoinendswithrecompile
IGNORECASE)patternr   levels	recursivere_patterns	componentre_globs          )/usr/lib/python3/dist-packages/fs/glob.py_translate_globr/      s    FI$K ) 	v&Ih)))NSS 	! --9I9I#9NTWXG


7AC  68]]C     c                     	 t         | df   \  }}}t        |j	                  |            S # t        $ r" t        | d      \  }}}|||ft         | df<   Y Dw xY w)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_patterns        r.   r6   r6   4   sq    $J(6(G%	: 
  &''  J(7PT(U%	:+19j*I'J   + (AAc                     	 t         | df   \  }}}t        |j	                  |            S # t        $ r" t        | d      \  }}}|||ft         | df<   Y Dw xY w)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   r2   r7   s        r.   imatchr;   N   ss    K(67G(H%	: 
  &''  K(7PT(U%	:,2Iz+J'(Kr9   c                   F    e Zd ZdZ	 	 	 	 d
dZd ZddZd Zd Zd Z	d	 Z
y)GlobberzA generator of glob results.Nc                 X    || _         || _        || _        || _        || _        || _        y)a  Create a new Globber instance.

        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"]``.

        N)fsr(   r   
namespacesr   exclude_dirs)selfr?   r(   r   r@   r   rA   s          r.   __init__zGlobber.__init__e   s0    0 	$,(r0   c           
          t        | j                  j                  | j                  | j                  | j
                  df| j                  d f| j                  df| j                  d f      S )Nr   T)r   r@   r   rA   )	r   	__class____name__r?   r(   r   r@   r   rA   rB   s    r.   __repr__zGlobber.__repr__   s^    NN##GGLL))S!. //6++T2
 	
r0   c              #     K   	 t         | j                  | j                  f   \  }}}| j
                  j                  j                  | j                  |xs | j                  |rd n||| j                        D ]6  \  }}|j                  r|dz  }|j                  |      s)t        ||       8 y # t        $ r( t	        | j                  | j                        \  }}}Y w xY ww)Nr   )r   r@   	max_depthsearchrA   r   )r3   r(   r   r4   r/   r?   walkr   r   r@   rA   is_dirr6   r
   )rB   rK   r@   r)   r*   r8   r   r   s           r.   
_make_iterzGlobber._make_iter   s     	,:t223-)FIz '',,++!4T__'dV** , 
 
	,JD$ {{%d++
	,  	,;T-@-@-)FIz	s.   C%#B1 A8C% C%1.C"C%!C""C%c                 "    | j                         S )z6Get an iterator of :class:`fs.glob.GlobMatch` objects.)rN   rG   s    r.   __iter__zGlobber.__iter__   s       r0   c                     d}d}d}| j                  dg      D ]+  \  }}|j                  r|dz  }n|dz  }||j                  z  }- t        |||      S )zCount files / directories / data in matched paths.

        Example:
            >>> my_fs.glob('**/*.py').count()
            Counts(files=2, directories=0, data=55)

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

        r   details)r@   r   )r   r   r   )rN   rM   sizer   )rB   r   r   r   _pathr   s         r.   countzGlobber.count   sl     ??yk?B 	KE4{{q 
DIID	 +UFFr0   c                     d}d}| j                         D ]N  \  }}|j                  s| j                  j                  |d      D ]  }|dz  }|j	                         s|dz  } P t        ||      S )zCount the lines in the matched files.

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

        Example:
            >>> my_fs.glob('**/*.py').count_lines()
            LineCounts(lines=4, non_blank=3)

        r   rbr   )r   r   )rN   is_filer?   openrstripr   )rB   r   r   r   r   lines         r.   count_lineszGlobber.count_lines   sw     	//+ 	'JD$|| GGLLt4 'DQJE{{}!Q	'	' ;;r0   c                     d}| j                  d      D ]M  \  }}|j                  r| j                  j                  |       n| j                  j	                  |       |dz  }O |S )zRemove all matched paths.

        Returns:
            int: Number of file and directories removed.

        Example:
            >>> my_fs.glob('**/*.pyc').remove()
            2

        r   depth)rK   r   )rN   rM   r?   
removetreeremove)rB   removesr   r   s       r.   r`   zGlobber.remove   s`     ///9 	JD${{""4(t$qLG	 r0   r   NTN)breadthN)rF   
__module____qualname____doc__rC   rH   rN   rP   rU   r\   r`    r0   r.   r=   r=   b   s7    & )>	
,.!
G.<,r0   r=   c                   ,    e Zd ZdZdgZd Zd Z	 ddZy)BoundGlobberzA `~fs.glob.Globber` object bound to a filesystem.

    An instance of this object is available on every Filesystem object
    as the `~fs.base.FS.glob` property.

    r?   c                     || _         y)znCreate a new bound Globber.

        Arguments:
            fs (FS): A filesystem object to bind to.

        N)r?   )rB   r?   s     r.   rC   zBoundGlobber.__init__   s     r0   c                 V    t        | j                  j                  | j                        S )N)r   rE   rF   r?   rG   s    r.   rH   zBoundGlobber.__repr__  s    00$''::r0   Nc                 8    t        | j                  |||||      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.

        )r@   r   rA   )r=   r?   )rB   r(   r   r@   r   rA   s         r.   __call__zBoundGlobber.__call__  s'    & GG!)%
 	
r0   rb   )rF   rd   re   rf   	__slots__rC   rH   rm   rg   r0   r.   ri   ri      s&     I; UY
r0   ri   )T)"rf   
__future__r   typingr%   collectionsr   r   r   _reprr   lrucacher   r   r	   r
   r   r   TYPE_CHECKINGr   r   r   r   r   r   baser   r3   r/   r6   r;   objectr=   ri   rg   r0   r.   <module>rw      s    (  	 "    {VV$45		H>	?w&<=
	EE 
*(4((If IX1
6 1
r0   