Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove --no-binary disabling wheel cache #11872

Merged
merged 3 commits into from
Mar 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions news/11453.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
``--no-binary`` does not disable the cache of locally built wheels anymore. It only
means "don't download wheels".
41 changes: 10 additions & 31 deletions src/pip/_internal/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
import logging
import os
from pathlib import Path
from typing import Any, Dict, List, Optional, Set
from typing import Any, Dict, List, Optional

from pip._vendor.packaging.tags import Tag, interpreter_name, interpreter_version
from pip._vendor.packaging.utils import canonicalize_name

from pip._internal.exceptions import InvalidWheelFilename
from pip._internal.models.direct_url import DirectUrl
from pip._internal.models.format_control import FormatControl
from pip._internal.models.link import Link
from pip._internal.models.wheel import Wheel
from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds
Expand All @@ -33,25 +32,13 @@ def _hash_dict(d: Dict[str, str]) -> str:
class Cache:
"""An abstract class - provides cache directories for data from links


:param cache_dir: The root of the cache.
:param format_control: An object of FormatControl class to limit
binaries being read from the cache.
:param allowed_formats: which formats of files the cache should store.
('binary' and 'source' are the only allowed values)
"""

def __init__(
self, cache_dir: str, format_control: FormatControl, allowed_formats: Set[str]
) -> None:
def __init__(self, cache_dir: str) -> None:
super().__init__()
assert not cache_dir or os.path.isabs(cache_dir)
self.cache_dir = cache_dir or None
self.format_control = format_control
self.allowed_formats = allowed_formats

_valid_formats = {"source", "binary"}
assert self.allowed_formats.union(_valid_formats) == _valid_formats

def _get_cache_path_parts(self, link: Link) -> List[str]:
"""Get parts of part that must be os.path.joined with cache_dir"""
Expand Down Expand Up @@ -91,10 +78,6 @@ def _get_candidates(self, link: Link, canonical_package_name: str) -> List[Any]:
if can_not_cache:
return []

formats = self.format_control.get_allowed_formats(canonical_package_name)
if not self.allowed_formats.intersection(formats):
return []

candidates = []
path = self.get_path_for_link(link)
if os.path.isdir(path):
Expand All @@ -121,8 +104,8 @@ def get(
class SimpleWheelCache(Cache):
"""A cache of wheels for future installs."""

def __init__(self, cache_dir: str, format_control: FormatControl) -> None:
super().__init__(cache_dir, format_control, {"binary"})
def __init__(self, cache_dir: str) -> None:
super().__init__(cache_dir)

def get_path_for_link(self, link: Link) -> str:
"""Return a directory to store cached wheels for link
Expand Down Expand Up @@ -191,13 +174,13 @@ def get(
class EphemWheelCache(SimpleWheelCache):
"""A SimpleWheelCache that creates it's own temporary cache directory"""

def __init__(self, format_control: FormatControl) -> None:
def __init__(self) -> None:
self._temp_dir = TempDirectory(
kind=tempdir_kinds.EPHEM_WHEEL_CACHE,
globally_managed=True,
)

super().__init__(self._temp_dir.path, format_control)
super().__init__(self._temp_dir.path)


class CacheEntry:
Expand All @@ -221,14 +204,10 @@ class WheelCache(Cache):
when a certain link is not found in the simple wheel cache first.
"""

def __init__(
self, cache_dir: str, format_control: Optional[FormatControl] = None
) -> None:
if format_control is None:
format_control = FormatControl()
super().__init__(cache_dir, format_control, {"binary"})
self._wheel_cache = SimpleWheelCache(cache_dir, format_control)
self._ephem_cache = EphemWheelCache(format_control)
def __init__(self, cache_dir: str) -> None:
super().__init__(cache_dir)
self._wheel_cache = SimpleWheelCache(cache_dir)
self._ephem_cache = EphemWheelCache()

def get_path_for_link(self, link: Link) -> str:
return self._wheel_cache.get_path_for_link(link)
Expand Down
9 changes: 9 additions & 0 deletions src/pip/_internal/cli/base_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ def _main(self, args: List[str]) -> int:
user_log_file=options.log,
)

always_enabled_features = set(options.features_enabled) & set(
cmdoptions.ALWAYS_ENABLED_FEATURES
)
if always_enabled_features:
logger.warning(
"The following features are always enabled: %s. ",
", ".join(sorted(always_enabled_features)),
)

# TODO: Try to get these passing down from the command?
# without resorting to os.environ to hold these.
# This also affects isolated builds and it should.
Expand Down
9 changes: 7 additions & 2 deletions src/pip/_internal/cli/cmdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,11 @@ def check_list_path_option(options: Values) -> None:
)


# Features that are now always on. A warning is printed if they are used.
ALWAYS_ENABLED_FEATURES = [
"no-binary-enable-wheel-cache", # always on since 23.1
]

use_new_feature: Callable[..., Option] = partial(
Option,
"--use-feature",
Expand All @@ -1004,8 +1009,8 @@ def check_list_path_option(options: Values) -> None:
choices=[
"fast-deps",
"truststore",
"no-binary-enable-wheel-cache",
],
]
+ ALWAYS_ENABLED_FEATURES,
help="Enable new functionality, that may be backward incompatible.",
)

Expand Down
24 changes: 2 additions & 22 deletions src/pip/_internal/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@
check_legacy_setup_py_options,
)
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.deprecation import (
LegacyInstallReasonFailedBdistWheel,
deprecated,
)
from pip._internal.utils.deprecation import LegacyInstallReasonFailedBdistWheel
from pip._internal.utils.filesystem import test_writable_dir
from pip._internal.utils.logging import getLogger
from pip._internal.utils.misc import (
Expand Down Expand Up @@ -346,24 +343,7 @@ def run(self, options: Values, args: List[str]) -> int:
reqs = self.get_requirements(args, options, finder, session)
check_legacy_setup_py_options(options, reqs)

if "no-binary-enable-wheel-cache" in options.features_enabled:
# TODO: remove format_control from WheelCache when the deprecation cycle
# is over
wheel_cache = WheelCache(options.cache_dir)
else:
if options.format_control.no_binary:
deprecated(
reason=(
"--no-binary currently disables reading from "
"the cache of locally built wheels. In the future "
"--no-binary will not influence the wheel cache."
),
replacement="to use the --no-cache-dir option",
feature_flag="no-binary-enable-wheel-cache",
issue=11453,
gone_in="23.1",
)
wheel_cache = WheelCache(options.cache_dir, options.format_control)
wheel_cache = WheelCache(options.cache_dir)

# Only when installing is it permitted to use PEP 660.
# In other circumstances (pip wheel, pip download) we generate
Expand Down
21 changes: 1 addition & 20 deletions src/pip/_internal/commands/wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
InstallRequirement,
check_legacy_setup_py_options,
)
from pip._internal.utils.deprecation import deprecated
from pip._internal.utils.misc import ensure_dir, normalize_path
from pip._internal.utils.temp_dir import TempDirectory
from pip._internal.wheel_builder import build, should_build_for_wheel_command
Expand Down Expand Up @@ -106,7 +105,6 @@ def run(self, options: Values, args: List[str]) -> int:
session = self.get_default_session(options)

finder = self._build_package_finder(options, session)
wheel_cache = WheelCache(options.cache_dir, options.format_control)

options.wheel_dir = normalize_path(options.wheel_dir)
ensure_dir(options.wheel_dir)
Expand All @@ -122,24 +120,7 @@ def run(self, options: Values, args: List[str]) -> int:
reqs = self.get_requirements(args, options, finder, session)
check_legacy_setup_py_options(options, reqs)

if "no-binary-enable-wheel-cache" in options.features_enabled:
# TODO: remove format_control from WheelCache when the deprecation cycle
# is over
wheel_cache = WheelCache(options.cache_dir)
else:
if options.format_control.no_binary:
deprecated(
reason=(
"--no-binary currently disables reading from "
"the cache of locally built wheels. In the future "
"--no-binary will not influence the wheel cache."
),
replacement="to use the --no-cache-dir option",
feature_flag="no-binary-enable-wheel-cache",
issue=11453,
gone_in="23.1",
)
wheel_cache = WheelCache(options.cache_dir, options.format_control)
wheel_cache = WheelCache(options.cache_dir)

preparer = self.make_requirement_preparer(
temp_build_dir=directory,
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -1656,7 +1656,7 @@ def test_install_no_binary_uses_local_backend(
assert os.path.isfile(marker), "Local PEP 517 backend not used"


def test_install_no_binary_disables_cached_wheels(
def test_install_no_binary_uses_cached_wheels(
script: PipTestEnvironment, data: TestData
) -> None:
# Seed the cache
Expand All @@ -1673,7 +1673,7 @@ def test_install_no_binary_disables_cached_wheels(
)
assert "Successfully installed upper-2.0" in str(res), str(res)
# upper is built and not obtained from cache
assert "Building wheel for upper" in str(res), str(res)
assert "Building wheel for upper" not in str(res), str(res)


def test_install_editable_with_wrong_egg_name(
Expand Down
11 changes: 5 additions & 6 deletions tests/unit/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,20 @@
from pip._vendor.packaging.tags import Tag, interpreter_name, interpreter_version

from pip._internal.cache import WheelCache, _hash_dict
from pip._internal.models.format_control import FormatControl
from pip._internal.models.link import Link
from pip._internal.utils.misc import ensure_dir


def test_falsey_path_none() -> None:
wc = WheelCache("", FormatControl())
wc = WheelCache("")
assert wc.cache_dir is None


def test_subdirectory_fragment() -> None:
"""
Test the subdirectory URL fragment is part of the cache key.
"""
wc = WheelCache("/tmp/.foo/", FormatControl())
wc = WheelCache("/tmp/.foo/")
link1 = Link("git+https://g.c/o/r#subdirectory=d1")
link2 = Link("git+https://g.c/o/r#subdirectory=d2")
assert wc.get_path_for_link(link1) != wc.get_path_for_link(link2)
Expand All @@ -29,7 +28,7 @@ def test_wheel_name_filter(tmpdir: Path) -> None:
Test the wheel cache filters on wheel name when several wheels
for different package are stored under the same cache directory.
"""
wc = WheelCache(os.fspath(tmpdir), FormatControl())
wc = WheelCache(os.fspath(tmpdir))
link = Link("https://g.c/package.tar.gz")
cache_path = wc.get_path_for_link(link)
ensure_dir(cache_path)
Expand Down Expand Up @@ -57,7 +56,7 @@ def test_link_to_cache(tmpdir: Path) -> None:
Test that Link.from_json() produces Links with consistent cache
locations
"""
wc = WheelCache(os.fspath(tmpdir), FormatControl())
wc = WheelCache(os.fspath(tmpdir))
# Define our expectations for stable cache path.
i_name = interpreter_name()
i_version = interpreter_version()
Expand Down Expand Up @@ -95,7 +94,7 @@ def test_link_to_cache(tmpdir: Path) -> None:


def test_get_cache_entry(tmpdir: Path) -> None:
wc = WheelCache(os.fspath(tmpdir), FormatControl())
wc = WheelCache(os.fspath(tmpdir))
persi_link = Link("https://g.c/o/r/persi")
persi_path = wc.get_path_for_link(persi_link)
ensure_dir(persi_path)
Expand Down
5 changes: 2 additions & 3 deletions tests/unit/test_req.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
from pip._internal.index.package_finder import PackageFinder
from pip._internal.metadata import select_backend
from pip._internal.models.direct_url import ArchiveInfo, DirectUrl, DirInfo, VcsInfo
from pip._internal.models.format_control import FormatControl
from pip._internal.models.link import Link
from pip._internal.network.session import PipSession
from pip._internal.operations.build.build_tracker import get_build_tracker
Expand Down Expand Up @@ -403,7 +402,7 @@ def test_download_info_archive_legacy_cache(
"""Test download_info hash is not set for an archive with legacy cache entry."""
url = shared_data.packages.joinpath("simple-1.0.tar.gz").as_uri()
finder = make_test_finder()
wheel_cache = WheelCache(str(tmp_path / "cache"), FormatControl())
wheel_cache = WheelCache(str(tmp_path / "cache"))
cache_entry_dir = wheel_cache.get_path_for_link(Link(url))
Path(cache_entry_dir).mkdir(parents=True)
wheel.make_wheel(name="simple", version="1.0").save_to_dir(cache_entry_dir)
Expand All @@ -426,7 +425,7 @@ def test_download_info_archive_cache_with_origin(
url = shared_data.packages.joinpath("simple-1.0.tar.gz").as_uri()
hash = "sha256=ad977496000576e1b6c41f6449a9897087ce9da6db4f15b603fe8372af4bf3c6"
finder = make_test_finder()
wheel_cache = WheelCache(str(tmp_path / "cache"), FormatControl())
wheel_cache = WheelCache(str(tmp_path / "cache"))
cache_entry_dir = wheel_cache.get_path_for_link(Link(url))
Path(cache_entry_dir).mkdir(parents=True)
Path(cache_entry_dir).joinpath("origin.json").write_text(
Expand Down