a
ˆljÄ\ ã @ sÒ d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZm Z m
Z
mZmZm
Z
mZmZmZ d dlmZ d dlmZ d dlmZ d dlmZmZ d dlmZ d d lmZ d d
lmZm Z d dl!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( d dl)m*Z*m+Z+ ee,ƒZ-ee.e/e
e. d
œdd„Z0e dee f e dee f dœdd„Z1e1eee. dœdd„ƒZ2ee. ee. dœdd„Z3ee. ee. dœdd„Z4ee. eee. ee. f dœdd„Z5G dd„ dƒZ6G d d!„ d!ƒZ7G d"d#„ d#ƒZ8dS )$é N)Úcache_from_source) ÚAnyÚCallableÚDictÚIterableÚIteratorÚListÚOptionalÚSetÚTuple)Ú
pkg_resources)ÚDistribution)ÚUninstallationError)Úget_bin_prefixÚget_bin_user)ÚWINDOWS)Úegg_link_path_from_location)Ú getLoggerÚ
indent_log)ÚaskÚdist_in_usersiteÚ
dist_is_localÚis_localÚnormalize_pathÚrenamesÚrmtree)ÚAdjacentTempDirectoryÚ
TempDirectory)ÚdistÚscript_nameÚis_guiÚreturnc C sp t | ƒrtƒ }ntƒ }tj ||¡}|g}trl| |d ¡ | |d ¡ |r^| |d ¡ n| |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
z.exez
.exe.manifestz-script.pywz
-script.py)r r r ÚosÚpathÚjoinr Úappend)r r r Úbin_dirZexe_nameÚpaths_to_remove© r( úC/usr/lib/python3.9/site-packages/pip/_internal/req/req_uninstall.pyÚ
_script_names s r* .)Úfnr! c s( t ˆ ¡tttt dœ‡ fdd„ƒ}|S )N)ÚargsÚkwr! c ? s6 t ƒ }ˆ | i |¤ŽD ]}||vr| |¡ |V qd S ©N)ÚsetÚadd)r, r- ÚseenÚitem©r+ r( r) Úunique5 s
z_unique..unique)Ú functoolsÚwrapsr r )r+ r4 r( r3 r) Ú_unique4 s r7 ©r r! c
c s8 zt | d¡¡}W n¤ ty¸ } zŒdj| d}z$t| d¡ƒ}|rL|dkrRtƒ ‚W n6 tttfyŠ d | j | j
¡}|d |¡7 }Y n0 |d |¡7 }t|ƒ|‚W Y d }~n
d }~0 0 |D ]t}tj
| j|d
¡}|V | d¡r¾tj
|¡\}} | d d… }
tj
||
d
¡}|V tj
||
d ¡}|V q¾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/
ZRECORDz/Cannot uninstall {dist}, RECORD file not found.)r Z INSTALLERZpipz{}=={}zZ You might be able to recover from this via: 'pip install --force-reinstall --no-deps {}'.z' Hint: The package was installed by {}.Nr ú.pyéýÿÿÿú.pycú.pyo)ÚcsvÚreaderZget_metadata_linesÚFileNotFoundErrorÚformatÚnextÚ
ValueErrorÚOSErrorÚ
StopIterationÚproject_nameÚversionr r" r# r$ ÚlocationÚendswithÚsplit)r ÚrZmissing_record_exceptionÚmsgZ installerZdepÚrowr# Zdnr+ Úbaser( r( r) Úuninstallation_paths@ s6
ÿÿ
rN )Úpathsr! c sJ t jj‰tƒ }t| tdD ]*‰ t‡ ‡fdd„|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 ¡ ˆ¡ƒ ˆkV qdS )Ú*N)Ú
startswithÚrstripÚlen)Ú.0Z shortpath©r# Úsepr( r) Ú u s þzcompact..)r" r# rX r/ ÚsortedrU Úanyr0 )rO Zshort_pathsZshould_skipr( rW r) Úcompactl s ýr\ c sø dd„ | D ƒ}t |ƒ}tdd„ | ¡ D ƒtd}t ƒ }ttdœdd„‰|D ]˜‰t‡fd d
„|D ƒƒrfqJt ƒ }t ƒ }t ˆ¡D ]B\‰ }}| ‡ ‡‡fdd
„|D ƒ¡ | ‡ ‡‡fdd
„|D ƒ¡ q||| sJ| |¡ |
ˆtj ¡ 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 |¡|“qS r( )r" r# Únormcase©rV Úpr( r( r) Ú
… ó z'compress_for_rename..c S s h | ]}t j |¡d ’qS )r )r" r# rI r^ r( r( r) Ú ‡ ra z&compress_for_rename..rP )Úar! c W s t j t jj| Ž ¡S r. )r" r# r] r$ )rc r( r( r) Ú norm_joinŠ s z&compress_for_rename..norm_joinc 3 s | ]}t j ˆ ¡ |¡V qd S r. )r" r# r] rS )rV Úw)Úrootr( r) rY Ž ra z&compress_for_rename..c 3 s | ]}ˆˆˆ |ƒV qd S r. r( )rV Úd©Údirnamerd rf r( r) rY • ra c 3 s | ]}ˆˆˆ |ƒV qd S r. r( )rV Úfrh r( r) rY – ra )r/ rZ ÚvaluesrU Ústrr[ r" ÚwalkÚupdateÚdifference_updater0 rX ÚmapÚ__getitem__) rO Zcase_mapZ remainingZ uncheckedZ wildcardsZ all_filesZall_subdirsÚsubdirsÚfilesr( rh r) Úcompress_for_rename s"
rt c
C sü t | ƒ}t ƒ }t ƒ }t ƒ }|D ]>}| d¡r.q| d¡s@d|v rR| tj |¡¡ | |¡ qt ttjj|ƒƒ}t|ƒ}|D ]d}t |¡D ]T\}} }
|
D ]D}| d¡r¨q˜tj
||¡}tj |¡r˜tj |¡|vr˜| |¡ q˜qŠq||dd„ |D ƒB }||fS )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__.pyú
.dist-infoc S s h | ]}t j |d ¡’qS )rR )r" r# r$ )rV Úfolderr( r( r) rb Î ra z.compress_for_output_listing..)r/ rH r0 r" r# ri rp r] r\ rm r$ Úisfile)
rO Úwill_removeÚ will_skipZfoldersrs r# Z_normcased_filesrv ÚdirpathÚ_ZdirfilesÚfnameZfile_r( r( r) Úcompress_for_output_listing¡ s2
ÿþr} c @ s| e Zd ZdZddœdd„Zeedœdd„Zeedœd d
„Zeedœdd„Zddœd
d„Z ddœdd„Z
eedœdd„ƒZ
dS )Ú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 sB zt |ƒ}W n ty( tdd}Y n0 || jtj |¡<