U
    ;»{j-]  ã                   @   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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„Z0ee+ ee+ dœdd„Z1ee+ eee+ ee+ f dœdd„Z2G dd„ dƒZ3G d d!„ d!ƒZ4G d"d#„ d#ƒZ5dS )$é    N)Úcache_from_source)	ÚAnyÚCallableÚDictÚ	GeneratorÚIterableÚListÚOptionalÚSetÚTuple)ÚLegacyDistutilsInstallÚUninstallMissingRecord)Ú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$   ú@/tmp/pip-install-zsn1f9xv/pip/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                  ?   s2   t ƒ }ˆ | |ŽD ]}||kr| |¡ |V  qd S ©N)ÚsetÚadd)r(   r)   ÚseenÚitem©r'   r$   r%   Úunique+   s
    
z_unique.<locals>.unique)Ú	functoolsÚwrapsr   r   )r'   r0   r$   r/   r%   Ú_unique(   s    "r3   ©Údistr   c                 c   s¨   | j }|dk	stdƒ‚|  ¡ }|dkr0t| d�‚|D ]n}tj ||¡}|V  | d¡r4tj |¡\}}|dd… }tj ||d ¡}|V  tj ||d ¡}|V  q4d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 an error,
    with possible information from the INSTALLER file.

    https://packaging.python.org/specifications/recording-installed-packages/
    Nznot installed©Údistributionú.pyéýÿÿÿú.pycú.pyo)	ÚlocationÚAssertionErrorÚiter_declared_entriesr   r    r!   r"   ÚendswithÚsplit)r5   r<   ÚentriesÚentryr!   Údnr'   Úbaser$   r$   r%   Úuninstallation_paths6   s    

rE   )Úpathsr   c                    sJ   t jj‰tƒ }t| td�D ]*‰ t‡ ‡fdd„|D ƒƒ}|s| ˆ ¡ q|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>a   s   þzcompact.<locals>.<genexpr>)r    r!   rP   r+   ÚsortedrL   Úanyr,   )rF   Úshort_pathsÚshould_skipr$   rO   r%   ÚcompactX   s    ýrV   c           	         sø   dd„ | D ƒ}t |ƒ}tdd„ | ¡ D ƒtd�}t ƒ }ttdœdd„‰|D ]˜‰t‡fd	d
„|D ƒƒrfqJt ƒ }t ƒ }t ˆ¡D ]B\‰ }}| ‡ ‡‡fdd
„|D ƒ¡ | ‡ ‡‡fdd
„|D ƒ¡ q||| sJ| 	|¡ | 
ˆtj ¡ qJt 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©rM   Úpr$   r$   r%   Ú
<dictcomp>q   s     
 z'compress_for_rename.<locals>.<dictcomp>c                 S   s   h | ]}t j |¡d  ’qS )r   )r    r!   r@   rX   r$   r$   r%   Ú	<setcomp>s   s     z&compress_for_rename.<locals>.<setcomp>rG   )Úar   c                  W   s   t j t jj| Ž ¡S r*   )r    r!   rW   r"   )r\   r$   r$   r%   Ú	norm_joinv   s    z&compress_for_rename.<locals>.norm_joinc                 3   s    | ]}t j ˆ ¡ |¡V  qd S r*   )r    r!   rW   rJ   )rM   Úw)Úrootr$   r%   rQ   z   s     z&compress_for_rename.<locals>.<genexpr>c                 3   s   | ]}ˆˆˆ |ƒV  qd S r*   r$   )rM   Úd©Údirnamer]   r_   r$   r%   rQ   �   s     c                 3   s   | ]}ˆˆˆ |ƒV  qd S r*   r$   )rM   Úfra   r$   r%   rQ   ‚   s     )r+   rR   ÚvaluesrL   ÚstrrS   r    ÚwalkÚupdateÚdifference_updater,   rP   ÚmapÚ__getitem__)	rF   Úcase_mapÚ	remainingÚ	uncheckedÚ	wildcardsÚ	all_filesÚall_subdirsÚsubdirsÚfilesr$   ra   r%   Úcompress_for_renamek   s"    
rs   c                 C   sü   t | ƒ}t ƒ }t ƒ }t ƒ }|D ]>}| d¡r.q| d¡s@d|krR| tj |¡¡ | |¡ qt ttjj|ƒƒ}t|ƒ}|D ]d}t 	|¡D ]T\}}	}
|
D ]D}| d¡r¨q˜tj 
||¡}tj |¡r˜tj |¡|kr˜| |¡ q˜qŠq||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.
    r:   z__init__.pyz
.dist-infoc                 S   s   h | ]}t j |d ¡’qS )rI   )r    r!   r"   )rM   Úfolderr$   r$   r%   r[   ¹   s     z.compress_for_output_listing.<locals>.<setcomp>)r+   r?   r,   r    r!   rb   ri   rW   rV   rf   r"   Úisfile)rF   Úwill_removeÚ	will_skipÚfoldersrr   r!   Ú_normcased_filesrt   ÚdirpathÚ_ÚdirfilesÚfnameÚfile_r$   r$   r%   Úcompress_for_output_listing�   s2    


ÿþr   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 r*   )Ú
_save_dirsÚ_moves©Úselfr$   r$   r%   Ú__init__Â   s    z StashedUninstallPathSet.__init__©r!   r   c                 C   sD   zt |ƒ}W n tk
r*   tdd�}Y nX || jtj |¡< |jS )z�Stashes 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!   rW   )r…   r!   Úsave_dirr$   r$   r%   Ú_get_directory_stashÊ   s    z,StashedUninstallPathSet._get_directory_stashc                 C   sº   t j |¡}t j |¡d }}d}||krfz| j| }W q†W n tk
rP   Y nX t j |¡| }}q"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!   rW   rb   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 )z�Stashes 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!   Zpath_is_dirÚnew_pathr$   r$   r%   Ústashó   s    


zStashedUninstallPathSet.stashc                 C   s(   | j  ¡ D ]}| ¡  q
g | _i | _ dS )z0Commits the uninstall by removing stashed files.N)r‚   rd   Úcleanuprƒ   )r…   rŒ   r$   r$   r%   Úcommit  s    
zStashedUninstallPathSet.commitc                 C   sÆ   | j D ]}tjd|žŽ  q| j D ]˜\}}zTt d||¡ tj |¡sPtj |¡r\t |¡ ntj 	|¡rpt
|ƒ t||ƒ W q  tk
r¶ } zt d|¡ t d|¡ W 5 d}~X Y q X q |  ¡  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!   ru   r•   Úunlinkr”   r   r   r‹   Úerrorr›   )r…   rY   r˜   r!   Úexr$   r$   r%   Úrollback  s    
 z StashedUninstallPathSet.rollbackc                 C   s
   t | jƒS r*   )Úboolrƒ   r„   r$   r$   r%   Úcan_rollback"  s    z$StashedUninstallPathSet.can_rollback)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r†   re   r�   r“   r™   r›   r£   Úpropertyr¤   r¥   r$   r$   r$   r%   r€   ¾   s   r€   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.Nr4   c                 C   s4   t ƒ | _t ƒ | _i | _|| _tƒ | _t t	¡| _
d S r*   )r+   Ú_pathsÚ_refuseÚ_pthÚ_distr€   Ú_moved_pathsr1   Ú	lru_cacher   Ú_normalize_path_cached)r…   r5   r$   r$   r%   r†   +  s    zUninstallPathSet.__init__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   rJ   r²   ÚsysÚprefix)r…   r!   r$   r$   r%   Ú
_permitted6  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é   r8   )r    r!   r@   r"   r²   rW   Úexistsrµ   r¬   r,   r­   Úsplitextr   )r…   r!   r‘   Útailr$   r$   r%   r,   A  s    
zUninstallPathSet.add)Úpth_filerB   r   c                 C   sN   |   |¡}|  |¡r>|| jkr,t|ƒ| j|< | j|  |¡ n| j |¡ d S r*   )r²   rµ   r®   ÚUninstallPthEntriesr,   r­   )r…   rº   rB   r$   r$   r%   Úadd_pthT  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ƒ �p |sR|  |¡r®| j}t	| j ƒ}t
t|ƒƒD ]}| |¡ t d|¡ qn| j ¡ D ]}| ¡  q”t d|¡ W 5 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¯   Úraw_nameZraw_versionr   Ú_allowed_to_proceedr°   rs   rR   rV   r™   r¾   r®   rd   Úremove)r…   r½   r¾   Údist_name_versionÚmovedÚ
for_renamer!   Úpthr$   r$   r%   rÂ   ]  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)ÚmsgrF   r   c              	   S   sD   |sd S t  | ¡ tƒ �" tt|ƒƒD ]}t  |¡ q&W 5 Q R X d S r*   )r�   rž   r   rR   rV   )rÇ   rF   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Ê   )re   r   r   r¬   r+   r­   rs   r   )r…   r¾   rÈ   rv   rw   r$   r$   r%   rÁ   z  s    	


z$UninstallPathSet._allowed_to_proceedr�   c                 C   sR   | j jst d| jj¡ dS t d| jj¡ | j  ¡  | j 	¡ D ]}| ¡  q@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®   rd   )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|D ]}	| tj ||	¡¡ qün®| d	¡�röz| d
¡}
W n tk
�rL   g ‰ Y nX |
jdd�‰ ‡ fdd„| d	¡ ¡ D ƒD ]N}tj ||¡}| |¡ | |› d�¡ | |› d�¡ | |› d�¡ �qv�n,|j�ràt|d�‚�n|j�r*| |¡ tj |¡d }tj tj |¡d¡}| |d| ¡ nÌ|j �rNt!|ƒD ]}| |¡ �q:n¨|�rèt"|ƒ�$}tj #| $¡  %¡ ¡}| &|¡}W 5 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,ƒ }zH| -¡ D ]:}| tj ||¡¡ t.�r| tj ||› d�¡¡ �qW n tt/fk
�rn   Y nX t0t1t2t1d d f dœdd„}|||ƒD ]}| |¡ �q–|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$   rX   r$   r$   r%   r[   ¼  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$   rX   ©Ú
namespacesr$   r%   Ú
<listcomp>ê  s    þz.UninstallPathSet.from_dist.<locals>.<listcomp>r8   r:   r;   r6   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)r5   r   r   c                 s   sP   |   ¡ D ]B}|jdkr,t||jdƒE d H  q|jdkrt||jdƒE d H  qd S )NÚconsole_scriptsFÚgui_scriptsT)Úiter_entry_pointsÚgroupr&   Úname)r5   r   Zentry_pointr$   r$   r%   Úiter_scripts_to_remove2  s
    

z:UninstallPathSet.from_dist.<locals>.iter_scripts_to_remove)3r<   Úinfo_locationr�   rž   Úcanonical_namer   Úlocalr³   r´   Ú	sysconfigÚget_pathr   rÀ   Z"installed_with_setuptools_egg_infor    r!   r·   r?   Zsetuptools_filenamer,   r>   r"   Úis_fileÚ	read_textÚFileNotFoundErrorÚ
splitlinesZinstalled_by_distutilsr   Zinstalled_as_eggr@   rb   r¼   Zinstalled_with_dist_inforE   ÚopenrW   ÚreadlineÚstripr²   Úsamefiler=   rŸ   Zin_usersiter   r   Ziter_distutils_script_namesr   ÚNotADirectoryErrorr   re   r   )Úclsr5   Údist_locationrÙ   Znormalized_dist_locationÚpaths_to_removeÚdevelop_egg_linkZsetuptools_flat_installationZinstalled_filesÚinstalled_fileZnamespace_packagesÚtop_level_pkgr!   Úeasy_install_eggÚeasy_install_pthÚfhÚlink_pointerZnormalized_link_pointerr   ÚscriptrØ   Úsr$   rÏ   r%   Ú	from_dist§  sÚ    þüþý
ÿ
þú



þ



þ
ÿ ÿý

 ÿý"ý
zUninstallPathSet.from_dist)FF)r¦   r§   r¨   r©   r   r†   re   r¤   rµ   r,   r¼   rÂ   rÁ   r£   r›   Úclassmethodró   r$   r$   r$   r%   r«   '  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 r*   )Úfiler+   rA   Ú_saved_lines)r…   rº   r$   r$   r%   r†   C  s    zUninstallPthEntries.__init__)rB   r   c                 C   s<   t j |¡}tr,t j |¡d s,| dd¡}| j |¡ d S )Nr   ú\ú/)r    r!   rW   r   Ú
splitdriveÚreplacerA   r,   )r…   rB   r$   r$   r%   r,   H  s    
zUninstallPthEntries.addr�   c              	   C   s
  t  d| j¡ tj | j¡s.t  d| j¡ d S t| jdƒ�}| ¡ }|| _	W 5 Q R X t
dd„ |D ƒƒrld}nd}|rž|d  | d	¡¡sž|d | d	¡ |d< | jD ]>}z$t  d
|¡ | ||  d	¡¡ W q¤ tk
rà   Y q¤X q¤t| jdƒ�}| |¡ W 5 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$   )rM   Úliner$   r$   r%   rQ   b  s     z-UninstallPthEntries.remove.<locals>.<genexpr>z
Ú
éÿÿÿÿzutf-8zRemoving entry: %sÚwb)r�   r¾   rõ   r    r!   ru   Úwarningrâ   Ú	readlinesrö   rS   r?   ÚencoderA   rÂ   Ú
ValueErrorÚ
writelines)r…   rï   ÚlinesÚendlinerB   r$   r$   r%   rÂ   W  s(    
zUninstallPthEntries.removec              	   C   sR   | j d krt d| j¡ dS t d| j¡ t| jdƒ�}| | j ¡ W 5 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£   r  s    
zUninstallPthEntries.rollback)	r¦   r§   r¨   re   r†   r,   rÂ   r¤   r£   r$   r$   r$   r%   r»   B  s   r»   )6r1   r    r³   rÜ   Úimportlib.utilr   Útypingr   r   r   r   r   r   r	   r
   r   Úpip._internal.exceptionsr   r   Úpip._internal.locationsr   r   Zpip._internal.metadatar   Úpip._internal.utils.compatr   Z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�   re   r¤   r&   r3   rE   rV   rs   r   r€   r«   r»   r$   r$   r$   r%   Ú<module>   sB   ,  þþ!"$1i  