a Re\@sddlZddlZddlZddlZddlZddlmZddlmZm Z m Z m Z m Z m Z mZmZmZddlmZddlmZddlmZddlmZmZddlmZdd lmZdd lmZm Z dd l!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(dd l)m*Z*m+Z+ee,Z-ee.e/e e.d ddZ0e de efe de efdddZ1e1ee e.dddZ2e e.ee.dddZ3e e.ee.dddZ4e e.eee.ee.fdddZ5GdddZ6Gd d!d!Z7Gd"d#d#Z8dS)$N)cache_from_source) AnyCallableDictIterableIteratorListOptionalSetTuple) pkg_resources) Distribution)UninstallationError)get_bin_prefix get_bin_user)WINDOWS)egg_link_path_from_location) getLogger indent_log)askdist_in_usersite dist_is_localis_localnormalize_pathrenamesrmtree)AdjacentTempDirectory TempDirectory)dist script_nameis_guireturncCspt|rt}nt}tj||}|g}trl||d||d|r^||dn||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)rrrospathjoinrappend)rrr bin_direxe_namepaths_to_remover)/builddir/build/BUILDROOT/alt-python39-pip-21.3.1-2.el8.x86_64/opt/alt/python39/lib/python3.9/site-packages/pip/_internal/req/req_uninstall.py _script_namessr+.)fnr!cs(tttttdfdd }|S)N)argskwr!c?s6t}|i|D]}||vr|||VqdSN)setadd)r-r.seenitemr,r)r*unique5s  z_unique..unique) functoolswrapsrr)r,r5r)r4r*_unique4sr8rr!c cs8zt|d}Wnty}zdj|d}z$t|d}|rL|dkrRtWn6tttfyd|j |j }|d|7}Yn0|d|7}t ||WYd }~n d }~00|D]t}t j |j|d }|V|d rt j |\}} | d d } t j || d }|Vt j || d}|Vqd 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/ RECORDz/Cannot uninstall {dist}, RECORD file not found.)r INSTALLERpipz{}=={}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)csvreaderget_metadata_linesFileNotFoundErrorformatnext ValueErrorOSError StopIteration project_nameversionrr"r#r$locationendswithsplit) rrmissing_record_exceptionmsg installerdeprowr#dnr,baser)r)r*uninstallation_paths@s6       rW)pathsr!csJtjjt}t|tdD]*tfdd|D}|s|q|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.keyc3s:|]2}|do0t|dkVqdS)*N) startswithrstriplen).0 shortpathr#sepr)r* uszcompact..)r"r#rbr0sortedr^anyr1)rX short_paths should_skipr)rar*compactls rhc sdd|D}t|}tdd|Dtd}t}ttddd|D]tfd d |DrfqJt}t}tD]B\}}|fd d |D|fd d |Dq|||sJ| || tj qJtt |j ||BS) 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. cSsi|]}tj||qSr))r"r#normcaser_pr)r)r* z'compress_for_rename..cSsh|]}tj|dqS)r)r"r#rNrjr)r)r* rmz&compress_for_rename..rY)ar!cWstjtjj|Sr/)r"r#rir$)ror)r)r* norm_joinsz&compress_for_rename..norm_joinc3s |]}tj|VqdSr/)r"r#rir\)r_w)rootr)r*rcrmz&compress_for_rename..c3s|]}|VqdSr/r))r_ddirnamerprrr)r*rcrmc3s|]}|VqdSr/r))r_frtr)r*rcrm)r0rdvaluesr^strrer"walkupdatedifference_updater1rbmap __getitem__) rXcase_map remaining unchecked wildcards all_files all_subdirssubdirsfilesr)rtr*compress_for_renames" rc Cst|}t}t}t}|D]>}|dr.q|ds@d|vrR|tj|||qtttjj|}t|}|D]d}t |D]T\}} } | D]D} | drqtj || } tj | rtj| |vr|| qqq||dd|DB}||fS)asReturns 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-infocSsh|]}tj|dqS)r[)r"r#r$)r_folderr)r)r*rnrmz.compress_for_output_listing..) r0rMr1r"r#rur|rirhryr$isfile) rX will_remove will_skipfoldersrr#_normcased_filesrdirpath_dirfilesfnamefile_r)r)r*compress_for_output_listings2     rc@s|eZdZdZddddZeedddZeedd d Zeedd d Zddd dZ ddddZ e e dddZ dS)StashedUninstallPathSetzWA set of file rename operations to stash files while tentatively uninstalling them.Nr!cCsi|_g|_dSr/) _save_dirs_movesselfr)r)r*__init__sz StashedUninstallPathSet.__init__r#r!cCsBz t|}Wnty(tdd}Yn0||jtj|<|jS)zStashes a directory. Directories are stashed adjacent to their original location if possible, or else moved/copied into the user's temp dir. uninstallkind)rrHrrr"r#ri)rr#save_dirr)r)r*_get_directory_stashs   z,StashedUninstallPathSet._get_directory_stashcCstj|}tj|d}}d}||krdz|j|}WqWntyNYn0tj||}}q"tj|}tdd}||j|<tj||}|r|tjjkrtj |j|S|jS)zStashes a file. If no root has been provided, one will be created for the directory in the user's temp directory.Nrr) r"r#rirurKeyErrorrrelpathcurdirr$)rr#headold_headrrr)r)r*_get_file_stashs"      z'StashedUninstallPathSet._get_file_stashcCsltj|otj| }|r*||}n ||}|j||f|r^tj|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#isdirislinkrrrr%rmdirr)rr# path_is_dirnew_pathr)r)r*stashs    zStashedUninstallPathSet.stashcCs,|jD]\}}|q g|_i|_dS)z0Commits the uninstall by removing stashed files.N)ritemscleanupr)rrrr)r)r*commits zStashedUninstallPathSet.commitc Cs|jD]}tjdg|Rq|jD]\}}zTtd||tj|sTtj|r`t|ntj |rtt |t ||Wq$t y}z$t d|td|WYd}~q$d}~00q$|dS)z2Undoes the uninstall by moving stashed files back.zMoving to %s from %szReplacing %s from %szFailed to restore %sz Exception: %sN)rloggerinfodebugr"r#rrunlinkrrrrHerrorr)rrkrr#exr)r)r*rollback$s    $z StashedUninstallPathSet.rollbackcCs t|jSr/)boolrrr)r)r* can_rollback7sz$StashedUninstallPathSet.can_rollback)__name__ __module__ __qualname____doc__rrxrrrrrpropertyrrr)r)r)r*rsrc@seZdZdZeddddZeedddZeddd d Z eedd d d Z deeddddZ eedddZ ddddZ ddddZeeddddZdS)UninstallPathSetzMA set of file paths to be removed in the uninstallation of a requirement.Nr9cCs(t|_t|_i|_||_t|_dSr/)r0rX_refusepthrr _moved_paths)rrr)r)r*r@s zUninstallPathSet.__init__rcCst|S)zs Return True if the given path is one we are permitted to remove/modify, False otherwise. )r)rr#r)r)r* _permittedGszUninstallPathSet._permittedcCstj|\}}tjt|tj|}tj|s:dS||rR|j |n |j |tj |ddkr| t |dS)Nr=) r"r#rNr$rriexistsrrXr1rsplitextr)rr#rtailr)r)r*r1Os   zUninstallPathSet.add)pth_fileentryr!cCsLt|}||r<||jvr*t||j|<|j||n |j|dSr/)rrrUninstallPthEntriesr1r)rrrr)r)r*add_pthbs   zUninstallPathSet.add_pthF) auto_confirmverboser!cCs|jstd|jjdS|jjd|jj}td|tz|sP||r|j}t |j}t t |D]}| |t d|ql|jD] }|qtd|Wdn1s0YdS)z[Remove paths in ``self.paths`` with confirmation (unless ``auto_confirm`` is True).z7Can't uninstall '%s'. No files were found to uninstall.N-zUninstalling %s:zRemoving file or directory %szSuccessfully uninstalled %s)rXrrrrJrKr_allowed_to_proceedrrrdrhrrrrwremove)rrrdist_name_versionmoved for_renamer#rr)r)r*rks$    zUninstallPathSet.remove)rr!cCs|tttdddd}|s*t|j\}}nt|j}t}|d||d||d|j|rn|dt|jtd d d kS) z@Display which files would be deleted and prompt for confirmationN)rQrXr!cSsX|sdSt|t,tt|D]}t|q&Wdn1sJ0YdSr/)rrrrdrh)rQrXr#r)r)r*_displays  z6UninstallPathSet._allowed_to_proceed.._displayz Would remove:z+Would not remove (might be manually added):z%Would not remove (outside of prefix):zWill actually move:zProceed (Y/n)? )ynr)rxrrrXr0rrr)rrrrrr)r)r*rs     z$UninstallPathSet._allowed_to_proceedrcCsR|jjstd|jjdStd|jj|j|j D] }|q@dS)z1Rollback the changes previously made by remove().z'Can't roll back %s; was not uninstalledNzRolling back uninstall of %s) rrrrrrJrrrrw)rrr)r)r*rs zUninstallPathSet.rollbackcCs|jdS)z?Remove temporary save dir: rollback will no longer be possible.N)rrrr)r)r*rszUninstallPathSet.commitcst|j}t|s.td|j|tj||S|ddt dt dhDvrhtd|j|||S||}t |j }d t |j }|jotj|j}t|jdd}|r|jd r|j|s||j|d r |d D]&}tjtj|j|} || qn|d r|d rD|d ngfd d|d DD]J} tj|j| } || || d|| d|| dqdnF|rtd |j n,|jdr$||jtj|jd} tjtj|jd} || d| n|rT|jdrTt |D]} || q@n|rt!|$} tj"| #$}Wdn1s0Y||jksJd ||j |j||tjtj|d} || |jnt%d||j|drn|&drn|'dD]P}t(|r2t)}nt*}|tj||t+r|tj||dqg}|j,dd}|-D]}|.t/||dq|j,dd}|-D]}|.t/||d q|D]}||q|S)!Nz1Not uninstalling %s at %s, outside environment %scSsh|] }|r|qSr)r)rjr)r)r*rnsz-UninstallPathSet.from_dist..stdlib platstdlibzs z.UninstallPathSet.from_dist..r=r?r@zCannot 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.eggrzeasy-install.pthz./rz;Egg-link {} does not match installed location of {} (at {})z)Not sure how to uninstall: %s - Check: %sscriptsz.batconsole_scripts)groupF gui_scriptsT)0rrLrrrrZsysprefix sysconfigget_pathrrJrEr to_filenameegg_infor"r#rgetattr _providerrMr1 has_metadata get_metadata splitlinesnormpathr$rrNrurrWopenrireadlinestriprmetadata_isdirmetadata_listdirrrrr get_entry_mapkeysextendr+)clsr dist_pathr(develop_egg_linkdevelop_egg_link_egg_infoegg_info_existsdistutils_egg_infoinstalled_filer# top_level_pkgeasy_install_eggeasy_install_pthfh link_pointerscriptr&_scripts_to_removernamersr)rr* from_dists                 4        zUninstallPathSet.from_dist)FF)rrrrr rrxrrr1rrrrr classmethodrr)r)r)r*r<s  rc@sHeZdZeddddZeddddZddd d Zedd d ZdS) rN)rr!cCs||_t|_d|_dSr/)filer0entries _saved_lines)rrr)r)r*rCszUninstallPthEntries.__init__)rr!cCs<tj|}tr,tj|ds,|dd}|j|dS)Nr\/)r"r#rir splitdrivereplacerr1)rrr)r)r*r1Hs  zUninstallPthEntries.addrc Cs2td|jtj|js.td|jdSt|jd}|}||_ Wdn1s^0Yt dd|Drd}nd}|r|d | d s|d| d |d<|j D]<}z$td |||| d WqtyYq0qt|jd }||Wdn1s$0YdS) NzRemoving pth entries from %s:z.Cannot remove entries from nonexistent file %srbcss|]}d|vVqdS)s Nr))r_liner)r)r*rcbrmz-UninstallPthEntries.remove..z  zutf-8zRemoving entry: %swb)rrrr"r#rwarningr readlinesrrerMencoderrrG writelines)rrlinesendlinerr)r)r*rWs($   zUninstallPthEntries.removecCsf|jdurtd|jdStd|jt|jd}||jWdn1sX0YdS)Nz.Cannot roll back changes to %s, none were madeFz!Rolling %s back to previous staterT)rrrrrrr)rrr)r)r*rrs *zUninstallPthEntries.rollback) rrrrxrr1rrrr)r)r)r*rBsr)9rAr6r"rrimportlib.utilrtypingrrrrrrr r r pip._vendorr pip._vendor.pkg_resourcesr pip._internal.exceptionsrpip._internal.locationsrrpip._internal.utils.compatrpip._internal.utils.egg_linkrpip._internal.utils.loggingrrpip._internal.utils.miscrrrrrrrpip._internal.utils.temp_dirrrrrrxrr+r8rWrhrrrrrr)r)r)r*s8 ,     $ ( +"$2i