o
    h#^                     @  sV  d dl mZ d dlZd dlZd dlZd dlZd dlmZmZ d dl	m
Z
 d dlmZmZ d dlmZmZ d dlmZmZ d dlmZ d d	lmZ d d
lmZ d dlmZmZ d dlmZmZm Z m!Z! d dl"m#Z#m$Z$ d dl%m&Z& ee'Z(d0ddZ)d1ddZ*e*d2ddZ+d3d#d$Z,d3d%d&Z-d4d(d)Z.G d*d+ d+Z/G d,d- d-Z0G d.d/ d/Z1dS )5    )annotationsN)	GeneratorIterable)cache_from_source)AnyCallable)LegacyDistutilsInstallUninstallMissingRecord)get_bin_prefixget_bin_user)BaseDistribution)WINDOWS)egg_link_path_from_location)	getLogger
indent_log)asknormalize_pathrenamesrmtree)AdjacentTempDirectoryTempDirectory)running_under_virtualenvbin_dirstrscript_nameis_guiboolreturnGenerator[str, None, None]c                 c  sZ    t j| |}|V  tsdS | dV  | dV  |r%| dV  dS | dV  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
    Nz.exez.exe.manifestz-script.pywz
-script.py)ospathjoinr   )r   r   r   exe_name r#   R/var/www/html/venv/lib/python3.10/site-packages/pip/_internal/req/req_uninstall.py_script_names   s   r%   fn)Callable[..., Generator[Any, None, None]]c                   s   t  d fdd}|S )	Nargsr   kwr   Generator[Any, None, None]c                  ?  s8    t  } | i |D ]}||vr|| |V  qd S N)setadd)r(   r)   seenitemr&   r#   r$   unique.   s   
z_unique.<locals>.unique)r(   r   r)   r   r   r*   )	functoolswraps)r&   r1   r#   r0   r$   _unique+   s   r4   distr   c                 c  s    | j }|dusJ d|  }|du rt| d|D ]7}tj||}|V  |drRtj|\}}|dd }tj||d }|V  tj||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 an error,
    with possible information from the INSTALLER file.

    https://packaging.python.org/specifications/recording-installed-packages/
    Nznot installeddistribution.py.pyc.pyo)locationiter_declared_entriesr	   r   r    r!   endswithsplit)r5   r<   entriesentryr    dnr&   baser#   r#   r$   uninstallation_paths9   s$   

rD   pathsIterable[str]set[str]c                   sJ   t jjt }t| tdD ] t fdd|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.keyc                 3  s<    | ]}  |d o t|d  kV  qdS )*N)
startswithrstriplen).0	shortpathr    sepr#   r$   	<genexpr>d   s    
zcompact.<locals>.<genexpr>)r   r    rQ   r,   sortedrM   anyr-   )rE   short_pathsshould_skipr#   rP   r$   compact[   s   
rW   c           	        s   dd | D }t |}tdd | D td}t  }dd	d
|D ]Ltfdd|D r0q"t  }t  }tD ]!\ }}| fdd|D  | fdd|D  q;|| sn|| |	tj
  q"t t|j||B S )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.
    c                 S  s   i | ]	}t j||qS r#   )r   r    normcaserN   pr#   r#   r$   
<dictcomp>t       z'compress_for_rename.<locals>.<dictcomp>c                 S  s   h | ]
}t j|d  qS )r   )r   r    r?   rY   r#   r#   r$   	<setcomp>v   s    z&compress_for_rename.<locals>.<setcomp>rH   ar   r   c                  W  s   t jt jj|  S r+   )r   r    rX   r!   )r^   r#   r#   r$   	norm_joiny   s   z&compress_for_rename.<locals>.norm_joinc                 3  s"    | ]}t j |V  qd S r+   )r   r    rX   rK   )rN   w)rootr#   r$   rR   }   s     z&compress_for_rename.<locals>.<genexpr>c                 3      | ]	} |V  qd S r+   r#   )rN   ddirnamer_   ra   r#   r$   rR          c                 3  rb   r+   r#   )rN   frd   r#   r$   rR      rf   N)r^   r   r   r   )r,   rS   valuesrM   rT   r   walkupdatedifference_updater-   rQ   map__getitem__)	rE   case_map	remaining	unchecked	wildcards	all_filesall_subdirssubdirsfilesr#   rd   r$   compress_for_renamen   s$   

rv   tuple[set[str], set[str]]c                 C  s   t | }t  }t  }t  }|D ]}|drq|ds d|v r)|tj| || qt ttjj|}t|}|D ]2}t	|D ]*\}}	}
|
D ]"}|drTqLtj
||}tj|rntj||vrn|| qLqEq>|dd |D B }||fS )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__.pyz
.dist-infoc                 S  s   h | ]	}t j|d qS )rJ   )r   r    r!   )rN   folderr#   r#   r$   r]      r\   z.compress_for_output_listing.<locals>.<setcomp>)r,   r>   r-   r   r    re   rl   rX   rW   ri   r!   isfile)rE   will_remove	will_skipfoldersru   r    _normcased_filesrx   dirpath_dirfilesfnamefile_r#   r#   r$   compress_for_output_listing   s6   



r   c                   @  sZ   e Zd ZdZdddZddd	Zdd
dZdddZdddZdddZ	e
dddZdS )StashedUninstallPathSetzWA set of file rename operations to stash files while
    tentatively uninstalling them.r   Nonec                 C  s   i | _ g | _d S r+   )
_save_dirs_movesselfr#   r#   r$   __init__   s   
z StashedUninstallPathSet.__init__r    r   c                 C  sB   zt |}W n ty   tdd}Y nw || jtj|< |jS )zStashes a directory.

        Directories are stashed adjacent to their original location if
        possible, or else moved/copied into the user's temp dir.	uninstallkind)r   OSErrorr   r   r   r    rX   )r   r    save_dirr#   r#   r$   _get_directory_stash   s   z,StashedUninstallPathSet._get_directory_stashc                 C  s   t j|}t j|d}}d}||kr3z| j| }W n& ty%   Y nw t j||}}||kst j|}tdd}|| j|< t j||}|rZ|t jjkrZt j	|j|S |jS )zStashes a file.

        If no root has been provided, one will be created for the directory
        in the user's temp directory.Nr   r   )
r   r    rX   re   r   KeyErrorr   relpathcurdirr!   )r   r    headold_headr   r   r#   r#   r$   _get_file_stash   s&   
	

z'StashedUninstallPathSet._get_file_stashc                 C  sl   t j|ot j| }|r| |}n| |}| j||f |r/t j|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    isdirislinkr   r   r   appendrmdirr   )r   r    path_is_dirnew_pathr#   r#   r$   stash   s   


zStashedUninstallPathSet.stashc                 C  s(   | j  D ]}|  qg | _i | _ dS )z0Commits the uninstall by removing stashed files.N)r   rh   cleanupr   )r   r   r#   r#   r$   commit  s   

zStashedUninstallPathSet.commitc                 C  s   | j D ]}tjdg|R   q| j D ]L\}}z*td|| tj|s*tj|r0t| n
tj	|r:t
| t|| W q ty^ } ztd| td| W Y d}~qd}~ww |   dS )z2Undoes the uninstall by moving stashed files back.zMoving to %s
 from %szReplacing %s from %szFailed to restore %szException: %sN)r   loggerinfodebugr   r    ry   r   unlinkr   r   r   r   errorr   )r   rZ   r   r    exr#   r#   r$   rollback  s    
z StashedUninstallPathSet.rollbackr   c                 C  s
   t | jS r+   )r   r   r   r#   r#   r$   can_rollback%  s   
z$StashedUninstallPathSet.can_rollbackNr   r   )r    r   r   r   r   r   )__name__
__module____qualname____doc__r   r   r   r   r   r   propertyr   r#   r#   r#   r$   r      s    





r   c                   @  sp   e Zd ZdZd!ddZd"ddZd#ddZd$ddZd%d&ddZd'ddZ	d(ddZ
d(ddZed)ddZd S )*UninstallPathSetzMA set of file paths to be removed in the uninstallation of a
    requirement.r5   r   r   r   c                 C  s4   t  | _t  | _i | _|| _t | _tt	| _
d S r+   )r,   _paths_refuse_pth_distr   _moved_pathsr2   	lru_cacher   _normalize_path_cached)r   r5   r#   r#   r$   r   .  s   zUninstallPathSet.__init__r    r   r   c                 C  s   t  sdS || tjS )zs
        Return True if the given path is one we are permitted to
        remove/modify, False otherwise.

        T)r   rK   r   sysprefix)r   r    r#   r#   r$   
_permitted9  s   zUninstallPathSet._permittedc                 C  s   t j|\}}t j| |t j|}t j|sd S | |r*| j	| n| j
	| t j|d dkrC| 	t| d S d S )N   r8   )r   r    r?   r!   r   rX   existsr   r   r-   r   splitextr   )r   r    r   tailr#   r#   r$   r-   D  s   
zUninstallPathSet.addpth_filerA   c                 C  sP   |  |}| |r || jvrt|| j|< | j| | d S | j| d S r+   )r   r   r   UninstallPthEntriesr-   r   )r   r   rA   r#   r#   r$   add_pthW  s   


zUninstallPathSet.add_pthFauto_confirmverbosec                 C  s   | j std| jj dS | jj d| jj }td| t F |s)| |r_| j}t	| j }t
t|D ]}|| td| q7| j D ]}|  qJtd| W d   dS W d   dS 1 sjw   Y  dS )z\Remove paths in ``self._paths`` with confirmation (unless
        ``auto_confirm`` is True).z7Can't uninstall '%s'. No files were found to uninstall.N-zUninstalling %s:zRemoving file or directory %szSuccessfully uninstalled %s)r   r   r   r   raw_nameraw_versionr   _allowed_to_proceedr   rv   rS   rW   r   r   r   rh   remove)r   r   r   dist_name_versionmoved
for_renamer    pthr#   r#   r$   r   `  s*   


"zUninstallPathSet.removec                 C  sp   ddd}|st | j\}}nt| j}t }|d	| |d
| |d| j |r1|dt| j tdddkS )z@Display which files would be deleted and prompt for confirmationmsgr   rE   rF   r   r   c                 S  sZ   |sd S t |  t  tt|D ]}t | qW d    d S 1 s&w   Y  d S r+   )r   r   r   rS   rW   )r   rE   r    r#   r#   r$   _display  s   
"z6UninstallPathSet._allowed_to_proceed.<locals>._displayzWould remove:z+Would not remove (might be manually added):z%Would not remove (outside of prefix):zWill actually move:zProceed (Y/n)? )yn r   N)r   r   rE   rF   r   r   )r   r   r,   r   rv   r   )r   r   r   rz   r{   r#   r#   r$   r   }  s   
	


z$UninstallPathSet._allowed_to_proceedc                 C  sR   | j jstd| jj dS td| jj | j   | j	 D ]}|  q dS )z1Rollback the changes previously made by remove().z'Can't roll back %s; was not uninstalledNzRolling back uninstall of %s)
r   r   r   r   r   r   r   r   r   rh   )r   r   r#   r#   r$   r     s   

zUninstallPathSet.rollbackc                 C  s   | j   dS )z?Remove temporary save dir: rollback will no longer be possible.N)r   r   r   r#   r#   r$   r     s   zUninstallPathSet.commitc              
     s  |j }|j}|d u rtd|j | |S t|}|js*td|j|tj | |S |dd t	
dt	
dhD v rGtd|j| | |S | |}t|j}|jof|d uoftj|of||j d }|r|d urr|| | }|d ur|D ]}	|tj||	 q|n|d	rz|d
}
W n ty   g  Y nw |
jdd  fdd|d	 D D ]&}tj||}|| || d || d || d qn|jrt|d|jr|| tj|d }tjtj|d}||d|  nq|j rt!|D ]}|| qn_|rut"|}tj#|$ % }|&|}W d    n	1 s?w   Y  tj'||s^J d| d| d|j d| d	|| tjtj|d}||| nt(d|| |j)rt* }nt+ }z$|, D ]}|tj|| t-r|tj|| d qW n tt.fy   Y nw d%d#d$}|||D ]}|| q|S )&Nz-Not uninstalling %s since it is not installedz1Not uninstalling %s at %s, outside environment %sc                 S  s   h | ]}|r|qS r#   r#   rY   r#   r#   r$   r]     s    z-UninstallPathSet.from_dist.<locals>.<setcomp>stdlib
platstdlibz<Not uninstalling %s at %s, as it is in the standard library.z	.egg-infoztop_level.txtznamespace_packages.txtF)keependsc                   s   g | ]
}|r| vr|qS r#   r#   rY   
namespacesr#   r$   
<listcomp>  s    z.UninstallPathSet.from_dist.<locals>.<listcomp>r8   r:   r;   r6   r   zeasy-install.pthz./z	Egg-link z (to z') does not match installed location of z (at )z)Not sure how to uninstall: %s - Check: %sz.batr5   r   r   r   r   r   c                 s  sR    |   D ]!}|jdkrt||jdE d H  q|jdkr&t||jdE d H  qd S )Nconsole_scriptsFgui_scriptsT)iter_entry_pointsgroupr%   name)r5   r   entry_pointr#   r#   r$   iter_scripts_to_remove8  s   

z:UninstallPathSet.from_dist.<locals>.iter_scripts_to_remove)r5   r   r   r   r   r   )/r<   info_locationr   r   canonical_namer   localr   r   	sysconfigget_pathr   r   "installed_with_setuptools_egg_infor   r    r   r>   setuptools_filenamer-   r=   r!   is_file	read_textFileNotFoundError
splitlinesinstalled_by_distutilsr   installed_as_eggr?   re   r   installed_with_dist_inforD   openrX   readlinestripr   samefiler   in_usersiter   r
   iter_distutils_script_namesr   NotADirectoryError)clsr5   dist_locationr   normalized_dist_locationpaths_to_removedevelop_egg_linksetuptools_flat_installationinstalled_filesinstalled_filenamespace_packagestop_level_pkgr    easy_install_eggeasy_install_pthfhlink_pointernormalized_link_pointerr   scriptr   sr#   r   r$   	from_dist  s   













zUninstallPathSet.from_distN)r5   r   r   r   )r    r   r   r   )r    r   r   r   )r   r   rA   r   r   r   )FF)r   r   r   r   r   r   )r   r   r   r   r   )r5   r   r   r   )r   r   r   r   r   r   r-   r   r   r   r   r   classmethodr  r#   r#   r#   r$   r   *  s    



	


r   c                   @  s4   e Zd ZdddZddd	Zdd
dZdddZdS )r   r   r   r   r   c                 C  s   || _ t | _d | _d S r+   )filer,   r@   _saved_lines)r   r   r#   r#   r$   r   I  s   
zUninstallPthEntries.__init__rA   c                 C  s<   t j|}trt j|d s|dd}| j| d S )Nr   \/)r   r    rX   r   
splitdrivereplacer@   r-   )r   rA   r#   r#   r$   r-   N  s   
zUninstallPthEntries.addc              	   C  s0  t d| j tj| jst d| j d S t| jd}| }|| _	W d    n1 s/w   Y  t
dd |D r@d}nd}|rY|d |d	sY|d |d	 |d< | jD ]}zt d
| ||| d	 W q\ tyy   Y q\w t| jd}|| W d    d S 1 sw   Y  d S )NzRemoving pth entries from %s:z.Cannot remove entries from nonexistent file %srbc                 s  s    | ]}d |v V  qdS )s   
Nr#   )rN   liner#   r#   r$   rR   h  s    z-UninstallPthEntries.remove.<locals>.<genexpr>z

zutf-8zRemoving entry: %swb)r   r   r  r   r    ry   warningr   	readlinesr  rT   r>   encoder@   r   
ValueError
writelines)r   r   linesendlinerA   r#   r#   r$   r   ]  s.   
"zUninstallPthEntries.remover   c                 C  sh   | j d u rtd| j dS td| j t| jd}|| j  W d    dS 1 s-w   Y  dS )Nz.Cannot roll back changes to %s, none were madeFz!Rolling %s back to previous stater  T)r  r   r   r  r   r   r  )r   r   r#   r#   r$   r   x  s   

zUninstallPthEntries.rollbackN)r   r   r   r   )rA   r   r   r   r   r   )r   r   r   r   r-   r   r   r#   r#   r#   r$   r   H  s
    


r   )r   r   r   r   r   r   r   r   )r&   r'   r   r'   )r5   r   r   r   )rE   rF   r   rG   )rE   rF   r   rw   )2
__future__r   r2   r   r   r   collections.abcr   r   importlib.utilr   typingr   r   pip._internal.exceptionsr   r	   pip._internal.locationsr
   r   pip._internal.metadatar   pip._internal.utils.compatr   pip._internal.utils.egg_linkr   pip._internal.utils.loggingr   r   pip._internal.utils.miscr   r   r   r   pip._internal.utils.temp_dirr   r   pip._internal.utils.virtualenvr   r   r   r%   r4   rD   rW   rv   r   r   r   r   r#   r#   r#   r$   <module>   s<    


!

"1i   