U n a\@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)r6r7r+r5r,_unique=sr:ccstt|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]. RECORDr.pyN.pyc.pyo) csvreaderr get_metadata_linesr!r"r#locationendswithsplit)r%rrowr"dnr6baser+r+r,uninstallation_pathsJs   rJcsJtjjt}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, lszcompact..)r!r"rTr/sortedrPanyr0)paths short_paths should_skipr+rSr,compactbs r[c 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"normcaserQpr+r+r,rU}sz&compress_for_rename..css|]}tj|dVqdS)rN)r!r"rEr]r+r+r,rUsrKcWstjtjj|Sr.)r!r"r\r#)ar+r+r, norm_joinsz&compress_for_rename..norm_joinc3s |]}tj|VqdSr.)r!r"r\rN)rQw)rootr+r,rUsc3s|]}|VqdSr.r+)rQddirnamer`rbr+r,rUsc3s|]}|VqdSr.r+)rQfrdr+r,rUs)dictr/rVvaluesrPrWr!walkupdatedifference_updater0rTmap __getitem__) rXcase_map remaining unchecked wildcards all_files all_subdirssubdirsfilesr+rdr,compress_for_renamevs6    rvc 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)rM)r!r"r#)rQfolderr+r+r, sz.compress_for_output_listing..) r/rDr0r!r"rerlr\r[rir#isfile) rX will_remove will_skipfoldersrur"_normcased_filesrxdirpath_dirfilesfnamefile_r+r+r,compress_for_output_listings4     rc@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. uninstallkind)rOSErrorrrr!r"r\)rr"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.Nrr) r!r"r\rerKeyErrorrrelpathcurdirr#)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]}tjd|q|jD]\}}zTtd||tj|sPtj|r\t|ntj |rpt |t ||Wq t k r}zt d|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)rloggerinfodebugr!r"rzrunlinkrrrrerrorr)rr^rr"exr+r+r,rollback&s     z StashedUninstallPathSet.rollbackcCs t|jSr.)boolrrr+r+r, can_rollback:sz$StashedUninstallPathSet.can_rollbackN) __name__ __module__ __qualname____doc__rrrrrrpropertyrr+r+r+r,rs rc@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/rX_refusepthr%r _moved_paths)rr%r+r+r,rCs zUninstallPathSet.__init__cCst|S)zs Return True if the given path is one we are permitted to remove/modify, False otherwise. )r)rr"r+r+r, _permittedKszUninstallPathSet._permittedcCstj|\}}tjt|tj|}tj|s:dS||rR|j |n |j |tj |ddkrt r| t |dS)Nr<)r!r"rEr#rr\existsrrXr0rsplitextr r)rr"rtailr+r+r,r0Ts   zUninstallPathSet.addcCsLt|}||r<||jkr*t||j|<|j||n |j|dSr.)rrrUninstallPthEntriesr0r)rpth_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)rXrrr% project_nameversionr _allowed_to_proceedrrvrVr[rrrrhremove)r auto_confirmverbosedist_name_versionmoved 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 rVr[)msgrXr"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)rrXr/rrvr )rrrr{r|r+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%rrrrrh)rrr+r+r,rs zUninstallPathSet.rollbackcCs|jdS)z?Remove temporary save dir: rollback will no longer be possible.N)rrrr+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|j||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+r]r+r+r,rysz-UninstallPathSet.from_dist..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./rwrFz;Egg-link {} does not match installed location of {} (at {})z)Not sure how to uninstall: %s - Check: %sscriptsz.batconsole_scripts)groupF gui_scriptsT)1rrCrrrrLsysprefix sysconfigget_pathrformatr to_filenameregg_infor!r"rgetattr _providerrDr0 has_metadata get_metadata splitlinesnormpathr#rrErerrJopenr\readlinestripAssertionErrorrmetadata_isdirmetadata_listdirr rrr 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_distN)FF)rrrrrrr0rrrrr classmethodrr+r+r+r,r@s  rc@s,eZdZddZddZddZddZd S) rcCs||_t|_d|_dSr.)filer/entries _saved_lines)rrr+r+r,rJszUninstallPthEntries.__init__cCs<tj|}tr,tj|ds,|dd}|j|dS)Nr\/)r!r"r\r splitdrivereplacerr0)rrr+r+r,r0Ps  zUninstallPthEntries.addc Cstd|jtj|js2td|jdSt|jd}| }||_ W5QRXt dd|Drpd}nd}|r|d | d s|d| d |d<|jD]>}z$td |||| d Wqtk rYqXqt|jd }||W5QRXdS) NzRemoving pth entries from %s:z.Cannot remove entries from nonexistent file {}rbcss|]}d|kVqdS)s Nr+)rQliner+r+r,rUosz-UninstallPthEntries.remove..z  zutf-8zRemoving entry: %swb)rrrr!r"rzwarningrr readlinesrrWrDencoderr ValueError writelines)rrlinesendlinerr+r+r,r`s0  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 )rrr+r+r,rs zUninstallPthEntries.rollbackN)rrrrr0rrr+r+r+r,rIsr)= __future__rr@r8loggingr!rr pip._vendorrpip._internal.exceptionsrpip._internal.locationsrrpip._internal.utils.compatrrr pip._internal.utils.loggingr pip._internal.utils.miscr r r rrrrrrpip._internal.utils.temp_dirrrpip._internal.utils.typingrtypingrrrrrrrrrZpip._vendor.pkg_resourcesr getLoggerrrr-r:rJr[rvrobjectrrrr+r+r+r,s<    ,  ,    (3o