Skip to content

Commit

Permalink
Merge pull request #34 from masenf/extra
Browse files Browse the repository at this point in the history
Handle extras in [testenv]
  • Loading branch information
masenf committed Feb 9, 2023
2 parents afd2e38 + 5f10383 commit f5e4e74
Show file tree
Hide file tree
Showing 18 changed files with 169 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.coverage
.coverage.*
.tox
__pycache__
*.egg-info
15 changes: 14 additions & 1 deletion src/tox_pin_deps/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ def env_pip_pre(self) -> bool: # pragma: no cover
"""[testenv] pip_pre value."""
raise NotImplementedError

@property
@abc.abstractmethod
def env_extras(self) -> t.Sequence[str]: # pragma: no cover
"""Extras defined for the local package in [testenv] extras key."""
raise NotImplementedError

@abc.abstractmethod
def execute(
self,
Expand Down Expand Up @@ -124,13 +130,20 @@ def pip_compile_opts(self) -> t.Iterable[str]:
* specified in the environment as PIP_COMPILE_OPTS
Options are combined in the order above.
Additional internal options are added here:
* extras
"""
sources = [
self.env_pip_compile_opts_env,
self.options.pip_compile_opts,
os.environ.get(ENV_PIP_COMPILE_OPTS),
]
return [opt for source in sources for opt in shlex.split(source or "")]
opts = [opt for source in sources for opt in shlex.split(source or "")]
if not self.skipsdist:
for extra in self.env_extras:
opts.extend(["--extra", extra])
return opts

@property
def _has_pinned_deps(self) -> bool:
Expand Down
5 changes: 5 additions & 0 deletions src/tox_pin_deps/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ def env_pip_pre(self) -> bool:
"""[testenv] pip_pre value."""
return bool(self.venv.envconfig.pip_pre)

@property
def env_extras(self) -> t.Sequence[str]: # pragma: no cover
"""[testenv] extras value."""
return [str(extra) for extra in (self.venv.envconfig.extras or [])]

def execute(
self,
cmd: t.Sequence[str],
Expand Down
6 changes: 6 additions & 0 deletions src/tox_pin_deps/plugin4.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ def env_pip_pre(self) -> bool:
"""[testenv] pip_pre value."""
return bool(self.venv.conf["pip_pre"])

@property
def env_extras(self) -> t.Sequence[str]: # pragma: no cover
"""[testenv] extras value."""
extras = self.venv.conf["extras"] if not self.skipsdist else []
return [str(extra) for extra in extras]

@staticmethod
def _deps(pydeps: PythonDeps) -> t.Sequence[str]:
return pydeps.lines()
Expand Down
29 changes: 24 additions & 5 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,14 @@ def mock_pkg_quuc(tmp_path_factory, pkg_path, mock_pkg_bar):


@pytest.fixture(scope="session")
def all_mock_packages(mock_pkg_foo, mock_pkg_bar, mock_pkg_quuc):
def mock_pkg_foo_ex(tmp_path_factory, pkg_path):
pkg_name = "mock_pkg_foo_ex"
versions = ["0.0.1"]
return mock_package_maker(pkg_name, versions, tmp_path_factory, pkg_path)


@pytest.fixture(scope="session")
def all_mock_packages(mock_pkg_foo, mock_pkg_bar, mock_pkg_quuc, mock_pkg_foo_ex):
return dict([mock_pkg_foo, mock_pkg_bar, mock_pkg_quuc])


Expand All @@ -94,7 +101,7 @@ def save_pip_vars():
@pytest.fixture(scope="session")
def package_server(pkg_path, all_mock_packages, save_pip_vars):
index = mock_packages.dumb_pypi_repo(pkg_path)
# os.environ["PIP_INDEX_URL"] = index
os.environ.pop("PIP_INDEX_URL", None)
os.environ["PIP_EXTRA_INDEX_URL"] = index
yield index

Expand Down Expand Up @@ -123,15 +130,25 @@ def example_environment_root(example_project_name, package_server):

@pytest.fixture(
scope="module",
params=["tox==3.27.1", "tox==4.0.5"],
params=["tox==3.27.1", "tox==4.4.5"],
)
def tox_version(request):
return request.param


@pytest.fixture(scope="module")
def tox_major(tox_version):
return "4" if "4" in tox_version else "3"
return "3" if "3" in tox_version else "4"


@pytest.fixture(scope="module")
def toxworkdir(tmp_path_factory, tox_version, mod_id):
workdir = tmp_path_factory.mktemp(f"workdir_{mod_id}_{tox_version}")
old_workdir = os.environ.get("TOX_WORK_DIR", None)
os.environ["TOX_WORK_DIR"] = str(workdir)
yield workdir
if old_workdir is not None:
os.environ["TOX_WORK_DIR"] = old_workdir


@pytest.fixture(scope="module")
Expand All @@ -157,6 +174,8 @@ def tox_venv(tmp_path_factory, mod_id, tox_version):
import pkg_resources

pytest_cov_dist = pkg_resources.get_distribution("pytest-cov")
if tox_version == "tox-dev":
tox_version = "tox>4"
subprocess.run(
[
tox_venv_path / "bin" / "python",
Expand Down Expand Up @@ -222,7 +241,7 @@ def link_tox_pin_deps(tox_venv, tox_venv_site_packages_dir):


@pytest.fixture(scope="module")
def tox_runner(tox_venv_python, link_tox_pin_deps, toxinidir):
def tox_runner(tox_venv_python, link_tox_pin_deps, toxworkdir, toxinidir):
def run_tox_cmd(*args):
return subprocess.run(
[tox_venv_python, "-m", "tox", *args],
Expand Down
11 changes: 10 additions & 1 deletion tests/integration/examples/pyproj/exp_lock_3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,13 @@ skipinst installed:
skipinst run-test: commands[0] | pip freeze
mock-pkg-bar==0.1.1
mock-pkg-foo==0.1.0
mock-pkg-quuc==2.0
mock-pkg-quuc==2.0
~reextrafoo installdeps: -r/.*/pyproj/requirements/extrafoo\.txt
extrafoo inst:
extrafoo installed:
extrafoo run-test: commands[0] | pip freeze
mock-pkg-bar==1.5
mock-pkg-foo==0.1.0
mock-pkg-foo-ex==0.0.1
mock-pkg-quuc==2.2
pyproj @
11 changes: 10 additions & 1 deletion tests/integration/examples/pyproj/exp_lock_4.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,13 @@ oldfoo: OK
skipinst: commands[0]> pip freeze
mock-pkg-bar==0.1.1
mock-pkg-foo==0.1.0
mock-pkg-quuc==2.0
mock-pkg-quuc==2.0
~reextrafoo: install_deps> python -I -m pip install -r /.*/pyproj/requirements/extrafoo\.txt
extrafoo: install_package>
extrafoo: commands[0]> pip freeze
mock-pkg-bar==1.5
mock-pkg-foo==0.1.0
mock-pkg-foo-ex==0.0.1
mock-pkg-quuc==2.2
pyproj @
extrafoo: OK
10 changes: 9 additions & 1 deletion tests/integration/examples/pyproj/exp_no_lock_3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,12 @@ skipinst installed: mock-pkg-bar==0.1.1,mock-pkg-foo==0.1.0,mock-pkg-quuc==2.0
skipinst run-test: commands[0] | pip freeze
mock-pkg-bar==0.1.1
mock-pkg-foo==0.1.0
mock-pkg-quuc==2.0
mock-pkg-quuc==2.0
extrafoo inst:
extrafoo installed: mock-pkg-bar==1.5,mock-pkg-foo==0.1.0,mock-pkg-foo-ex==0.0.1,mock-pkg-quuc==2.2,pyproj @
extrafoo run-test: commands[0] | pip freeze
mock-pkg-bar==1.5
mock-pkg-foo==0.1.0
mock-pkg-foo-ex==0.0.1
mock-pkg-quuc==2.2
pyproj @
11 changes: 10 additions & 1 deletion tests/integration/examples/pyproj/exp_no_lock_4.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,13 @@ skipinst: install_deps> python -I -m pip install 'mock_pkg_bar<1.1' 'mock_pkg_qu
skipinst: commands[0]> pip freeze
mock-pkg-bar==0.1.1
mock-pkg-foo==0.1.0
mock-pkg-quuc==2.0
mock-pkg-quuc==2.0
extrafoo: install_package_deps> python -I -m pip install mock_pkg_foo_ex mock_pkg_quuc
extrafoo: install_package>
extrafoo: commands[0]> pip freeze
mock-pkg-bar==1.5
mock-pkg-foo==0.1.0
mock-pkg-foo-ex==0.0.1
mock-pkg-quuc==2.2
pyproj @
extrafoo: OK
14 changes: 13 additions & 1 deletion tests/integration/examples/pyproj/exp_pip_compile_3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,16 @@ skipinst run-test: commands[0] | pip freeze
mock-pkg-bar==0.1.1
mock-pkg-foo==0.1.0
mock-pkg-quuc==2.0
pip-tools==
pip-tools==
extrafoo tox-pin-deps: ['pip', 'install', 'pip-tools']
~reextrafoo tox-pin-deps: \['pip-compile', '/.*/pyproj/pyproject.toml', '--output-file', '/.*/pyproj/requirements/extrafoo\.txt', '--generate-hashes', '-v', '--extra-index-url', '.*', '--extra', 'ex']
~reextrafoo installdeps: -r/.*/pyproj/requirements/extrafoo\.txt
extrafoo inst:
extrafoo installed:
extrafoo run-test: commands[0] | pip freeze
mock-pkg-bar==1.5
mock-pkg-foo==0.1.0
mock-pkg-foo-ex==0.0.1
mock-pkg-quuc==2.2
pip-tools==
pyproj @
13 changes: 12 additions & 1 deletion tests/integration/examples/pyproj/exp_pip_compile_4.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,15 @@ skipinst: commands[0]> pip freeze
mock-pkg-bar==0.1.1
mock-pkg-foo==0.1.0
mock-pkg-quuc==2.0
pip-tools==
pip-tools==
skipinst: OK
extrafoo: tox-pin-deps> pip install pip-tools
~reextrafoo: tox-pin-deps> pip-compile /.*/pyproj/pyproject\.toml --output-file /.*/pyproj/requirements/extrafoo\.txt --generate-hashes -v --extra-index-url .* --extra ex
~reextrafoo: install_deps> python -I -m pip install -r /.*/pyproj/requirements/extrafoo\.txt
extrafoo: commands[0]> pip freeze
mock-pkg-bar==1.5
mock-pkg-foo==0.1.0
mock-pkg-foo-ex==0.0.1
mock-pkg-quuc==2.2
pip-tools==
pyproj @
10 changes: 9 additions & 1 deletion tests/integration/examples/pyproj/exp_reuse_3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@ skipinst installed: mock-pkg-bar==0.1.1,mock-pkg-foo==0.1.0,mock-pkg-quuc==2.0
skipinst run-test: commands[0] | pip freeze
mock-pkg-bar==0.1.1
mock-pkg-foo==0.1.0
mock-pkg-quuc==2.0
mock-pkg-quuc==2.0
extrafoo inst-nodeps
extrafoo installed: mock-pkg-bar==1.5,mock-pkg-foo==0.1.0,mock-pkg-foo-ex==0.0.1,mock-pkg-quuc==2.2,pyproj @
extrafoo run-test: commands[0] | pip freeze
mock-pkg-bar==1.5
mock-pkg-foo==0.1.0
mock-pkg-foo-ex==0.0.1
mock-pkg-quuc==2.2
pyproj @
8 changes: 7 additions & 1 deletion tests/integration/examples/pyproj/exp_reuse_4.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ oldfoo: OK
skipinst: commands[0]> pip freeze
mock-pkg-bar==0.1.1
mock-pkg-foo==0.1.0
mock-pkg-quuc==2.0
mock-pkg-quuc==2.0
skipinst: OK
extrafoo: commands[0]> pip freeze
mock-pkg-bar==1.5
mock-pkg-foo-ex==0.0.1
mock-pkg-quuc==2.2
pyproj @
5 changes: 4 additions & 1 deletion tests/integration/examples/pyproj/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ build-backend = 'setuptools.build_meta'
[project]
name = "pyproj"
dependencies = ['mock_pkg_quuc']
version = "0.0.1"
version = "0.0.1"

[project.optional-dependencies]
ex = ["mock_pkg_foo_ex"]
5 changes: 4 additions & 1 deletion tests/integration/examples/pyproj/tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tox]
isolated_build = true
envlist = nodeps, prefoo, oldfoo, skipinst
envlist = nodeps, prefoo, oldfoo, skipinst, extrafoo


[testenv]
Expand All @@ -23,3 +23,6 @@ skip_install = True
deps =
mock_pkg_quuc < 2.1
mock_pkg_bar < 1.1

[testenv:extrafoo]
extras = ex
5 changes: 5 additions & 0 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ def pip_pre(request):
return request.param


@pytest.fixture(params=[[], ["ex1", "ex2"]], ids=["noextra", "extras"])
def extras(request):
return request.param


@pytest.fixture(params=[True, False], ids=["setup.py", "no_setup.py"])
def setup_py(request, toxinidir):
if request.param:
Expand Down
11 changes: 11 additions & 0 deletions tests/unit/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def envconfig(venv_name, config):
envconfig.pip_compile_opts = None
envconfig.recreate = False
envconfig.pip_pre = False
envconfig.extras = []
config.envconfigs[venv_name] = envconfig
config.envlist.append(venv_name)
return envconfig
Expand Down Expand Up @@ -103,6 +104,12 @@ def pip_pre(pip_pre, envconfig):
return pip_pre


@pytest.fixture
def extras(extras, envconfig):
envconfig.extras = extras
return extras


@pytest.fixture
def action():
return mock.Mock()
Expand Down Expand Up @@ -190,6 +197,7 @@ def test_tox_testenv_install_deps_will_install(
venv,
action,
pip_pre,
extras,
pip_compile_opts_env,
pip_compile_opts_cli,
pip_compile_opts_testenv,
Expand Down Expand Up @@ -235,6 +243,9 @@ def test_tox_testenv_install_deps_will_install(
exp_opts.extend(shlex.split(pip_compile_opts_cli))
if pip_compile_opts_env:
exp_opts.extend(shlex.split(pip_compile_opts_env))
if extras and not skipsdist and not skip_install:
for extra in extras:
exp_opts.extend(["--extra", extra])
assert cmd[start_idx:] == exp_opts


Expand Down
12 changes: 11 additions & 1 deletion tests/unit/test_plugin4.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def options(options):
@pytest.fixture
def conf():
"""tox4 per-testenv config."""
return dict(pip_compile_opts=None, skip_install=False, pip_pre=False)
return dict(pip_compile_opts=None, skip_install=False, pip_pre=False, extras=[])


@pytest.fixture
Expand Down Expand Up @@ -106,6 +106,12 @@ def pip_pre(pip_pre, conf):
return pip_pre


@pytest.fixture
def extras(extras, conf):
conf["extras"] = extras
return extras


def test_install(
toxinidir,
venv_name,
Expand Down Expand Up @@ -168,6 +174,7 @@ def test_install_will_install(
venv_name,
toxinidir,
pip_pre,
extras,
pip_compile_opts_env,
pip_compile_opts_cli,
pip_compile_opts_testenv,
Expand Down Expand Up @@ -215,6 +222,9 @@ def test_install_will_install(
exp_opts.extend(shlex.split(pip_compile_opts_cli))
if pip_compile_opts_env:
exp_opts.extend(shlex.split(pip_compile_opts_env))
if extras and not skipsdist and not skip_install:
for extra in extras:
exp_opts.extend(["--extra", extra])
assert cmd[start_idx:] == exp_opts


Expand Down

0 comments on commit f5e4e74

Please sign in to comment.