o ai\ @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-d ede.de/de e.fddZ0de de efde de effddZ1e1d ede e.fddZ2de e.dee.fddZ3de e.dee.fddZ4de e.deee.ee.ffddZ5Gd d!d!Z6Gd"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 TempDirectorydist script_nameis_guireturncCsrt|rt}nt}tj||}|g}tr7||d||d|r0||d|S||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-python310-pip-21.3.1-5.el8.x86_64/opt/alt/python310/lib/python3.10/site-packages/pip/_internal/req/req_uninstall.py _script_namessr+fn.cs,tdtdtdttffdd }|S)Nargskwr!c?s8t}|i|D]}||vr|||Vq dSN)setadd)r-r.seenitemr,r)r*unique5s z_unique..unique) functoolswrapsrr)r,r5r)r4r*_unique4s r8c cs.z t|d}WnLtyW}z@dj|d}zt|d}|r'|dkr*tWntttfyFd|j |j }|d|7}Ynw|d|7}t ||d }~ww|D]:}t j |j|d }|V|d rt j |\}} | d d } t j || d }|Vt j || d}|VqZd 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@sB     rVpathscsJtjjt}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<|]}|dot|dkVqdS)*N) startswithrstriplen).0 shortpathr#sepr)r* us  zcompact..)r"r#rar0sortedr]anyr1)rW short_paths should_skipr)r`r*compactls rgc sdd|D}t|}tdd|Dtd}t}dtdtfdd |D]Ltfd d |Dr4q&t}t}tD]!\}}|fd d |D|fd d |Dq?||sr| || tj q&tt |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#rMrir)r)r* sz&compress_for_rename..rXar!cWstjtjj|Sr/)r"r#rhr$)rnr)r)r* norm_joinsz&compress_for_rename..norm_joinc3s"|] }tj|VqdSr/)r"r#rhr[)r^w)rootr)r*rbs z&compress_for_rename..c3|] }|VqdSr/r))r^ddirnamerorqr)r*rbc3rrr/r))r^frtr)r*rbrv)r0rcvaluesr]strrdr"walkupdatedifference_updater1ramap __getitem__) rWcase_map remaining unchecked wildcards all_files all_subdirssubdirsfilesr)rtr*compress_for_renames$ rc Cst|}t}t}t}|D]}|drq|ds d|vr)|tj|||qtttjj|}t|}|D]2}t |D]*\}} } | D]"} | drTqLtj || } tj | rntj| |vrn|| qLqEq>|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)rZ)r"r#r$)r^folderr)r)r*rmrlz.compress_for_output_listing..) r0rLr1r"r#rur}rhrgrzr$isfile) rW will_remove will_skipfoldersrr#_normcased_filesrdirpath_dirfilesfnamefile_r)r)r*compress_for_output_listings6       rc@sveZdZdZdddZdedefddZdedefd d Zdedefd d Zdd dZ dddZ e de fddZ dS)StashedUninstallPathSetzWA set of file rename operations to stash files while tentatively uninstalling them.r!NcCsi|_g|_dSr/) _save_dirs_movesselfr)r)r*__init__s z StashedUninstallPathSet.__init__r#cCsBzt|}Wntytdd}Ynw||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)rrGrrr"r#rh)rr#save_dirr)r)r*_get_directory_stashs  z,StashedUninstallPathSet._get_directory_stashcCstj|}tj|d}}d}||kr3z|j|}Wn&ty%Ynwtj||}}||kstj|}tdd}||j|<tj||}|rZ|tjjkrZtj |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#rhrurKeyErrorrrelpathcurdirr$)rr#headold_headrrr)r)r*_get_file_stashs&     z'StashedUninstallPathSet._get_file_stashcCsltj|o tj| }|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]\}}|qg|_i|_dS)z0Commits the uninstall by removing stashed files.N)ritemscleanupr)rrrr)r)r*commits  zStashedUninstallPathSet.commitc Cs|jD] }tjdg|Rq|jD]L\}}z*td||tj|s*tj|r0t|n tj |r:t |t ||Wqt y^}zt d|td|WYd}~qd}~ww|dS)z2Undoes the uninstall by moving stashed files back.zMoving to %s from %szReplacing %s from %szFailed to restore %sz Exception: %sN)rloggerinfodebugr"r#rrunlinkrrrrGerrorr)rrjrr#exr)r)r*rollback$s     z StashedUninstallPathSet.rollbackcCs t|jSr/)boolrrr)r)r* can_rollback7s z$StashedUninstallPathSet.can_rollbackr!N)__name__ __module__ __qualname____doc__rryrrrrrpropertyrrr)r)r)r*rs   rc@seZdZdZdeddfddZdedefdd Zdeddfd d Z d ed eddfddZ ddededdfddZ dedefddZ dddZ dddZededdfddZdS)UninstallPathSetzMA set of file paths to be removed in the uninstallation of a requirement.rr!NcCs(t|_t|_i|_||_t|_dSr/)r0rW_refusepthrr _moved_paths)rrr)r)r*r@s  zUninstallPathSet.__init__r#cCst|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|sdS||r)|j |n|j |tj |ddkrB| t |dSdS)Nr<) r"r#rMr$rrhexistsrrWr1rsplitextr)rr#rtailr)r)r*r1Os   zUninstallPathSet.addpth_fileentrycCsNt|}||r||jvrt||j|<|j||dS|j|dSr/)rrrUninstallPthEntriesr1r)rrrr)r)r*add_pthbs   zUninstallPathSet.add_pthF auto_confirmverbosecCs|js td|jjdS|jjd|jj}td|tF|s(||r^|j}t |j}t t |D] }| |t d|q6|jD]}|qItd|WddSWddS1siwYdS)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)rWrrrrIrJr_allowed_to_proceedrrrcrgrrrrxremove)rrrdist_name_versionmoved for_renamer#rr)r)r*rks*    "zUninstallPathSet.removecCsdtdttddfdd}|st|j\}}nt|j}t}|d||d||d |j|r9|d t|jtd d d kS)z@Display which files would be deleted and prompt for confirmationrPrWr!NcSsZ|sdSt|ttt|D]}t|qWddS1s&wYdSr/)rrrrcrg)rPrWr#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)ryrrrWr0rrr)rrrrrr)r)r*rs     z$UninstallPathSet._allowed_to_proceedcCsR|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) rrrrrrIrrrrx)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|std|j|tj||S|ddt dt dhDvr4td|j|||S||}t |j }d t |j }|joOtj|j}t|jdd}|r|jd r|j|s||j|d r|d D]}tjtj|j|} || qwn|d r|d r|d ngfd d|d DD]$} tj|j| } || || d|| d|| dqn|rtd |j |jdr||jtj|jd} tjtj|jd} || d| nk|r|jdrt |D]} || qnS|rjt!|} tj"| #$}Wdn 1s.stdlib platstdlibzsz.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)0rrKrrrrYsysprefix sysconfigget_pathrrIrDr to_filenameegg_infor"r#rgetattr _providerrLr1 has_metadata get_metadata splitlinesnormpathr$rrMrurrVopenrhreadlinestriprmetadata_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                          zUninstallPathSet.from_dist)FFr)rrrrr rryrrr1rrrrr classmethodrr)r)r)r*r<s   rc@sHeZdZdeddfddZdeddfddZd d d Zdefd d ZdS)rrr!NcCs||_t|_d|_dSr/)filer0entries _saved_lines)rrr)r)r*rCs zUninstallPthEntries.__init__rcCs<tj|}trtj|ds|dd}|j|dS)Nr\/)r"r#rhr splitdrivereplacerr1)rrr)r)r*r1Hs  zUninstallPthEntries.addc Cs0td|jtj|jstd|jdSt|jd}|}||_ Wdn1s/wYt dd|Dr@d}nd}|rY|d | d sY|d| d |d<|j D]}ztd |||| d Wq\tyyYq\wt|jd }||WddS1swYdS) NzRemoving pth entries from %s:z.Cannot remove entries from nonexistent file %srbcss|]}d|vVqdS)s Nr))r^liner)r)r*rbbsz-UninstallPthEntries.remove..z  zutf-8zRemoving entry: %swb)rrrr"r#rwarningr readlinesrrdrLencoderrrF writelines)rrlinesendlinerr)r)r*rWs.    "zUninstallPthEntries.removecCsh|jdurtd|jdStd|jt|jd}||jWddS1s-wYdS)Nz.Cannot roll back changes to %s, none were madeFz!Rolling %s back to previous staterT)rrrrrrr)rrr)r)r*rrs  zUninstallPthEntries.rollbackr) rrrryrr1rrrr)r)r)r*rBs  r)9r@r6r"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_dirrrrrryrr+r8rVrgrrrrrr)r)r)r*s: ,     $ * +&"2i