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

Add --cache-dir option to pip-compile #1022

Merged
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
5 changes: 1 addition & 4 deletions piptools/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from pip._vendor.packaging.requirements import Requirement

from .exceptions import PipToolsError
from .locations import CACHE_DIR
from .utils import as_tuple, key_from_req, lookup_table


Expand Down Expand Up @@ -49,9 +48,7 @@ class DependencyCache(object):
Where X.Y indicates the Python version.
"""

def __init__(self, cache_dir=None):
if cache_dir is None:
cache_dir = CACHE_DIR
def __init__(self, cache_dir):
if not os.path.isdir(cache_dir):
os.makedirs(cache_dir)
py_version = ".".join(str(digit) for digit in sys.version_info[:2])
Expand Down
10 changes: 5 additions & 5 deletions piptools/repositories/pypi.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
path_to_url,
url_to_path,
)
from ..cache import CACHE_DIR
from ..click import progressbar
from ..exceptions import NoCandidateFound
from ..logging import log
Expand Down Expand Up @@ -54,7 +53,7 @@ class PyPIRepository(BaseRepository):
changed/configured on the Finder.
"""

def __init__(self, pip_args, build_isolation=False):
def __init__(self, pip_args, cache_dir, build_isolation=False):
self.build_isolation = build_isolation

# Use pip's parser for pip.conf management and defaults.
Expand All @@ -81,8 +80,9 @@ def __init__(self, pip_args, build_isolation=False):

# Setup file paths
self.freshen_build_caches()
self._download_dir = fs_str(os.path.join(CACHE_DIR, "pkgs"))
self._wheel_download_dir = fs_str(os.path.join(CACHE_DIR, "wheels"))
self._cache_dir = cache_dir
self._download_dir = fs_str(os.path.join(self._cache_dir, "pkgs"))
self._wheel_download_dir = fs_str(os.path.join(self._cache_dir, "wheels"))

def freshen_build_caches(self):
"""
Expand Down Expand Up @@ -262,7 +262,7 @@ def get_dependencies(self, ireq):
if not os.path.isdir(self._wheel_download_dir):
os.makedirs(self._wheel_download_dir)

wheel_cache = WheelCache(CACHE_DIR, self.options.format_control)
wheel_cache = WheelCache(self._cache_dir, self.options.format_control)
prev_tracker = os.environ.get("PIP_REQ_TRACKER")
try:
self._dependencies_cache[ireq] = self.resolve_reqs(
Expand Down
5 changes: 1 addition & 4 deletions piptools/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from . import click
from ._compat import install_req_from_line
from .cache import DependencyCache
from .logging import log
from .utils import (
UNSAFE_PACKAGES,
Expand Down Expand Up @@ -95,7 +94,7 @@ def __init__(
self,
constraints,
repository,
cache=None,
cache,
prereleases=False,
clear_caches=False,
allow_unsafe=False,
Expand All @@ -108,8 +107,6 @@ def __init__(
self.our_constraints = set(constraints)
self.their_constraints = set()
self.repository = repository
if cache is None:
cache = DependencyCache() # pragma: no cover
self.dependency_cache = cache
self.prereleases = prereleases
self.clear_caches = clear_caches
Expand Down
17 changes: 16 additions & 1 deletion piptools/scripts/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

from .. import click
from .._compat import install_req_from_line, parse_requirements
from ..cache import DependencyCache
from ..exceptions import PipToolsError
from ..locations import CACHE_DIR
from ..logging import log
from ..repositories import LocalRequirementsRepository, PyPIRepository
from ..resolver import Resolver
Expand Down Expand Up @@ -172,6 +174,15 @@
default=True,
help="Add the find-links option to generated file",
)
@click.option(
"--cache-dir",
help="Store the cache data in DIRECTORY.",
default=CACHE_DIR,
envvar="PIP_TOOLS_CACHE_DIR",
show_default=True,
show_envvar=True,
type=click.Path(file_okay=False, writable=True),
)
atugushev marked this conversation as resolved.
Show resolved Hide resolved
def cli(
ctx,
verbose,
Expand All @@ -198,6 +209,7 @@ def cli(
max_rounds,
build_isolation,
emit_find_links,
cache_dir,
atugushev marked this conversation as resolved.
Show resolved Hide resolved
):
"""Compiles requirements.txt from requirements.in specs."""
log.verbosity = verbose - quiet
Expand Down Expand Up @@ -260,7 +272,9 @@ def cli(
for host in trusted_host:
pip_args.extend(["--trusted-host", host])

repository = PyPIRepository(pip_args, build_isolation=build_isolation)
repository = PyPIRepository(
pip_args, build_isolation=build_isolation, cache_dir=cache_dir
)

# Parse all constraints coming from --upgrade-package/-P
upgrade_reqs_gen = (install_req_from_line(pkg) for pkg in upgrade_packages)
Expand Down Expand Up @@ -353,6 +367,7 @@ def cli(
constraints,
repository,
prereleases=repository.finder.allow_all_prereleases or pre,
cache=DependencyCache(cache_dir),
clear_caches=rebuild,
allow_unsafe=allow_unsafe,
)
Expand Down
1 change: 1 addition & 0 deletions piptools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"--upgrade",
"--upgrade-package",
"--verbose",
"--cache-dir",
}


Expand Down
7 changes: 5 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,11 @@ def repository():


@fixture
def pypi_repository():
return PyPIRepository(["--index-url", PyPIRepository.DEFAULT_INDEX_URL])
def pypi_repository(tmpdir):
return PyPIRepository(
["--index-url", PyPIRepository.DEFAULT_INDEX_URL],
cache_dir=str(tmpdir / "pypi-repo"),
)


@fixture
Expand Down
38 changes: 20 additions & 18 deletions tests/test_cli_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import mock
import pytest
from click.testing import CliRunner
from pytest import mark

from .constants import MINIMAL_WHEELS_PATH, PACKAGES_PATH
Expand All @@ -15,6 +14,11 @@
from piptools.scripts.compile import cli


@pytest.fixture(autouse=True)
def temp_dep_cache(tmpdir, monkeypatch):
monkeypatch.setenv("PIP_TOOLS_CACHE_DIR", str(tmpdir / "cache"))


def test_default_pip_conf_read(pip_with_index_conf, runner):
# preconditions
with open("requirements.in", "w"):
Expand Down Expand Up @@ -69,13 +73,13 @@ def test_command_line_setuptools_read(pip_conf, runner):
(["setup.py", "--output-file", "output.txt"], "output.txt"),
],
)
def test_command_line_setuptools_output_file(pip_conf, options, expected_output_file):
def test_command_line_setuptools_output_file(
pip_conf, runner, options, expected_output_file
):
"""
Test the output files for setup.py as a requirement file.
"""
runner = CliRunner(mix_stderr=False)
with runner.isolated_filesystem():
package = open("setup.py", "w")
with open("setup.py", "w") as package:
package.write(
dedent(
"""\
Expand All @@ -84,11 +88,10 @@ def test_command_line_setuptools_output_file(pip_conf, options, expected_output_
"""
)
)
package.close()

out = runner.invoke(cli, options)
assert out.exit_code == 0
assert os.path.exists(expected_output_file)
out = runner.invoke(cli, options)
assert out.exit_code == 0
assert os.path.exists(expected_output_file)


def test_find_links_option(runner):
Expand Down Expand Up @@ -235,15 +238,14 @@ def test_locally_available_editable_package_is_not_archived_in_cache_dir(
fake_package_dir = os.path.join(PACKAGES_PATH, "small_fake_with_deps")
fake_package_dir = path_to_url(fake_package_dir)

with mock.patch("piptools.repositories.pypi.CACHE_DIR", new=str(cache_dir)):
with open("requirements.in", "w") as req_in:
req_in.write("-e " + fake_package_dir) # require editable fake package
with open("requirements.in", "w") as req_in:
req_in.write("-e " + fake_package_dir) # require editable fake package

out = runner.invoke(cli, ["-n", "--rebuild"])
out = runner.invoke(cli, ["-n", "--rebuild", "--cache-dir", str(cache_dir)])

assert out.exit_code == 0
assert fake_package_dir in out.stderr
assert "small-fake-a==0.1" in out.stderr
assert out.exit_code == 0
assert fake_package_dir in out.stderr
assert "small-fake-a==0.1" in out.stderr

# we should not find any archived file in {cache_dir}/pkgs
assert not os.listdir(os.path.join(str(cache_dir), "pkgs"))
Expand Down Expand Up @@ -519,7 +521,7 @@ def test_generate_hashes_verbose(pip_conf, runner):


@pytest.mark.skipif(PIP_VERSION < (9,), reason="needs pip 9 or greater")
def test_filter_pip_markers(runner):
def test_filter_pip_markers(pip_conf, runner):
"""
Check that pip-compile works with pip environment markers (PEP496)
"""
Expand Down Expand Up @@ -592,7 +594,7 @@ def test_not_specified_input_file(runner):
assert out.exit_code == 2


def test_stdin(runner):
def test_stdin(pip_conf, runner):
"""
Test compile requirements from STDIN.
"""
Expand Down
4 changes: 2 additions & 2 deletions tests/test_top_level_editable.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ def get_dependencies(self, ireq):


@pytest.fixture
def mocked_repository():
return MockedPyPIRepository(["--no-index"])
def mocked_repository(tmpdir):
return MockedPyPIRepository(["--no-index"], cache_dir=str(tmpdir / "pypi-repo"))


def test_editable_top_level_deps_preserved(
Expand Down
4 changes: 2 additions & 2 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,10 @@ def test_create_install_command():
pytest.param(("example1.com", "example2.com:8080"), id="multiple hosts"),
],
)
def test_get_trusted_hosts(hosts):
def test_get_trusted_hosts(hosts, tmpdir):
"""
Test get_trusted_hosts(finder) returns a list of hosts.
"""
pip_args = list(itertools.chain(*zip(["--trusted-host"] * len(hosts), hosts)))
repository = PyPIRepository(pip_args)
repository = PyPIRepository(pip_args, cache_dir=str(tmpdir / "pypi-repo"))
assert tuple(get_trusted_hosts(repository.finder)) == hosts