3

g9\                 @   s|  d dl m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mZ d dlmZ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 d d	lm Z m!Z! d d
l"m#Z# e#r
d dl$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z- d dl.m/Z/ ej0e1Z2dd Z3dd Z4e4dd Z5dd Z6dd Z7dd Z8G dd de9Z:G dd de9Z;G dd de9Z<dS )    )absolute_importN)pkg_resources)UninstallationError)bin_pybin_user)WINDOWScache_from_sourceuses_pycache)
indent_log)	FakeFileaskdist_in_usersitedist_is_localegg_link_pathis_localnormalize_pathrenamesrmtree)AdjacentTempDirectoryTempDirectory)MYPY_CHECK_RUNNING)	AnyCallableDictIterableIteratorListOptionalSetTuple)Distributionc             C   sl   t | rt}nt}tjj||}|g}trh|j|d  |j|d  |rZ|j|d  n|j|d  |S )zCreate the fully qualified name of the files created by
    {console,gui}_scripts for the given ``dist``.
    Returns the list of file names
    z.exez.exe.manifestz-script.pywz
-script.py)r   r   r   ospathjoinr   append)distscript_nameis_guibin_direxe_namepaths_to_remove r+   C/tmp/pip-unpacked-wheel-v59g9nu1/pip/_internal/req/req_uninstall.py_script_names'   s    r-   c                s   t j  fdd}|S )Nc              ?   s6   t  }x* | |D ]}||kr|j| |V  qW d S )N)setadd)argskwseenitem)fnr+   r,   unique?   s
    
z_unique.<locals>.unique)	functoolswraps)r4   r5   r+   )r4   r,   _unique=   s    r8   c             c   s   t jt| jd}x||D ]t}tjj| j|d }|V  |jdrtjj	|\}}|dd }tjj||d }|V  tjj||d }|V  qW dS )	a  
    Yield all the uninstallation paths for dist based on RECORD-without-.py[co]

    Yield paths to all the files in RECORD. For each .py file in RECORD, add
    the .pyc and .pyo in the same directory.

    UninstallPathSet.add() takes care of the __pycache__ .py[co].
    RECORDr   z.pyN   z.pycz.pyo)
csvreaderr   get_metadata_linesr!   r"   r#   locationendswithsplit)r%   rrowr"   dnr4   baser+   r+   r,   uninstallation_pathsJ   s    

rF   c                sN   t jjt }x:t| tdD ]* t fdd|D }|s|j  qW |S )zCompact a path set to contain the minimal number of paths
    necessary to contain all paths in the set. If /a/path/ and
    /a/path/to/a/file.txt are both in the set, leave only the
    shorter path.)keyc             3   s:   | ]2} j |jd o0 t|jd j kV  qdS )*N)
startswithrstriplen).0	shortpath)r"   sepr+   r,   	<genexpr>m   s   zcompact.<locals>.<genexpr>)r!   r"   rN   r.   sortedrK   anyr/   )pathsshort_pathsshould_skipr+   )r"   rN   r,   compactb   s    
rU   c       	         s   t dd | D }t|}ttdd |j D td}t }dd x|D ]tfdd|D rhqLt }t }xPtjD ]B\ }}|j fdd|D  |j fd	d|D  qW || sL|j	| |j
tj  qLW tt|j||B S )
zReturns a set containing the paths that need to be renamed.

    This set may include directories when the original sequence of paths
    included every file on disk.
    c             s   s   | ]}t jj||fV  qd S )N)r!   r"   normcase)rL   pr+   r+   r,   rO   }   s    z&compress_for_rename.<locals>.<genexpr>c             s   s   | ]}t jj|d  V  qdS )r   N)r!   r"   rA   )rL   rW   r+   r+   r,   rO      s   )rG   c              W   s   t jjt jj|  S )N)r!   r"   rV   r#   )ar+   r+   r,   	norm_join   s    z&compress_for_rename.<locals>.norm_joinc             3   s    | ]}t jj j|V  qd S )N)r!   r"   rV   rI   )rL   w)rootr+   r,   rO      s   c             3   s   | ]} |V  qd S )Nr+   )rL   d)dirnamerY   r[   r+   r,   rO      s   c             3   s   | ]} |V  qd S )Nr+   )rL   f)r]   rY   r[   r+   r,   rO      s   )dictr.   rP   valuesrK   rQ   r!   walkupdatedifference_updater/   rN   map__getitem__)	rR   case_map	remaining	unchecked	wildcards	all_filesall_subdirssubdirsfilesr+   )r]   rY   r[   r,   compress_for_renamev   s*    




rn   c             C   s  t | }t  }t  }t  }xF|D ]>}|jdr0q |jdsBd|krT|jtjj| |j| q W t ttjj|}t|}xt|D ]l}xftj	|D ]X\}}	}
xL|
D ]D}|jdrqtjj
||}tjj|rtjj||kr|j| qW qW qW |dd |D B }||fS )as  Returns a tuple of 2 sets of which paths to display to user

    The first set contains paths that would be deleted. Files of a package
    are not added and the top-level directory of the package has a '*' added
    at the end - to signify that all it's contents are removed.

    The second set contains files that would have been skipped in the above
    folders.
    z.pycz__init__.pyz
.dist-infoc             S   s   h | ]}t jj|d qS )rH   )r!   r"   r#   )rL   folderr+   r+   r,   	<setcomp>   s   z.compress_for_output_listing.<locals>.<setcomp>)r.   r@   r/   r!   r"   r]   rd   rV   rU   ra   r#   isfile)rR   will_remove	will_skipfoldersrm   r"   _normcased_filesro   dirpath_dirfilesfnamefile_r+   r+   r,   compress_for_output_listing   s0    





r{   c               @   sL   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	e
dd ZdS )StashedUninstallPathSetzWA set of file rename operations to stash files while
    tentatively uninstalling them.c             C   s   i | _ g | _d S )N)
_save_dirs_moves)selfr+   r+   r,   __init__   s    z StashedUninstallPathSet.__init__c             C   sD   yt |}W n tk
r*   tdd}Y nX || jtjj|< |jS )zStashes a directory.

        Directories are stashed adjacent to their original location if
        possible, or else moved/copied into the user's temp dir.	uninstall)kind)r   OSErrorr   r}   r!   r"   rV   )r   r"   save_dirr+   r+   r,   _get_directory_stash   s    z,StashedUninstallPathSet._get_directory_stashc             C   s   t jj|}t jj|d }}d}xd||krfy| j| }P W n tk
rP   Y nX t jj|| }}q$W t jj|}tdd}|| j|< t jj||}|r|t jjkrt jj	|j|S |jS )zStashes a file.

        If no root has been provided, one will be created for the directory
        in the user's temp directory.Nr   )r   )
r!   r"   rV   r]   r}   KeyErrorr   relpathcurdirr#   )r   r"   headold_headr   r   r+   r+   r,   _get_file_stash   s"    



z'StashedUninstallPathSet._get_file_stashc             C   sl   t jj|ot jj| }|r*| j|}n
| j|}| jj||f |r^t jj|r^t j| t	|| |S )zStashes the directory or file and returns its new location.
        Handle symlinks as files to avoid modifying the symlink targets.
        )
r!   r"   isdirislinkr   r   r~   r$   rmdirr   )r   r"   path_is_dirnew_pathr+   r+   r,   stash  s    


zStashedUninstallPathSet.stashc             C   s0   x| j j D ]\}}|j  qW g | _i | _ dS )z0Commits the uninstall by removing stashed files.N)r}   itemscleanupr~   )r   rw   r   r+   r+   r,   commit  s    zStashedUninstallPathSet.commitc             C   s   x| j D ]}tjd|  qW x| j D ]\}}yTtjd|| tjj|sVtjj|rbtj| ntjj	|rvt
| t|| W q& tk
r } ztjd| tjd| W Y dd}~X q&X q&W | j  dS )z2Undoes the uninstall by moving stashed files back.Moving to %s
 from %szReplacing %s from %szFailed to restore %szException: %sN)r   )r~   loggerinfodebugr!   r"   rq   r   unlinkr   r   r   r   errorr   )r   rW   r   r"   exr+   r+   r,   rollback&  s    "z StashedUninstallPathSet.rollbackc             C   s
   t | jS )N)boolr~   )r   r+   r+   r,   can_rollback:  s    z$StashedUninstallPathSet.can_rollbackN)__name__
__module____qualname____doc__r   r   r   r   r   r   propertyr   r+   r+   r+   r,   r|      s   	r|   c               @   s^   e Zd ZdZdd Zdd Zdd Zdd	 ZdddZdd Z	dd Z
dd Zedd ZdS )UninstallPathSetzMA set of file paths to be removed in the uninstallation of a
    requirement.c             C   s(   t  | _t  | _i | _|| _t | _d S )N)r.   rR   _refusepthr%   r|   _moved_paths)r   r%   r+   r+   r,   r   C  s
    zUninstallPathSet.__init__c             C   s   t |S )zs
        Return True if the given path is one we are permitted to
        remove/modify, False otherwise.

        )r   )r   r"   r+   r+   r,   
_permittedK  s    zUninstallPathSet._permittedc             C   s   t jj|\}}t jjt|t jj|}t jj|s:d S | j|rR| jj	| n| j
j	| t jj|d dkrtr| j	t| d S )N   z.py)r!   r"   rA   r#   r   rV   existsr   rR   r/   r   splitextr	   r   )r   r"   r   tailr+   r+   r,   r/   T  s    
zUninstallPathSet.addc             C   sL   t |}| j|r<|| jkr*t|| j|< | j| j| n| jj| d S )N)r   r   r   UninstallPthEntriesr/   r   )r   pth_fileentryr+   r+   r,   add_pthh  s    

zUninstallPathSet.add_pthFc             C   s   | j stjd| jj dS | jjd | jj }tjd| t x |sP| j|r| j}t	| j }x*t
t|D ]}|j| tjd| qnW x| jj D ]}|j  qW tjd| W dQ R X dS )z[Remove paths in ``self.paths`` with confirmation (unless
        ``auto_confirm`` is True).z7Can't uninstall '%s'. No files were found to uninstall.N-zUninstalling %s:zRemoving file or directory %szSuccessfully uninstalled %s)rR   r   r   r%   project_nameversionr
   _allowed_to_proceedr   rn   rP   rU   r   r   r   r`   remove)r   auto_confirmverbosedist_name_versionmoved
for_renamer"   r   r+   r+   r,   r   r  s"    


zUninstallPathSet.removec             C   sn   dd }|st | j\}}nt| j}t }|d| |d| |d| j |r`|dt| j tdd
dkS )zIDisplay which files would be deleted and prompt for confirmation
        c          
   S   sH   |sd S t j|  t & xtt|D ]}t j| q(W W d Q R X d S )N)r   r   r
   rP   rU   )msgrR   r"   r+   r+   r,   _display  s    
z6UninstallPathSet._allowed_to_proceed.<locals>._displayzWould remove:z+Would not remove (might be manually added):z%Would not remove (outside of prefix):zWill actually move:zProceed (y/n)? yn)r   r   )r{   rR   r.   r   rn   r   )r   r   r   rr   rs   r+   r+   r,   r     s    



z$UninstallPathSet._allowed_to_proceedc             C   sV   | j jstjd| jj dS tjd| jj | j j  x| jj	 D ]}|j  qBW dS )z1Rollback the changes previously made by remove().z'Can't roll back %s; was not uninstalledNzRolling back uninstall of %s)
r   r   r   r   r%   r   r   r   r   r`   )r   r   r+   r+   r,   r     s    

zUninstallPathSet.rollbackc             C   s   | j j  dS )z?Remove temporary save dir: rollback will no longer be possible.N)r   r   )r   r+   r+   r,   r     s    zUninstallPathSet.commitc                s  t |j}t|s.tjd|j|tj | |S |dd tj	dtj	dhD krhtjd|j| | |S | |}t
|}djtj|j}|jotjj|j}t|jdd }|o|jjd	o|jj| r|j|j |jd
r x|jd
j D ]&}tjjtjj|j|}	|j|	 qW n|jdr|jdrD|jd ng  xj fdd|jdj D D ]J}
tjj|j|
}	|j|	 |j|	d  |j|	d  |j|	d  qfW n6|rtdj|jn|jjdr(|j|j tjj|jd }tjjtjj|jd}|j|d|  n|r\|jjdr\xt |D ]}	|j|	 qFW n|rt!|d}tjj"|j# j$ }W d Q R X ||jkst%d||j|jf |j| tjjtjj|d}|j||j ntj&d||j |jdrb|j'drbxZ|j(dD ]L}t)|r&t*}nt+}|jtjj|| t,r|jtjj||d  qW g }|j-dd}x$|j. D ]}|j/t0||d q|W |j-d d}x$|j. D ]}|j/t0||d! qW x|D ]}|j| qW |S )"Nz1Not uninstalling %s at %s, outside environment %sc             S   s   h | ]}|r|qS r+   r+   )rL   rW   r+   r+   r,   rp     s    z-UninstallPathSet.from_dist.<locals>.<setcomp>stdlib
platstdlibz<Not uninstalling %s at %s, as it is in the standard library.z{}.egg-infor"   z	.egg-infozinstalled-files.txtztop_level.txtznamespace_packages.txtc                s   g | ]}|r| kr|qS r+   r+   )rL   rW   )
namespacesr+   r,   
<listcomp>  s    z.UninstallPathSet.from_dist.<locals>.<listcomp>z.pyz.pycz.pyozCannot uninstall {!r}. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.z.eggr   zeasy-install.pthz./z
.dist-inforB   z;Egg-link %s does not match installed location of %s (at %s)z)Not sure how to uninstall: %s - Check: %sscriptsz.batconsole_scripts)groupFgui_scriptsT)1r   r?   r   r   r   rG   sysprefix	sysconfigget_pathr   formatr   to_filenamer   egg_infor!   r"   r   getattr	_providerr@   r/   has_metadataget_metadata
splitlinesnormpathr#   r   rA   r]   r   rF   openrV   readlinestripAssertionErrorr   metadata_isdirmetadata_listdirr   r   r   r   get_entry_mapkeysextendr-   )clsr%   	dist_pathr*   develop_egg_linkdevelop_egg_link_egg_infoegg_info_existsdistutils_egg_infoinstalled_filer"   top_level_pkgeasy_install_eggeasy_install_pthfhlink_pointerscriptr(   _scripts_to_remover   namer   sr+   )r   r,   	from_dist  s    






zUninstallPathSet.from_distN)FF)r   r   r   r   r   r   r/   r   r   r   r   r   classmethodr   r+   r+   r+   r,   r   @  s   	

 r   c               @   s,   e Zd Zdd Zdd Zdd Zdd Zd	S )
r   c             C   s0   t jj|std| || _t | _d | _d S )Nz.Cannot remove entries from nonexistent file %s)r!   r"   rq   r   filer.   entries_saved_lines)r   r   r+   r+   r,   r   I  s    
zUninstallPthEntries.__init__c             C   s>   t jj|}tr.t jj|d  r.|jdd}| jj| d S )Nr   \/)r!   r"   rV   r   
splitdrivereplacer   r/   )r   r   r+   r+   r,   r/   S  s    
zUninstallPthEntries.addc             C   s   t jd| j t| jd}|j }|| _W d Q R X tdd |D rLd}nd}|r|d j|jd r|d |jd |d< xH| j	D ]>}y$t jd	| |j
|| jd W q tk
r   Y qX qW t| jd
}|j| W d Q R X d S )NzRemoving pth entries from %s:rbc             s   s   | ]}d |kV  qdS )s   
Nr+   )rL   liner+   r+   r,   rO   j  s    z-UninstallPthEntries.remove.<locals>.<genexpr>z

r   zutf-8zRemoving entry: %swbr   r   )r   r   r   r   	readlinesr   rQ   r@   encoder   r   
ValueError
writelines)r   r   linesendliner   r+   r+   r,   r   c  s"    
zUninstallPthEntries.removec          	   C   sR   | j d krtjd| j dS tjd| j t| jd}|j| j  W d Q R X dS )Nz.Cannot roll back changes to %s, none were madeFz!Rolling %s back to previous stater   T)r   r   r   r   r   r   r   )r   r   r+   r+   r,   r   z  s    

zUninstallPthEntries.rollbackN)r   r   r   r   r/   r   r   r+   r+   r+   r,   r   H  s   
r   )=
__future__r   r<   r6   loggingr!   r   r   pip._vendorr   pip._internal.exceptionsr   pip._internal.locationsr   r   pip._internal.utils.compatr   r   r	   pip._internal.utils.loggingr
   pip._internal.utils.miscr   r   r   r   r   r   r   r   r   pip._internal.utils.temp_dirr   r   pip._internal.utils.typingr   typingr   r   r   r   r   r   r   r   r   Zpip._vendor.pkg_resourcesr    	getLoggerr   r   r-   r8   rF   rU   rn   r{   objectr|   r   r   r+   r+   r+   r,   <module>   s:   ,,
(3o  
