B
    Ù&ef`  ã               @   sÖ  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mZm	Z	m
Z
mZmZmZmZmZ d dlmZ d dlmZmZ d dlm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!m"Z" d dl#m$Z$m%Z% d dl&m'Z' ee(ƒZ)e*e*e+e
e*ddf dœdd„Z,ede
eddf f ede
eddf f dœdd„Z-e-ee
e*ddf dœdd„ƒZ.ee* ee* dœdd„Z/ee* ee* dœdd„Z0ee* eee* ee* f dœdd„Z1G dd„ dƒZ2G d d!„ d!ƒZ3G d"d#„ d#ƒZ4dS )$é    N)Úcache_from_source)	ÚAnyÚCallableÚDictÚ	GeneratorÚIterableÚListÚOptionalÚSetÚTuple)ÚUninstallationError)Úget_bin_prefixÚget_bin_user)ÚBaseDistribution)ÚWINDOWS)Úegg_link_path_from_location)Ú	getLoggerÚ
indent_log)ÚaskÚnormalize_pathÚrenamesÚrmtree)ÚAdjacentTempDirectoryÚTempDirectory)Úrunning_under_virtualenv)Úbin_dirÚscript_nameÚis_guiÚreturnc             c   sV   t j | |¡}|V  tsdS |› dV  |› dV  |rF|› dV  n|› dV  dS )z‘Create the fully qualified name of the files created by
    {console,gui}_scripts for the given ``dist``.
    Returns the list of file names
    Nz.exez.exe.manifestz-script.pywz
-script.py)ÚosÚpathÚjoinr   )r   r   r   Úexe_name© r#   úN/home/dcms/DCMS/lib/python3.7/site-packages/pip/_internal/req/req_uninstall.pyÚ_script_names   s    r%   .)Úfnr   c                s.   t  ˆ ¡ttttd d f dœ‡ fdd„ƒ}|S )N)ÚargsÚkwr   c              ?   s6   t ƒ }x*ˆ | |ŽD ]}||kr| |¡ |V  qW d S )N)ÚsetÚadd)r'   r(   ÚseenÚitem)r&   r#   r$   Úunique+   s
    
z_unique.<locals>.unique)Ú	functoolsÚwrapsr   r   )r&   r-   r#   )r&   r$   Ú_unique(   s    "r0   )Údistr   c             c   sö   | j }|dk	stdƒ‚|  ¡ }|dkrzdj| d}| j}|rD|dkrdd | j| j¡}|d |¡7 }n|d |¡7 }t|ƒ‚xv|D ]n}tj	 
||¡}|V  | d	¡r€tj	 |¡\}}	|	dd
… }
tj	 
||
d ¡}|V  t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].

    If RECORD is not found, raises UninstallationError,
    with possible information from the INSTALLER file.

    https://packaging.python.org/specifications/recording-installed-packages/
    Nznot installedz/Cannot uninstall {dist}, RECORD file not found.)r1   Úpipz{}=={}zZ You might be able to recover from this via: 'pip install --force-reinstall --no-deps {}'.z' Hint: The package was installed by {}.z.pyéýÿÿÿz.pycz.pyo)ÚlocationÚAssertionErrorÚiter_declared_entriesÚformatÚ	installerÚraw_nameÚversionr   r   r    r!   ÚendswithÚsplit)r1   r4   ÚentriesÚmsgr8   ÚdepÚentryr    Údnr&   Úbaser#   r#   r$   Úuninstallation_paths6   s.    


rC   )Úpathsr   c                sN   t jj‰tƒ }x:t| tdD ]*‰ t‡ ‡fdd„|D ƒƒ}|s| ˆ ¡ qW |S )zÈCompact 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}ˆ   | d ¡¡o0ˆ t| d ¡ ˆ¡ƒ ˆkV  qdS )Ú*N)Ú
startswithÚrstripÚlen)Ú.0Ú	shortpath)r    Úsepr#   r$   ú	<genexpr>l   s   zcompact.<locals>.<genexpr>)r   r    rL   r)   ÚsortedrI   Úanyr*   )rD   Úshort_pathsÚshould_skipr#   )r    rL   r$   Úcompactb   s    
rR   c       	         s   dd„ | D ƒ}t |ƒ}tdd„ | ¡ D ƒtd}t ƒ }ttdœdd„‰x¤|D ]œ‰t‡fd	d
„|D ƒƒrhqLt ƒ }t ƒ }xPt ˆ¡D ]B\‰ }}| ‡ ‡‡fdd
„|D ƒ¡ | ‡ ‡‡fdd
„|D ƒ¡ q€W || sL| 	|¡ | 
ˆtj ¡ qLW t t|j|ƒƒ|B S )z«Returns 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   i | ]}|t j |¡“qS r#   )r   r    Únormcase)rJ   Úpr#   r#   r$   ú
<dictcomp>{   s    z'compress_for_rename.<locals>.<dictcomp>c             S   s   h | ]}t j |¡d  ’qS )r   )r   r    r<   )rJ   rT   r#   r#   r$   ú	<setcomp>}   s    z&compress_for_rename.<locals>.<setcomp>)rE   )Úar   c              W   s   t j t jj| Ž ¡S )N)r   r    rS   r!   )rW   r#   r#   r$   Ú	norm_join€   s    z&compress_for_rename.<locals>.norm_joinc             3   s    | ]}t j ˆ ¡ |¡V  qd S )N)r   r    rS   rG   )rJ   Úw)Úrootr#   r$   rM   „   s    z&compress_for_rename.<locals>.<genexpr>c             3   s   | ]}ˆˆˆ |ƒV  qd S )Nr#   )rJ   Úd)ÚdirnamerX   rZ   r#   r$   rM   ‹   s    c             3   s   | ]}ˆˆˆ |ƒV  qd S )Nr#   )rJ   Úf)r\   rX   rZ   r#   r$   rM   Œ   s    )r)   rN   ÚvaluesrI   ÚstrrO   r   ÚwalkÚupdateÚdifference_updater*   rL   ÚmapÚ__getitem__)	rD   Úcase_mapÚ	remainingÚ	uncheckedÚ	wildcardsÚ	all_filesÚall_subdirsÚsubdirsÚfilesr#   )r\   rX   rZ   r$   Úcompress_for_renameu   s"    
 
rm   c             C   s  t | ƒ}t ƒ }t ƒ }t ƒ }xF|D ]>}| d¡r0q | d¡sBd|krT| tj |¡¡ | |¡ q W t ttjj|ƒƒ}t|ƒ}xt|D ]l}xft 	|¡D ]X\}}	}
xL|
D ]D}| d¡r²q¢tj 
||¡}tj |¡r¢tj |¡|kr¢| |¡ q¢W q’W q‚W |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 |d ¡’qS )rF   )r   r    r!   )rJ   Úfolderr#   r#   r$   rV   Ä   s    z.compress_for_output_listing.<locals>.<setcomp>)r)   r;   r*   r   r    r\   rc   rS   rR   r`   r!   Úisfile)rD   Úwill_removeÚ	will_skipÚfoldersrl   r    Ú_normcased_filesrn   ÚdirpathÚ_ÚdirfilesÚfnameÚfile_r#   r#   r$   Úcompress_for_output_listing—   s.    




ry   c               @   s|   e Zd ZdZddœdd„Zeedœdd„Zeedœd	d
„Zeedœdd„Zddœdd„Z	ddœdd„Z
eedœdd„ƒZdS )ÚStashedUninstallPathSetzWA set of file rename operations to stash files while
    tentatively uninstalling them.N)r   c             C   s   i | _ g | _d S )N)Ú
_save_dirsÚ_moves)Úselfr#   r#   r$   Ú__init__Í   s    z StashedUninstallPathSet.__init__)r    r   c             C   sD   yt |ƒ}W n tk
r*   tdd}Y nX || jt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    rS   )r}   r    Úsave_dirr#   r#   r$   Ú_get_directory_stashÕ   s    z,StashedUninstallPathSet._get_directory_stashc             C   s¼   t j |¡}t j |¡d }}d}xd||krfy| j| }P W n tk
rP   Y nX t j |¡| }}q$W t j |¡}tdd}|| j|< t j ||¡}|r¶|t jjkr¶t j 	|j|¡S |jS )z‚Stashes 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    rS   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 |¡ot j |¡ }|r*|  |¡}n
|  |¡}| j ||f¡ |r^t j |¡r^t  |¡ 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|   ÚappendÚrmdirr   )r}   r    Úpath_is_dirÚnew_pathr#   r#   r$   Ústashþ   s    


zStashedUninstallPathSet.stashc             C   s0   x| j  ¡ D ]\}}| ¡  qW g | _i | _ dS )z0Commits the uninstall by removing stashed files.N)r{   ÚitemsÚcleanupr|   )r}   ru   r‚   r#   r#   r$   Úcommit  s    zStashedUninstallPathSet.commitc             C   sÎ   x| j D ]}tjd|žŽ  qW x¢| j D ]˜\}}yTt d||¡ tj |¡sVtj |¡rbt |¡ ntj 	|¡rvt
|ƒ t||ƒ W q& tk
r¼ } zt d|¡ t d|¡ W dd}~X Y q&X q&W |  ¡  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    ro   r‹   ÚunlinkrŠ   r   r   r   Úerrorr“   )r}   rT   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_rollback)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r~   r_   rƒ   r‰   r   r“   r›   Úpropertyrœ   r   r#   r#   r#   r$   rz   É   s   rz   c               @   s¦   e Zd ZdZeddœdd„Zeedœdd„Zeddœd	d
„Z	eeddœdd„Z
deeddœdd„Zeedœdd„Zddœdd„Zddœdd„Zeed dœdd„ƒZdS )ÚUninstallPathSetzMA set of file paths to be removed in the uninstallation of a
    requirement.N)r1   r   c             C   s6   t ƒ | _t ƒ | _i | _|| _tƒ | _t ¡ t	ƒ| _
d S )N)r)   Ú_pathsÚ_refuseÚ_pthÚ_distrz   Ú_moved_pathsr.   Ú	lru_cacher   Ú_normalize_path_cached)r}   r1   r#   r#   r$   r~   6  s    zUninstallPathSet.__init__)r    r   c             C   s   t ƒ s
dS | |  tj¡¡S )zs
        Return True if the given path is one we are permitted to
        remove/modify, False otherwise.

        T)r   rG   rª   ÚsysÚprefix)r}   r    r#   r#   r$   Ú
_permittedA  s    zUninstallPathSet._permittedc             C   s†   t j |¡\}}t j |  |¡t j |¡¡}t j |¡s<d S |  |¡rT| j 	|¡ n| j
 	|¡ t j |¡d dkr‚|  	t|ƒ¡ d S )Né   z.py)r   r    r<   r!   rª   rS   Úexistsr­   r¤   r*   r¥   Úsplitextr   )r}   r    r‡   Útailr#   r#   r$   r*   L  s    
zUninstallPathSet.add)Úpth_filer@   r   c             C   sN   |   |¡}|  |¡r>|| jkr,t|ƒ| j|< | j|  |¡ n| j |¡ d S )N)rª   r­   r¦   ÚUninstallPthEntriesr*   r¥   )r}   r²   r@   r#   r#   r$   Úadd_pth_  s    


zUninstallPathSet.add_pthF)Úauto_confirmÚverboser   c          	   C   sÄ   | j st d| jj¡ dS | jj› d| jj› }t d|¡ tƒ x |sR|  |¡r¶| j}t	| j ƒ}x*t
t|ƒƒD ]}| |¡ t d|¡ qpW x| j ¡ D ]}| ¡  qšW t 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)r¤   r•   r–   r§   r9   r:   r   Ú_allowed_to_proceedr¨   rm   rN   rR   r   r¶   r¦   r^   Úremove)r}   rµ   r¶   Údist_name_versionÚmovedÚ
for_renamer    Úpthr#   r#   r$   r¹   h  s"    


zUninstallPathSet.remove)r¶   r   c             C   s|   t tt  ddœdd„}|s*t| jƒ\}}nt| jƒ}tƒ }|d|ƒ |d|ƒ |d| jƒ |rn|dt| jƒƒ td	d
ƒdkS )z@Display which files would be deleted and prompt for confirmationN)r>   rD   r   c          	   S   sH   |sd S t  | ¡ tƒ & xtt|ƒƒD ]}t  |¡ q(W W d Q R X d S )N)r•   r–   r   rN   rR   )r>   rD   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   ry   r¤   r)   r¥   rm   r   )r}   r¶   r¾   rp   rq   r#   r#   r$   r¸   …  s    	


z$UninstallPathSet._allowed_to_proceed)r   c             C   sV   | j jst d| jj¡ dS t d| jj¡ | j  ¡  x| j 	¡ D ]}| ¡  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§   r9   r–   r›   r¦   r^   )r}   r½   r#   r#   r$   r›   ¡  s    

zUninstallPathSet.rollbackc             C   s   | 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Æ  |j }|j}|d kr*t d|j¡ | |ƒS t|ƒ}|jsTt d|j|tj¡ | |ƒS |dd„ t	 
d¡t	 
d¡hD ƒkrŽt d|j|¡ | |ƒS | |ƒ}t|jƒ}|joÌ|d k	oÌtj |¡oÌ| |j› d¡ }|rÒ|d k	ræ| |¡ | ¡ }|d k	rxÔ|D ]}	| tj ||	¡¡ qþW n²| d	¡ry| d
¡}
W n tk
rP   g ‰ Y nX |
jdd‰ xn‡ fdd„| d	¡ ¡ D ƒD ]N}tj ||¡}| |¡ | |› d¡ | |› d¡ | |› d¡ q|W n6|jrîtd |j¡ƒ‚n|jr8| |¡ tj |¡d }tj tj |¡d¡}|  |d| ¡ nÐ|j!r`xÆt"|ƒD ]}| |¡ qJW n¨|rút#|ƒ$}tj $| %¡  &¡ ¡}| '|¡}W d Q R X tj (||¡sÌt)d|› d|› d|j› d|› d	ƒ‚| |¡ tj tj |¡d¡}|  ||¡ nt *d||¡ |j+rt,ƒ }nt-ƒ }yLxF| .¡ D ]:}| tj ||¡¡ t/r*| tj ||› d¡¡ q*W W n tt0fk
r„   Y nX t1t2t3t2d d f dœdd„}x|||ƒD ]}| |¡ q®W |S ) Nz-Not uninstalling %s since it is not installedz1Not uninstalling %s at %s, outside environment %sc             S   s   h | ]}|r|’qS r#   r#   )rJ   rT   r#   r#   r$   rV   Ç  s   z-UninstallPathSet.from_dist.<locals>.<setcomp>ÚstdlibÚ
platstdlibz<Not uninstalling %s at %s, as it is in the standard library.z	.egg-infoztop_level.txtznamespace_packages.txtF)Úkeependsc                s   g | ]}|r|ˆ kr|‘qS r#   r#   )rJ   rT   )Ú
namespacesr#   r$   ú
<listcomp>ö  s   z.UninstallPathSet.from_dist.<locals>.<listcomp>z.pyz.pycz.pyoz©Cannot 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.r®   zeasy-install.pthz./z	Egg-link z (to z') does not match installed location of z (at ú)z)Not sure how to uninstall: %s - Check: %sz.bat)r1   r   r   c             s   sT   xN|   ¡ D ]B}|jdkr.t||jdƒE d H  q
|jdkr
t||jdƒE d H  q
W d S )NÚconsole_scriptsFÚgui_scriptsT)Úiter_entry_pointsÚgroupr%   Úname)r1   r   Úentry_pointr#   r#   r$   Úiter_scripts_to_removeC  s
    

z:UninstallPathSet.from_dist.<locals>.iter_scripts_to_remove)4r4   Úinfo_locationr•   r–   Úcanonical_namer   Úlocalr«   r¬   Ú	sysconfigÚget_pathr   r9   Ú"installed_with_setuptools_egg_infor   r    r¯   r;   Úsetuptools_filenamer*   r6   r!   Úis_fileÚ	read_textÚFileNotFoundErrorÚ
splitlinesÚinstalled_by_distutilsr   r7   Úinstalled_as_eggr<   r\   r´   Úinstalled_with_dist_inforC   ÚopenrS   ÚreadlineÚstriprª   Úsamefiler5   r—   Úin_usersiter   r   Úiter_distutils_script_namesr   ÚNotADirectoryErrorr   r_   r   )Úclsr1   Údist_locationrÏ   Únormalized_dist_locationÚpaths_to_removeÚdevelop_egg_linkÚsetuptools_flat_installationÚinstalled_filesÚinstalled_fileÚnamespace_packagesÚtop_level_pkgr    Úeasy_install_eggÚeasy_install_pthÚfhÚlink_pointerÚnormalized_link_pointerr   ÚscriptrÎ   Úsr#   )rÅ   r$   Ú	from_dist²  s¾    









"
$zUninstallPathSet.from_dist)FF)rž   rŸ   r    r¡   r   r~   r_   rœ   r­   r*   r´   r¹   r¸   r›   r“   Úclassmethodrõ   r#   r#   r#   r$   r£   2  s   	r£   c               @   sH   e Zd Zeddœdd„Zeddœdd„Zddœd	d
„Zedœdd„ZdS )r³   N)r²   r   c             C   s   || _ tƒ | _d | _d S )N)Úfiler)   r=   Ú_saved_lines)r}   r²   r#   r#   r$   r~   T  s    zUninstallPthEntries.__init__)r@   r   c             C   s<   t j |¡}tr,t j |¡d s,| dd¡}| j |¡ d S )Nr   ú\ú/)r   r    rS   r   Ú
splitdriveÚreplacer=   r*   )r}   r@   r#   r#   r$   r*   Y  s    
zUninstallPthEntries.add)r   c          	   C   s  t  d| j¡ tj | j¡s.t  d| j¡ d S t| jdƒ}| ¡ }|| _	W d Q R X t
dd„ |D ƒƒrld}nd}|rž|d  | d	¡¡sž|d | d	¡ |d< xH| jD ]>}y$t  d
|¡ | ||  d	¡¡ W q¦ tk
râ   Y q¦X q¦W t| jdƒ}| |¡ W d Q R X d S )NzRemoving pth entries from %s:z.Cannot remove entries from nonexistent file %sÚrbc             s   s   | ]}d |kV  qdS )s   
Nr#   )rJ   Úliner#   r#   r$   rM   s  s    z-UninstallPthEntries.remove.<locals>.<genexpr>z
Ú
éÿÿÿÿzutf-8zRemoving entry: %sÚwb)r•   r¶   r÷   r   r    ro   ÚwarningrÝ   Ú	readlinesrø   rO   r;   Úencoder=   r¹   Ú
ValueErrorÚ
writelines)r}   rð   ÚlinesÚendliner@   r#   r#   r$   r¹   h  s(    
zUninstallPthEntries.removec          	   C   sR   | j d krt d| j¡ dS t d| j¡ t| jdƒ}| | 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›   ƒ  s    
zUninstallPthEntries.rollback)	rž   rŸ   r    r_   r~   r*   r¹   rœ   r›   r#   r#   r#   r$   r³   S  s   r³   )5r.   r   r«   rÒ   Úimportlib.utilr   Útypingr   r   r   r   r   r   r	   r
   r   Úpip._internal.exceptionsr   Úpip._internal.locationsr   r   Úpip._internal.metadatar   Úpip._internal.utils.compatr   Úpip._internal.utils.egg_linkr   Úpip._internal.utils.loggingr   r   Úpip._internal.utils.miscr   r   r   r   Úpip._internal.utils.temp_dirr   r   Úpip._internal.utils.virtualenvr   rž   r•   r_   rœ   r%   r0   rC   rR   rm   ry   rz   r£   r³   r#   r#   r#   r$   Ú<module>   s:   , +"$2i  #