B
    ܇\/%                 @   s  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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 d dlmZ d dlZd dlmZ dd	lmZ erd d
lmZmZ nd d
lmZmZ ddgZdZeddZdd Zd9ddZ dd Z!dd Z"dd Z#dd Z$ej%r2dd Z&ne'Z&dd  Z(d!d" Z)d#d$ Z*e j+fd%d&Z,d'd( Z-d)d* Z.d+d, Z/d-d. Z0d/d0 Z1d1d2 Z2d3d4 Z3d5d6 Z4d7d8 Z5dS ):    N)reduce)
expanduser)
expandvars)isabs)sep)map   )PY36)PathPurePathr
   r   i0*  joinpathz.lockc             C   s    |   rt| dd |   dS )z6
    ensures the given path is an empty directory
    T)forceN)existsrmtreemkdir)path r   .lib/python3.7/site-packages/_pytest/pathlib.pyensure_reset_dir#   s    r   Fc             C   s*   |rt jt| dd nt t|  d S )NT)ignore_errors)shutilr   str)r   r   r   r   r   r   ,   s    r   c             c   s4   |  }x&|  D ]}|j  |r|V  qW dS )zGfinds all elements in root that begin with the prefix, case insensitiveN)lowerZiterdirname
startswith)rootprefixZl_prefixxr   r   r   find_prefixed5   s    r   c             c   s*   t |}x| D ]}|j|d V  qW dS )z
    :param iter: iterator over path names
    :param prefix: expected prefix of the path names
    :returns: the parts of the paths following the prefix
    N)lenr   )iterr   Zp_lenpr   r   r   extract_suffixes=   s    
r"   c             C   s   t t| ||S )z0combines find_prefixes and extract_suffixes
    )r"   r   )r   r   r   r   r   find_suffixesH   s    r#   c             C   s"   yt | S  tk
r   dS X dS )z0parses number path suffixes, returns -1 on errorN)int
ValueError)Z	maybe_numr   r   r   	parse_numN   s    r'   c             C   s   t t| |S )z<needed due to python2.7 lacking the default argument for max)r   max)iterabledefaultr   r   r   _maxX   s    r+   c             C   sT   |  |}y|  W n tk
r*   Y nX y|| W n tk
rN   Y nX dS )a  helper to create the current symlink

    it's full of race conditions that are reasonably ok to ignore
    for the context of best effort linking to the latest testrun

    the presumption being thatin case of much parallelism
    the inaccuracy is going to be acceptable
    N)r   unlinkOSErrorZ
symlink_to	Exception)r   targetZlink_toZcurrent_symlinkr   r   r   _force_symlinka   s    	
r0   c          	   C   s   xt dD ]l}tttt| |dd}|d }| d||}y|  W n tk
r`   Y q
X t	| |d | |S q
W t
dj|| dd	S )
zJcreate a directory with an increased number as suffix for the given prefix
   r$   )r*   r   z{}{}ZcurrentzKcould not create numbered dir with prefix {prefix} in {root} after 10 tries)r   r   N)ranger+   r   r'   r#   r   formatr   r.   r0   EnvironmentError)r   r   imax_existingZ
new_numbernew_pathr   r   r   make_numbered_diru   s    r8   c          
   C   s   t | }y$tt|tjtjB tjB d}W nJ tk
rv } z,|jtj	krdt
tdj| d| n W dd}~X Y nPX t }t|}t|ts|d}t|| t| | std|S dS )z1crates a lock to prevent premature folder cleanupi  z cannot create lockfile in {path})r   Nasciiz/lock path got renamed after successful creation)get_lock_pathosopenr   O_WRONLYO_CREATO_EXCLr-   errnoZEEXISTsixZ
raise_fromr4   r3   getpid
isinstancebytesencodewritecloseis_file)r!   	lock_pathfdepidZspidr   r   r   create_cleanup_lock   s"    $


rM   c             C   s   t  }| |fdd}||S )zFregisters a cleanup function for removing a lock, by default on atexitc          	   S   s>   t  }||krd S y|   W n ttfk
r8   Y nX d S )N)r;   rB   r,   r-   IOError)rI   Zoriginal_pidZcurrent_pidr   r   r   cleanup_on_exit   s    z6register_cleanup_lock_removal.<locals>.cleanup_on_exit)r;   rB   )rI   registerrL   rO   r   r   r   register_cleanup_lock_removal   s    
rQ   c             C   s   d}zZy<t | }| j}|dt }| | t|dd W n tt	fk
rZ   dS X W d|dk	ry|
  W n ttfk
r   Y nX X dS )zZremoves a numbered directory if its lock can be obtained and it does not seem to be in useNz
garbage-{}T)r   )rM   parentr   r3   uuidZuuid4renamer   r-   r4   r,   rN   )r   rI   rR   Zgarbager   r   r   maybe_delete_a_numbered_dir   s    

rU   c             C   s`   |   rdS t| }| s dS y| j}W n tk
rB   dS X ||k rX|  dS dS dS )z<checks if a lock exists and breaks it if its considered deadFTN)
is_symlinkr:   r   statst_mtimer.   r,   )r   $consider_lock_dead_if_created_beforelockZ	lock_timer   r   r   ensure_deletable   s    r[   c             C   s   t | |rt|  dS )z9tries to cleanup a folder if we can ensure it's deletableN)r[   rU   )r   rY   r   r   r   try_cleanup   s    
r\   c       
      c   sr   t ttt| |dd}|| }t| |}t|\}}ttt||}x$t||D ]\}}	|	|krT|V  qTW dS )zIlists candidates for numbered directories to be removed - follows py.pathr$   )r*   N)	r+   r   r'   r#   r   	itertoolsteer"   zip)
r   r   keepr6   Z
max_deletepathsZpaths2Znumbersr   Znumberr   r   r   cleanup_candidates   s    
rb   c             C   sB   xt | ||D ]}t|| qW x| dD ]}t|| q,W dS )z,cleanup for lock driven numbered directoriesz	garbage-*N)rb   r\   Zglob)r   r   r`   rY   r   r   r   r   cleanup_numbered_dir   s    rc   c       
      C   s   d}xxt dD ]l}yt| |}t|}t| W n& tk
rV } z|}W dd}~X Y qX | j| }	t| |||	d |S qW |dk	st|dS )z?creates a numbered dir with a cleanup lock and removes old onesNr1   )r   r   r`   rY   )	r2   r8   rM   rQ   r.   rW   rX   rc   AssertionError)
r   r   r`   Zlock_timeoutrK   r5   r!   rI   excrY   r   r   r   make_numbered_dir_with_cleanup   s"    
rf   c             C   sH   t | trtdt|}t| } t| } t| r:t| S || S d S )Nzwould break on py2)rC   r
   rd   r   r   r   r   )inputr   r   r   r   resolve_from_str  s    rh   c             C   sZ   t |}tjd}|r4t| kr4t| kr4| tt} t| krD|j}n
t	|}t

|| S )a  FNMatcher port from py.path.common which works with PurePath() instances.

    The difference between this algorithm and PurePath.match() is that the latter matches "**" glob expressions
    for each part of the path, while this algorithm uses the whole path instead.

    For example:
        "tests/foo/bar/doc/test_foo.py" matches pattern "tests/**/doc/test*.py" with this algorithm, but not with
        PurePath.match().

    This algorithm was ported to keep backward-compatibility with existing settings which assume paths match according
    this logic.

    References:
    * https://bugs.python.org/issue29249
    * https://bugs.python.org/issue34731
    win)r   sysplatformr   r   	posix_sepreplacer   rA   Z	text_typefnmatch)patternr   Ziswin32r   r   r   r   
fnmatch_ex  s    
rp   c                s$   |  t  fddtt D S )Nc                s&   h | ]}t  d |d  p t qS )Nr   )r   join).0r5   )partsr   r   	<setcomp>?  s    zparts.<locals>.<setcomp>)splitr   r2   r   )sr   )rs   r   rs   =  s    
rs   )F)6atexitr@   rn   r]   operatorr;   r   rj   rS   	functoolsr   os.pathr   r   r   r   	posixpathrl   rA   Z	six.movesr   compatr	   Zpathlibr
   r   Zpathlib2__all__ZLOCK_TIMEOUTmethodcallerr:   r   r   r   r"   r#   r'   ZPY2r+   r(   r0   r8   rM   rP   rQ   rU   r[   r\   rb   rc   rf   rh   rp   rs   r   r   r   r   <module>   sZ   	
	
!