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

Switch to PIP_RUN_RETENTION_STRATEGY from mode #86

Merged
merged 7 commits into from
Oct 1, 2023
Merged
35 changes: 17 additions & 18 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -347,27 +347,26 @@ For specifics, see `pip_run.run()
Environment Persistence
=======================

``pip-run`` honors the ``PIP_RUN_MODE`` variable. If unset or
set to ``ephemeral``, dependencies are installed to an ephemeral
temporary directory on each invocation (and deleted after).
Setting this variable to ``persist`` will instead create or re-use
a directory in the user's cache, only installing the dependencies if
the directory doesn't already exist. A separate cache is maintained
for each combination of requirements specified.

``persist`` mode can greatly improve startup performance at the
expense of staleness and accumulated cruft.

Without ``PIP_RUN_MODE=persist`` (or with ``=ephemeral``), ``pip-run`` will
re-install dependencies every time a script runs, silently adding to the
startup time while dependencies are installed into an ephemeral environment,
depending on how many dependencies there are and whether the dependencies have
been previously downloaded to the local pip cache. Use ``pip-run -v ...`` to
see the installation activity.
``pip-run`` honors the ``PIP_RUN_RETENTION_STRATEGY`` variable. If unset or
set to ``destroy``, dependencies are installed to a temporary directory on
each invocation (and deleted after). Setting this variable to ``persist`` will
instead create or re-use a directory in the user's cache, only installing the
dependencies if the directory doesn't already exist. A separate cache is
maintained for each combination of requirements specified.

``persist`` strategy can greatly improve startup performance at the expense of
staleness and accumulated cruft.

Without ``PIP_RUN_RETENTION_STRATEGY=persist`` (or with ``=destroy``),
``pip-run`` will re-install dependencies every time a script runs, silently
adding to the startup time while dependencies are installed into an ephemeral
environment, depending on how many dependencies there are and whether the
dependencies have been previously downloaded to the local pip cache. Use
``pip-run -v ...`` to see the installation activity.

The location of the cache can be revealed with this command::

py -c 'import importlib; print(importlib.import_module("pip_run.mode.persist").paths.user_cache_path)'
py -c 'import importlib; print(importlib.import_module("pip_run.retention.persist").paths.user_cache_path)'


Limitations
Expand Down
10 changes: 5 additions & 5 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import jaraco.path
import pytest

import pip_run.mode.persist
import pip_run.retention.persist


collect_ignore = ['examples']
Expand Down Expand Up @@ -48,12 +48,12 @@ def alt_cache_dir(monkeypatch_session, tmp_path_factory):
class Paths:
user_cache_path = alt_cache

monkeypatch_session.setattr(pip_run.mode.persist, 'paths', Paths)
monkeypatch_session.setattr(pip_run.retention.persist, 'paths', Paths)


@pytest.fixture(params=['persist', 'ephemeral'])
def run_mode(monkeypatch, request):
monkeypatch.setenv('PIP_RUN_MODE', request.param)
@pytest.fixture(params=['persist', 'destroy'])
def retention_strategy(monkeypatch, request):
monkeypatch.setenv('PIP_RUN_RETENTION_STRATEGY', request.param)


@pytest.fixture
Expand Down
1 change: 1 addition & 0 deletions newsfragments/84.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Renamed PIP_RUN_MODE variable to PIP_RUN_RETENTION_STRATEGY. Also renamed the default value of 'ephemeral' to 'destroy'. If PIP_RUN_MODE is used, a warning is emitted.
19 changes: 15 additions & 4 deletions pip_run/deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import pathlib
import types
import importlib
import warnings

import packaging.requirements
from jaraco.context import suppress
Expand Down Expand Up @@ -53,9 +54,19 @@ def __bool__(self):
return bool(self.requirement or self.package)


def mode():
mode = os.environ.get('PIP_RUN_MODE', 'ephemeral')
return importlib.import_module(f'.mode.{mode}', package=__package__)
def _mode_compat():
if mode := os.environ.get('PIP_RUN_MODE'): # pragma: no cover
warnings.warn(
'PIP_RUN_MODE is deprecated. Use PIP_RUN_RETENTION_STRATEGY instead.',
)
return mode.replace('ephemeral', 'destroy')


def retention_strategy():
strategy = (
os.environ.get('PIP_RUN_RETENTION_STRATEGY') or _mode_compat() or 'destroy'
)
return importlib.import_module(f'.retention.{strategy}', package=__package__)


@suppress(FileNotFoundError)
Expand All @@ -82,7 +93,7 @@ def empty(path):

@contextlib.contextmanager
def load(*args):
with mode().context(args) as target:
with retention_strategy().context(args) as target:
cmd = (sys.executable, '-m', 'pip', 'install', '-t', sp(target)) + args
env = dict(os.environ, PIP_QUIET="1")
if Install.parse(args) and empty(target):
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 4 additions & 5 deletions tests/test_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_not_installed_args(self):
assert list(filtered) == expected


@pytest.mark.usefixtures('run_mode')
@pytest.mark.usefixtures('retention_strategy')
class TestLoad:
def test_no_args_passes(self):
"""
Expand All @@ -50,9 +50,8 @@ def test_only_options_passes(self):
pass


@pytest.mark.usefixtures('run_mode')
def test_target_mode_context():
@pytest.mark.usefixtures('retention_strategy')
def test_target_retention_context():
"""Verify a target exists or can be created."""
mode = deps.mode()
with mode.context([]) as target:
with deps.retention_strategy().context([]) as target:
target.mkdir(exist_ok=True)
Loading