U .e&\@s|ddlmZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl m Z mZddlmZmZmZddlmZddlmZmZmZmZmZmZmZmZmZdd lm Z m!Z!dd l"m#Z#e#r dd l$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-dd l.m/Z/e0e1Z2d dZ3ddZ4e4ddZ5ddZ6ddZ7ddZ8Gddde9Z:Gddde9Z;Gddde9Z.unique) functoolswraps)r3r4r(r2r)_unique=sr7ccstt|d}|D]t}tj|j|d}|V|drtj |\}}|dd}tj||d}|Vtj||d}|VqdS)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]. ZRECORDr.pyN.pyc.pyo) csvreaderr Zget_metadata_linesr!r"r#locationendswithsplit)r%rrowr"Zdnr3baser(r(r)uninstallation_pathsJs   rDcsJtjjt}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).0Z shortpathr"sepr(r) lszcompact..)r!r"rMr,sortedrJanyr-)pathsZ short_pathsZ should_skipr(rLr)compactbs rRc stdd|D}t|}ttdd|Dtd}t}dd|D]tfdd|DrfqJt}t}tD]B\}}|fdd|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. css|]}tj||fVqdSr+)r!r"normcaserKpr(r(r)rN}sz&compress_for_rename..css|]}tj|dVqdS)rN)r!r"r@rTr(r(r)rNsrEcWstjtjj|Sr+)r!r"rSr#)ar(r(r) norm_joinsz&compress_for_rename..norm_joinc3s |]}tj|VqdSr+)r!r"rSrH)rKw)rootr(r)rNsc3s|]}|VqdSr+r()rKddirnamerWrYr(r)rNsc3s|]}|VqdSr+r()rKfr[r(r)rNs)dictr,rOvaluesrJrPr!walkupdatedifference_updater-rMmap __getitem__) rQZcase_mapZ remainingZ uncheckedZ wildcardsZ all_filesZ all_subdirsZsubdirsfilesr(r[r)compress_for_renamevs6    rfc Cst|}t}t}t}|D]>}|dr.q|ds@d|krR|tj|||qtttjj|}t|}|D]d}t |D]T\}} } | D]D} | drqtj || } tj | rtj| |kr|| 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)rG)r!r"r#)rKfolderr(r(r) sz.compress_for_output_listing..) r,r?r-r!r"r\rcrSrRr`r#isfile) rQ will_remove will_skipZfoldersrer"Z_normcased_filesrhdirpath_ZdirfilesZfnameZfile_r(r(r)compress_for_output_listings4     roc@sLeZdZdZddZddZddZdd Zd d Zd d Z e ddZ dS)StashedUninstallPathSetzWA set of file rename operations to stash files while tentatively uninstalling them.cCsi|_g|_dSr+) _save_dirs_movesselfr(r(r)__init__sz StashedUninstallPathSet.__init__cCsDz t|}Wntk r*tdd}YnX||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. uninstallZkind)rOSErrorrrqr!r"rS)rtr"save_dirr(r(r)_get_directory_stashs  z,StashedUninstallPathSet._get_directory_stashcCstj|}tj|d}}d}||krfz|j|}WqWntk rPYnXtj||}}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.Nrvrw) r!r"rSr\rqKeyErrorrrelpathcurdirr#)rtr"headZold_headryr|r(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"isdirislinkrzrrrr$rmdirr)rtr"Z path_is_dirnew_pathr(r(r)stashs    zStashedUninstallPathSet.stashcCs,|jD]\}}|q g|_i|_dS)z0Commits the uninstall by removing stashed files.N)rqitemsZcleanuprr)rtrnryr(r(r)commits zStashedUninstallPathSet.commitc Cs|jD]}tjd|q|jD]\}}zTtd||tj|sPtj|r\t |ntj |rpt |t ||Wq t k r}ztd|td|W5d}~XYq Xq |dS)z2Undoes the uninstall by moving stashed files back.Moving to %s from %szReplacing %s from %szFailed to restore %sz Exception: %sN)r)rrlogginginfologgerdebugr!r"rjrunlinkrrrrxerrorr)rtrUrr"Zexr(r(r)rollback&s     z StashedUninstallPathSet.rollbackcCs t|jSr+)boolrrrsr(r(r) can_rollback:sz$StashedUninstallPathSet.can_rollbackN) __name__ __module__ __qualname____doc__rurzrrrrpropertyrr(r(r(r)rps rpc@s^eZdZdZddZddZddZdd Zdd d Zd dZ ddZ ddZ e ddZ dS)UninstallPathSetzMA set of file paths to be removed in the uninstallation of a requirement.cCs(t|_t|_i|_||_t|_dSr+)r,rQ_refusepthr%rp _moved_paths)rtr%r(r(r)ruCs zUninstallPathSet.__init__cCst|S)zs Return True if the given path is one we are permitted to remove/modify, False otherwise. )r)rtr"r(r(r) _permittedKszUninstallPathSet._permittedcCstj|\}}tjt|tj|}tj|s:dS||rR|j |n |j |tj |ddkrt r| t |dS)Nr8)r!r"r@r#rrSexistsrrQr-rsplitextr r)rtr"r~tailr(r(r)r-Ts   zUninstallPathSet.addcCsLt|}||r<||jkr*t||j|<|j||n |j|dSr+)rrrUninstallPthEntriesr-r)rtpth_fileentryr(r(r)add_pthhs   zUninstallPathSet.add_pthFc Cs|jstd|jjdS|jjd|jj}td|tp|sP||r|j}t |j}t t |D]}| |t d|ql|jD] }|qtd|W5QRXdS)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)rQrrr% project_nameversionr _allowed_to_proceedrrfrOrRrrrr_remove)rtZ auto_confirmverboseZdist_name_versionZmovedZ for_renamer"rr(r(r)rrs&    zUninstallPathSet.removecCsndd}|st|j\}}nt|j}t}|d||d||d|j|r`|dt|jtddd kS) zIDisplay which files would be deleted and prompt for confirmation c SsD|sdSt|t"tt|D]}t|q&W5QRXdSr+)rrr rOrR)msgrQr"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)rorQr,rrfr )rtrrrkrlr(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) rrrrr%rrrrr_)rtrr(r(r)rs zUninstallPathSet.rollbackcCs|jdS)z?Remove temporary save dir: rollback will no longer be possible.N)rrrsr(r(r)rszUninstallPathSet.commitc st|j}t|s.td|j|tj||S|ddt dt dhDkrhtd|j|||S||}t |}d t |j}|jotj|j}t|jdd}|r|jd r|j|s||j|d r|d D]&}tjtj|j|} || qn|d r|d rB|d ngfd d|d DD]J} tj|j| } || || d|| d|| dqbn2|rtd |jn|jdr"||jtj|jd} tjtj|jd} || d| n|rR|jdrRt |D]} || q>n|rt!|d} tj"| #$}W5QRX||jkst%d||j|jf||tjtj|d} || |jnt&d||j|drT|'drT|(dD]L}t)|rt*}nt+}|tj||t,r|tj||dqg}|j-dd}|.D]}|/t0||dql|j-d d}|.D]}|/t0||d!q|D]}||q|S)"Nz1Not uninstalling %s at %s, outside environment %scSsh|] }|r|qSr(r(rTr(r(r)risz-UninstallPathSet.from_dist..ZstdlibZ platstdlibzsz.UninstallPathSet.from_dist..r8r: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./rgrAz;Egg-link %s does not match installed location of %s (at %s)z)Not sure how to uninstall: %s - Check: %sZscriptsz.batconsole_scripts)groupF gui_scriptsT)1rr>rrrrFsysprefix sysconfigZget_pathrformatrZ to_filenamerZegg_infor!r"rgetattrZ _providerr?r-Z has_metadataZ get_metadata splitlinesnormpathr#rr@r\rrDopenrSreadlinestripAssertionErrorrZmetadata_isdirZmetadata_listdirr rrrZ get_entry_mapkeysextendr*)clsr%Z dist_pathr'Zdevelop_egg_linkZdevelop_egg_link_egg_infoZegg_info_existsZdistutils_egg_infoZinstalled_filer"Z top_level_pkgZeasy_install_eggZeasy_install_pthfhZ link_pointerZscriptr&Z_scripts_to_removernamersr(rr) from_dists                       zUninstallPathSet.from_distN)FF)rrrrrurr-rrrrr classmethodrr(r(r(r)r@s  rc@s,eZdZddZddZddZddZd S) rcCs0tj|std|||_t|_d|_dS)Nz.Cannot remove entries from nonexistent file %s)r!r"rjrfiler,entries _saved_lines)rtrr(r(r)ruIs zUninstallPthEntries.__init__cCs<tj|}tr,tj|ds,|dd}|j|dS)Nr\/)r!r"rSr splitdrivereplacerr-)rtrr(r(r)r-Ss  zUninstallPthEntries.addc Cstd|jt|jd}|}||_W5QRXtdd|DrLd}nd}|r~|d|ds~|d|d|d<|j D]>}z$td || ||dWqt k rYqXqt|jd }| |W5QRXdS) NzRemoving pth entries from %s:rbcss|]}d|kVqdS)s Nr()rKliner(r(r)rNjsz-UninstallPthEntries.remove..z  zutf-8zRemoving entry: %swb) rrrr readlinesrrPr?encoderr ValueError writelines)rtrlinesZendlinerr(r(r)rcs"  zUninstallPthEntries.removec CsR|jdkrtd|jdStd|jt|jd}||jW5QRXdS)Nz.Cannot roll back changes to %s, none were madeFz!Rolling %s back to previous staterT)rrrrrrr)rtrr(r(r)rzs zUninstallPthEntries.rollbackN)rrrrur-rrr(r(r(r)rHs r)=Z __future__rr<r5rr!rrZ pip._vendorrZpip._internal.exceptionsrZpip._internal.locationsrrZpip._internal.utils.compatrrr Zpip._internal.utils.loggingr Zpip._internal.utils.miscr r r rrrrrrZpip._internal.utils.temp_dirrrZpip._internal.utils.typingrtypingrrrrrrrrrZpip._vendor.pkg_resourcesr Z getLoggerrrr*r7rDrRrfroobjectrprrr(r(r(r)s<    ,  ,    (3o