1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

cache normalize_path in req_uninstall and is_local

This commit is contained in:
Ryan Shepherd 2023-03-16 10:54:11 -07:00 committed by Stéphane Bidoul
parent 5d4a974b60
commit d46fd99de8
2 changed files with 20 additions and 6 deletions

View file

@ -11,7 +11,7 @@ from pip._internal.metadata import BaseDistribution
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.egg_link import egg_link_path_from_location
from pip._internal.utils.logging import getLogger, indent_log
from pip._internal.utils.misc import ask, is_local, normalize_path, renames, rmtree
from pip._internal.utils.misc import ask, is_local, normalize_path, normalize_path_cached, renames, rmtree
from pip._internal.utils.temp_dir import AdjacentTempDirectory, TempDirectory
logger = getLogger(__name__)
@ -312,6 +312,7 @@ class UninstallPathSet:
self._pth: Dict[str, UninstallPthEntries] = {}
self._dist = dist
self._moved_paths = StashedUninstallPathSet()
normalize_path_cached.cache_clear()
def _permitted(self, path: str) -> bool:
"""
@ -326,7 +327,7 @@ class UninstallPathSet:
# we normalize the head to resolve parent directory symlinks, but not
# the tail, since we only want to uninstall symlinks, not their targets
path = os.path.join(normalize_path(head), os.path.normcase(tail))
path = os.path.join(normalize_path_cached(head), os.path.normcase(tail))
if not os.path.exists(path):
return
@ -341,7 +342,7 @@ class UninstallPathSet:
self.add(cache_from_source(path))
def add_pth(self, pth_file: str, entry: str) -> None:
pth_file = normalize_path(pth_file)
pth_file = normalize_path_cached(pth_file)
if self._permitted(pth_file):
if pth_file not in self._pth:
self._pth[pth_file] = UninstallPthEntries(pth_file)
@ -434,7 +435,7 @@ class UninstallPathSet:
)
return cls(dist)
normalized_dist_location = normalize_path(dist_location)
normalized_dist_location = normalize_path_cached(dist_location)
if not dist.local:
logger.info(
"Not uninstalling %s at %s, outside environment %s",
@ -531,7 +532,7 @@ class UninstallPathSet:
# above, so this only covers the setuptools-style editable.
with open(develop_egg_link) as fh:
link_pointer = os.path.normcase(fh.readline().strip())
normalized_link_pointer = normalize_path(link_pointer)
normalized_link_pointer = normalize_path_cached(link_pointer)
assert os.path.samefile(
normalized_link_pointer, normalized_dist_location
), (

View file

@ -3,6 +3,7 @@
import contextlib
import errno
import functools
import getpass
import hashlib
import io
@ -294,6 +295,17 @@ def normalize_path(path: str, resolve_symlinks: bool = True) -> str:
return os.path.normcase(path)
@functools.lru_cache
def normalize_path_cached(path: str, resolve_symlinks: bool = True) -> str:
"""
Cache the results of normalize_path when called frequently during certain
operations. Separate function because it is probably unsafe to
cache normalize_path in the general case, e.g. symlinks can be changed
while the process is running.
"""
return normalize_path(str, resolve_symlinks)
def splitext(path: str) -> Tuple[str, str]:
"""Like os.path.splitext, but take off .tar too"""
base, ext = posixpath.splitext(path)
@ -331,7 +343,8 @@ def is_local(path: str) -> bool:
"""
if not running_under_virtualenv():
return True
return path.startswith(normalize_path(sys.prefix))
# Safe to call cached because sys.prefix shouldn't change
return path.startswith(normalize_path_cached(sys.prefix))
def write_output(msg: Any, *args: Any) -> None: