Compare commits

...

7 Commits

Author SHA1 Message Date
Ellen Marie Dash 7ea4857612
Merge 4d0d414ea8 into a15dd75d98 2023-12-13 16:45:58 +01:00
Tzu-ping Chung a15dd75d98
Merge pull request #12417 from xqm32/fix-outdated-pip-install 2023-11-28 16:08:29 +09:00
Tzu-ping Chung d8ab6dc6c1 Clarify news fragment 2023-11-28 15:06:25 +08:00
Qiming Xu fe10d368f6
Add end line 2023-11-28 14:25:56 +08:00
Qiming Xu 28250baffb
Fix line wrap length and add news entry 2023-11-28 14:17:51 +08:00
Qiming Xu 88ac529219
Fix outdated pip install argument description 2023-11-28 13:15:31 +08:00
Ellen Marie Dash 4d0d414ea8 [commands/cache] make `pip cache purge` remove everything from http + wheels caches; make `pip cache remove` prune empty directories. 2023-04-09 00:58:45 -04:00
4 changed files with 69 additions and 2 deletions

View File

@ -45,8 +45,8 @@ When looking at the items to be installed, pip checks what type of item
each is, in the following order:
1. Project or archive URL.
2. Local directory (which must contain a ``setup.py``, or pip will report
an error).
2. Local directory (which must contain a ``pyproject.toml`` or ``setup.py``,
otherwise pip will report an error).
3. Local file (a sdist or wheel format archive, following the naming
conventions for those formats).
4. A requirement, as specified in :pep:`440`.

1
news/12417.doc.rst Normal file
View File

@ -0,0 +1 @@
Fix outdated pip install argument description in documentation.

View File

@ -183,7 +183,24 @@ class CacheCommand(Command):
for filename in files:
os.unlink(filename)
logger.verbose("Removed %s", filename)
http_dirs = filesystem.subdirs_with_no_files(self._cache_dir(options, "http"))
wheel_dirs = filesystem.subdirs_with_no_files(
self._cache_dir(options, "wheels")
)
dirs = list(http_dirs) + list(wheel_dirs)
for dirname in dirs:
os.rmdir(dirname)
logger.verbose("Removed %s", dirname)
# selfcheck.json is no longer used by pip.
selfcheck_json = self._cache_dir(options, "selfcheck.json")
if os.path.isfile(selfcheck_json):
os.remove(selfcheck_json)
logger.verbose("Removed legacy selfcheck.json file")
logger.info("Files removed: %s", len(files))
logger.info("Empty directories removed: %s", len(dirs))
def purge_cache(self, options: Values, args: List[Any]) -> None:
if args:

View File

@ -4,11 +4,13 @@ import os.path
import random
import sys
from contextlib import contextmanager
from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import Any, BinaryIO, Generator, List, Union, cast
from pip._vendor.tenacity import retry, stop_after_delay, wait_fixed
from pip._internal.exceptions import PipError
from pip._internal.utils.compat import get_path_uid
from pip._internal.utils.misc import format_size
@ -151,3 +153,50 @@ def directory_size(path: str) -> Union[int, float]:
def format_directory_size(path: str) -> str:
return format_size(directory_size(path))
def _leaf_subdirs(path):
"""Traverses the file tree, finding every empty directory."""
path_obj = Path(path)
if not path_obj.exists():
return
for item in path_obj.iterdir():
if not item.is_dir():
continue
subitems = item.iterdir()
# ASSUMPTION: Nothing in subitems will be None or False.
if not any(subitems):
yield item
if not any(subitem.is_file() for subitem in subitems):
yield from _leaf_subdirs(item)
def _leaf_parents_without_files(path, leaf):
"""Yields +leaf+ and each parent directory below +path+, until one of
them includes a file (as opposed to directories or nothing)."""
if not str(leaf).startswith(str(path)):
# If +leaf+ is not a subdirectory of +path+, bail early to avoid
# an endless loop.
raise PipError("leaf is not a subdirectory of path")
path = Path(path)
leaf = Path(leaf)
while leaf != path:
if all(item.is_dir() for item in leaf.iterdir()):
yield str(leaf)
else:
break
leaf = leaf.parent
def subdirs_with_no_files(path):
"""Yields every subdirectory of +path+ that has no files under it."""
for leaf in _leaf_subdirs(path):
yield from _leaf_parents_without_files(path, leaf)