B
    Khh1O                 @   s  d Z ddlZddlZddlZddlZddlZddlZddlZddlm	Z
mZ ddlmZ ddlmZmZ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 ejdkreeee f Zneeef Zd	d
 ejejgD Z i Z!ej"edddZ#d;ee ee ee$ eedf dddZ%ee ee dddZ&ee$dddZ'd<eee ee$ ed dddZ(eeeeef ee$ed dddZ)d=eee ee$ ee ddd Z*d>d!d"Z+eeegef d#d$d%Z,ee ee$d&d'd(Z-ee ee ee d)d*d+Z.d?eee	e  ed,d-d.Z/d@ee ee	e  eeee f d/d0d1Z0dAeeegef ee$ dd2d3d4Z1G d5d6 d6e2Z3G d7d8 d8e2Z4G d9d de5Z6G d:d de5Z7dS )BzC
This module provides utility methods for dealing with path-specs.
    N)
CollectionIterable)PathLike)AnyAnyStrCallabler   Dictr   IteratorListOptionalSequenceSetUnion   )Pattern)   	   c             C   s   g | ]}|r|t jkr|qS  )	posixpathsep).0Z__sepr   r   3/tmp/pip-install-vv81h98y/pathspec/pathspec/util.py
<listcomp>(   s   r   )pathreturnc             C   s   t | }|  r|tj7 }|S )a5  
	Appends the path separator to the path if the path is a directory.
	This can be used to aid in distinguishing between directories and
	files on the file-system by relying on the presence of a trailing path
	separator.

	*path* (:class:`pathlib.path`) is the path to use.

	Returns the path (:class:`str`).
	)stris_dirosr   )r   Zstr_pathr   r   r   append_dir_sep:   s    
r   MatchDetail)patternsfilesall_matchesr   c       	      C   s   t |tr|nt|}i }x| D ]~}|jdk	r ||}|jrx^|D ]@}||krv|rf|| j| q||| jd< qDt|g||< qDW q x|D ]
}||= qW q W |S )a  
	Matches the files to the patterns, and returns which patterns matched
	the files.

	*patterns* (:class:`~collections.abc.Iterable` of :class:`~pathspec.pattern.Pattern`)
	contains the patterns to use.

	*files* (:class:`~collections.abc.Iterable` of :class:`str`) contains
	the normalized file paths to be matched against *patterns*.

	*all_matches* (:class:`boot` or :data:`None`) is whether to return all
	matches patterns (:data:`True`), or only the last matched pattern
	(:data:`False`). Default is :data:`None` for :data:`False`.

	Returns the matched files (:class:`dict`) which maps each matched file
	(:class:`str`) to the patterns that matched in order (:class:`.MatchDetail`).
	Nr   )
isinstanceCollectionTypelistincludematchr    appendr   )	r    r!   r"   Z	all_filesreturn_filespatternZresult_filesZresult_filefiler   r   r   detailed_match_filesL   s    




r,   )r    r   c             C   s   dd | D S )z
	Filters out null-patterns.

	*patterns* (:class:`Iterable` of :class:`.Pattern`) contains the
	patterns.

	Returns the patterns (:class:`list` of :class:`.Pattern`).
	c             S   s   g | ]}|j d k	r|qS )N)r&   )r   Z__patr   r   r   r      s   z$_filter_patterns.<locals>.<listcomp>r   )r    r   r   r   _filter_patternsz   s    
r-   )valuer   c             C   s   t | tot | ttf S )z
	Check whether the value is an iterable (excludes strings).

	*value* is the value to check,

	Returns whether *value* is a iterable (:class:`bool`).
	)r#   IterableTyper   bytes)r.   r   r   r   _is_iterable   s    r1   	TreeEntry)rooton_errorfollow_linksr   c             c   sN   |dk	r t |s td|d|dkr,d}ttj| di ||E dH  dS )a  
	Walks the specified directory for all files and directories.

	*root* (:class:`str` or :class:`os.PathLike[str]`) is the root directory to
	search.

	*on_error* (:class:`~collections.abc.Callable` or :data:`None`)
	optionally is the error handler for file-system exceptions. It will be
	called with the exception (:exc:`OSError`). Reraise the exception to
	abort the walk. Default is :data:`None` to ignore file-system
	exceptions.

	*follow_links* (:class:`bool` or :data:`None`) optionally is whether
	to walk symbolic links that resolve to directories. Default is
	:data:`None` for :data:`True`.

	Raises :exc:`RecursionError` if recursion is detected.

	Returns an :class:`~collections.abc.Iterator` yielding each file or
	directory entry (:class:`.TreeEntry`) relative to *root*.
	Nz	on_error:z is not callable.T )callable	TypeError_iter_tree_entries_nextr   r   abspath)r3   r4   r5   r   r   r   iter_tree_entries   s
    r;   )	root_fulldir_relmemor4   r5   r   c             c   st  t j| |}t j|}||kr,|||< nt||| |dt |}x|D ]}t j||j}	y|jdd}
W n4 tk
r } z|dk	r|| wTW dd}~X Y nX |	 ry| }W n4 tk
r } z|dk	r|| wTW dd}~X Y nX n|
}|j
|dr8t|j|	|
|V  t| |	|||E dH  qT| sJ|	 rTt|j|	|
|V  qTW W dQ R X ||= dS )aq  
	Scan the directory for all descendant files.

	*root_full* (:class:`str`) the absolute path to the root directory.

	*dir_rel* (:class:`str`) the path to the directory to scan relative to
	*root_full*.

	*memo* (:class:`dict`) keeps track of ancestor directories
	encountered. Maps each ancestor real path (:class:`str`) to relative
	path (:class:`str`).

	*on_error* (:class:`~collections.abc.Callable` or :data:`None`)
	optionally is the error handler for file-system exceptions.

	*follow_links* (:class:`bool`) is whether to walk symbolic links that
	resolve to directories.

	Yields each entry (:class:`.TreeEntry`).
	)	real_path
first_pathsecond_pathF)follow_symlinksN)r   r   joinrealpathRecursionErrorscandirnamestatOSError
is_symlinkr   r2   r9   is_file)r<   r=   r>   r4   r5   Zdir_fullZdir_realZ	scan_iterZnode_entZnode_relZ
node_lstate	node_statr   r   r   r9      s8    
 r9   c             c   s.   x(t | ||dD ]}||s|jV  qW dS )a   
	Walks the specified directory for all files.

	*root* (:class:`str` or :class:`os.PathLike[str]`) is the root directory to
	search for files.

	*on_error* (:class:`~collections.abc.Callable` or :data:`None`)
	optionally is the error handler for file-system exceptions. It will be
	called with the exception (:exc:`OSError`). Reraise the exception to
	abort the walk. Default is :data:`None` to ignore file-system
	exceptions.

	*follow_links* (:class:`bool` or :data:`None`) optionally is whether
	to walk symbolic links that resolve to directories. Default is
	:data:`None` for :data:`True`.

	Raises :exc:`RecursionError` if recursion is detected.

	Returns an :class:`~collections.abc.Iterator` yielding the path to
	each file (:class:`str`) relative to *root*.
	)r4   r5   N)r;   r   r   )r3   r4   r5   entryr   r   r   iter_tree_files	  s    
rO   c             C   s   t jdtdd t| ||dS )zg
	DEPRECATED: The :func:`.iter_tree` function is an alias for the
	:func:`.iter_tree_files` function.
	zCutil.iter_tree() is deprecated. Use util.iter_tree_files() instead.   )
stacklevel)r4   r5   )warningswarnDeprecationWarningrO   )r3   r4   r5   r   r   r   	iter_tree(  s    
rU   )rG   r   c             C   s   t |  S )z
	Lookups a registered pattern factory by name.

	*name* (:class:`str`) is the name of the pattern factory.

	Returns the registered pattern factory (:class:`~collections.abc.Callable`).
	If no pattern factory is registered, raises :exc:`KeyError`.
	)_registered_patterns)rG   r   r   r   lookup_pattern3  s    	rW   )r    r+   r   c             C   s4   d}x*| D ]"}|j dk	r
||dk	r
|j }q
W |S )a7  
	Matches the file to the patterns.

	*patterns* (:class:`~collections.abc.Iterable` of :class:`~pathspec.pattern.Pattern`)
	contains the patterns to use.

	*file* (:class:`str`) is the normalized file path to be matched
	against *patterns*.

	Returns :data:`True` if *file* matched; otherwise, :data:`False`.
	FN)r&   
match_file)r    r+   matchedr*   r   r   r   rX   ?  s    


rX   )r    r!   r   c             C   sD   t jdtdd t| }t }x |D ]}t||r$|| q$W |S )a  
	DEPRECATED: This is an old function no longer used. Use the :func:`.match_file`
	function with a loop for better results.

	Matches the files to the patterns.

	*patterns* (:class:`~collections.abc.Iterable` of :class:`~pathspec.pattern.Pattern`)
	contains the patterns to use.

	*files* (:class:`~collections.abc.Iterable` of :class:`str`) contains
	the normalized file paths to be matched against *patterns*.

	Returns the matched files (:class:`set` of :class:`str`).
	zWutil.match_files() is deprecated. Use util.match_file() with a loop for better results.rP   )rQ   )rR   rS   rT   r-   setrX   add)r    r!   Zuse_patternsr)   r+   r   r   r   match_filesT  s    


r\   )r+   
separatorsr   c             C   sd   |dkrt }t| }x|D ]}||tj}qW |drJ|dd }n|dr`|dd }|S )a  
	Normalizes the file path to use the POSIX path separator (i.e.,
	:data:`'/'`), and make the paths relative (remove leading :data:`'/'`).

	*file* (:class:`str` or :class:`os.PathLike[str]`) is the file path.

	*separators* (:class:`~collections.abc.Collection` of :class:`str`; or
	:data:`None`) optionally contains the path separators to normalize.
	This does not need to include the POSIX path separator (:data:`'/'`),
	but including it will not affect the results. Default is :data:`None`
	for :data:`NORMALIZE_PATH_SEPS`. To prevent normalization, pass an
	empty container (e.g., an empty tuple :data:`()`).

	Returns the normalized file path (:class:`str`).
	N/r   z./rP   )NORMALIZE_PATH_SEPSr   fspathreplacer   r   
startswith)r+   r]   	norm_filer   r   r   r   normalize_fileu  s    



rd   )r!   r]   r   c             C   sT   t jdtdd i }x:| D ]2}t||d}||krB|| | q|g||< qW |S )a  
	DEPRECATED: This function is no longer used. Use the :func:`.normalize_file`
	function with a loop for better results.

	Normalizes the file paths to use the POSIX path separator.

	*files* (:class:`~collections.abc.Iterable` of :class:`str` or
	:class:`os.PathLike[str]`) contains the file paths to be normalized.

	*separators* (:class:`~collections.abc.Collection` of :class:`str`; or
	:data:`None`) optionally contains the path separators to normalize.
	See :func:`normalize_file` for more information.

	Returns a :class:`dict` mapping each normalized file path (:class:`str`)
	to the original file paths (:class:`list` of :class:`str` or
	:class:`os.PathLike[str]`).
	z_util.normalize_files() is deprecated. Use util.normalize_file() with a loop for better results.rP   )rQ   )r]   )rR   rS   rT   rd   r(   )r!   r]   Z
norm_filesr   rc   r   r   r   normalize_files  s    

re   )rG   pattern_factoryoverrider   c             C   sX   t | tstd| dt|s2td|d| tkrL|sLt| t|  |t| < dS )aE  
	Registers the specified pattern factory.

	*name* (:class:`str`) is the name to register the pattern factory
	under.

	*pattern_factory* (:class:`~collections.abc.Callable`) is used to
	compile patterns. It must accept an uncompiled pattern (:class:`str`)
	and return the compiled pattern (:class:`.Pattern`).

	*override* (:class:`bool` or :data:`None`) optionally is whether to
	allow overriding an already registered pattern under the same name
	(:data:`True`), instead of raising an :exc:`AlreadyRegisteredError`
	(:data:`False`). Default is :data:`None` for :data:`False`.
	zname:z is not a string.zpattern_factory:z is not callable.N)r#   r   r8   r7   rV   AlreadyRegisteredError)rG   rf   rg   r   r   r   register_pattern  s    
ri   c                   st   e Zd ZdZeeegef dd fddZe	edddZ
e	edd	d
Ze	eegef dddZ  ZS )rh   z|
	The :exc:`AlreadyRegisteredError` exception is raised when a pattern
	factory is registered under a name already in use.
	N)rG   rf   r   c                s   t t| || dS )z
		Initializes the :exc:`AlreadyRegisteredError` instance.

		*name* (:class:`str`) is the name of the registered pattern.

		*pattern_factory* (:class:`~collections.abc.Callable`) is the
		registered pattern factory.
		N)superrh   __init__)selfrG   rf   )	__class__r   r   rk     s    zAlreadyRegisteredError.__init__)r   c             C   s   dj | j| jdS )z4
		*message* (:class:`str`) is the error message.
		zG{name!r} is already registered for pattern factory:{pattern_factory!r}.)rG   rf   )formatrG   rf   )rl   r   r   r   message  s    zAlreadyRegisteredError.messagec             C   s
   | j d S )zB
		*name* (:class:`str`) is the name of the registered pattern.
		r   )args)rl   r   r   r   rG     s    zAlreadyRegisteredError.namec             C   s
   | j d S )za
		*pattern_factory* (:class:`~collections.abc.Callable`) is the
		registered pattern factory.
		r   )rp   )rl   r   r   r   rf     s    z&AlreadyRegisteredError.pattern_factory)__name__
__module____qualname____doc__r   r   r   r   rk   propertyro   rG   rf   __classcell__r   r   )rm   r   rh     s   	rh   c                   st   e Zd ZdZeeedd fddZeedddZeedd	d
ZeedddZ	eedddZ
  ZS )rE   zN
	The :exc:`RecursionError` exception is raised when recursion is
	detected.
	N)r?   r@   rA   r   c                s   t t| ||| dS )a+  
		Initializes the :exc:`RecursionError` instance.

		*real_path* (:class:`str`) is the real path that recursion was
		encountered on.

		*first_path* (:class:`str`) is the first path encountered for
		*real_path*.

		*second_path* (:class:`str`) is the second path encountered for
		*real_path*.
		N)rj   rE   rk   )rl   r?   r@   rA   )rm   r   r   rk     s    zRecursionError.__init__)r   c             C   s
   | j d S )zx
		*first_path* (:class:`str`) is the first path encountered for
		:attr:`self.real_path <RecursionError.real_path>`.
		r   )rp   )rl   r   r   r   r@   +  s    zRecursionError.first_pathc             C   s   dj | j| j| jdS )z4
		*message* (:class:`str`) is the error message.
		zDReal path {real!r} was encountered at {first!r} and then {second!r}.)realfirstsecond)rn   r?   r@   rA   )rl   r   r   r   ro   3  s    zRecursionError.messagec             C   s
   | j d S )zV
		*real_path* (:class:`str`) is the real path that recursion was
		encountered on.
		r   )rp   )rl   r   r   r   r?   >  s    zRecursionError.real_pathc             C   s
   | j d S )zz
		*second_path* (:class:`str`) is the second path encountered for
		:attr:`self.real_path <RecursionError.real_path>`.
		rP   )rp   )rl   r   r   r   rA   F  s    zRecursionError.second_path)rq   rr   rs   rt   r   rk   ru   r@   ro   r?   rA   rv   r   r   )rm   r   rE     s   
rE   c               @   s(   e Zd ZdZdZee ddddZdS )r   z>
	The :class:`.MatchDetail` class contains information about
	)r    N)r    r   c             C   s
   || _ dS )z
		Initialize the :class:`.MatchDetail` instance.

		*patterns* (:class:`~collections.abc.Sequence` of :class:`~pathspec.pattern.Pattern`)
		contains the patterns that matched the file in the order they were
		encountered.
		N)r    )rl   r    r   r   r   rk   W  s    	zMatchDetail.__init__)rq   rr   rs   rt   	__slots__r   r   rk   r   r   r   r   r   O  s   c               @   s   e Zd ZdZdZeeejejddddZde	e
 e
ddd	Zde	e
 e
dd
dZe
dddZde	e
 ejdddZdS )r2   zR
	The :class:`.TreeEntry` class contains information about a file-system
	entry.
	)_lstatrG   r   _statN)rG   r   lstatrH   r   c             C   s   || _ || _|| _|| _dS )aP  
		Initialize the :class:`.TreeEntry` instance.

		*name* (:class:`str`) is the base name of the entry.

		*path* (:class:`str`) is the relative path of the entry.

		*lstat* (:class:`os.stat_result`) is the stat result of the direct
		entry.

		*stat* (:class:`os.stat_result`) is the stat result of the entry,
		potentially linked.
		N)r{   rG   r   r|   )rl   rG   r   r}   rH   r   r   r   rk   q  s
    zTreeEntry.__init__)r5   r   c             C   s(   |dkrd}|r| j n| j}t|jS )a<  
		Get whether the entry is a directory.

		*follow_links* (:class:`bool` or :data:`None`) is whether to follow
		symbolic links. If this is :data:`True`, a symlink to a directory
		will result in :data:`True`. Default is :data:`None` for :data:`True`.

		Returns whether the entry is a directory (:class:`bool`).
		NT)r|   r{   rH   S_ISDIRst_mode)rl   r5   rM   r   r   r   r     s    
zTreeEntry.is_dirc             C   s(   |dkrd}|r| j n| j}t|jS )aE  
		Get whether the entry is a regular file.

		*follow_links* (:class:`bool` or :data:`None`) is whether to follow
		symbolic links. If this is :data:`True`, a symlink to a regular file
		will result in :data:`True`. Default is :data:`None` for :data:`True`.

		Returns whether the entry is a regular file (:class:`bool`).
		NT)r|   r{   rH   S_ISREGr   )rl   r5   rM   r   r   r   rK     s    
zTreeEntry.is_file)r   c             C   s   t | jjS )zC
		Returns whether the entry is a symbolic link (:class:`bool`).
		)rH   S_ISLNKr{   r   )rl   r   r   r   rJ     s    zTreeEntry.is_symlinkc             C   s   |dkrd}|r| j S | jS )a9  
		Get the cached stat result for the entry.

		*follow_links* (:class:`bool` or :data:`None`) is whether to follow
		symbolic links. If this is :data:`True`, the stat result of the
		linked file will be returned. Default is :data:`None` for :data:`True`.

		Returns that stat result (:class:`os.stat_result`).
		NT)r|   r{   )rl   r5   r   r   r   rH     s    
zTreeEntry.stat)N)N)N)rq   rr   rs   rt   rz   r   r   stat_resultrk   r   boolr   rK   rJ   rH   r   r   r   r   r2   h  s   %)N)NN)NN)NN)N)N)N)8rt   r   os.pathZpathlibr   rH   sysrR   collections.abcr   r$   r   r/   r   typingr   r   r   r   r	   r
   r   r   r   r   r*   r   version_infor   ZStrPathr   altsepr_   rV   Pathr   r   r,   r-   r1   r;   r9   rO   rU   rW   rX   r\   rd   re   ri   	Exceptionrh   rE   objectr   r2   r   r   r   r   <module>   sd   8

*  
M 
 '%/>