diff --git a/README.rst b/README.rst index 53786f7..44fe5c4 100644 --- a/README.rst +++ b/README.rst @@ -36,6 +36,12 @@ The ``tox-current-env`` plugin adds these options: Use ``-`` for ``FILE`` to print to standard output. This option only exists with tox 4 and requires at least tox 4.22. +``tox --assert-config`` + In tox 4, this option ensures that tox fails (raises an exception) if no configuration is found. + By default, tox 4 does not terminate when no configuration exists. + In tox 3, this option has no effect, but it can still be specified without causing errors. + This option can be used alongside other options. + It is possible to use the three printing options together, as long as the ``FILE`` is different. Invoking ``tox`` without any of the above options should behave as regular ``tox`` invocation without this plugin. diff --git a/src/tox_current_env/hooks3.py b/src/tox_current_env/hooks3.py index eca79f8..f4cda4e 100644 --- a/src/tox_current_env/hooks3.py +++ b/src/tox_current_env/hooks3.py @@ -48,6 +48,12 @@ def tox_addoption(parser): help="Don't run tests, only print the names of the required extras to the given file " + "(use `-` for stdout)", ) + parser.add_argument( + "--assert-config", + action="store_true", + default=False, + help="Fail if no tox configuration is found (default on tox 3, does nothing)", + ) def _plugin_active(option): diff --git a/src/tox_current_env/hooks4.py b/src/tox_current_env/hooks4.py index 7597cca..4213c8c 100644 --- a/src/tox_current_env/hooks4.py +++ b/src/tox_current_env/hooks4.py @@ -66,12 +66,26 @@ def tox_add_option(parser): help="Don't run tests, only print the names of the required dependency-groups to the given file " + "(use `-` for stdout)", ) + parser.add_argument( + "--assert-config", + action="store_true", + default=False, + help="Fail if no tox configuration is found", + ) @impl def tox_add_core_config(core_conf, state): opt = state.conf.options + if opt.assert_config and not state.conf.src_path.exists(): + raise LookupError( + "tox configuration not found. " + "To use tox, please ensure tox configuration is located in current directory " + "(in tox.ini, setup.cfg, pyproject.toml, or tox.toml). " + "See https://tox.wiki/en/latest/config.html for details." + ) + if opt.current_env or opt.print_deps_to or opt.print_extras_to or opt.print_dependency_groups_to: # We do not want to install the main package. # no_package is the same as skipsdist. diff --git a/tests/test_integration_tox3.py b/tests/test_integration_tox3.py index ef50036..e8d210e 100644 --- a/tests/test_integration_tox3.py +++ b/tests/test_integration_tox3.py @@ -580,3 +580,43 @@ def test_passenv(projdir, passenv): assert result.returncode == 0 assert "\nassertme\n" in result.stdout assert "\nNone\n" not in result.stdout + + +def test_assert_config_option_with_config(projdir): + result = tox("-l", "--assert-config", check=False) + assert result.returncode == 0 + + +def test_assert_config_option_without_config(projdir): + (projdir / "tox.ini").unlink() + result = tox("-l", "--assert-config", check=False) + assert result.returncode > 0 + assert "config" in result.stderr + assert "not found" in result.stderr + + +def test_assert_config_option_with_setup_cfg(projdir): + (projdir / "tox.ini").unlink() + setup_cfg = projdir / "setup.cfg" + setup_cfg.write_text(textwrap.dedent(""" + [tox:tox] + env_list = + py310 + """)) + result = tox("-l", "--assert-config", check=False) + assert result.returncode == 0 + + +def test_assert_config_option_with_pyproject_toml(projdir): + (projdir / "tox.ini").unlink() + pyproject_toml = projdir / "pyproject.toml" + pyproject_toml.write_text(textwrap.dedent(''' + [tool.tox] + legacy_tox_ini = """ + [tox] + envlist = + py310 + """ + ''')) + result = tox("-l", "--assert-config", check=False) + assert result.returncode == 0 diff --git a/tests/test_integration_tox4.py b/tests/test_integration_tox4.py index 964b047..4773209 100644 --- a/tests/test_integration_tox4.py +++ b/tests/test_integration_tox4.py @@ -591,3 +591,54 @@ def test_report_installed(projdir): assert result.returncode == 0 assert "tox==" in result.stdout assert "pytest==" in result.stdout + + +def test_assert_config_option_with_config(projdir): + result = tox("-l", "--assert-config", check=False) + assert result.returncode == 0 + + +def test_assert_config_option_without_config(projdir): + (projdir / "tox.ini").unlink() + result = tox("-l", "--assert-config", check=False) + assert result.returncode > 0 + assert "config" in result.stderr + assert "not found" in result.stderr + + +def test_assert_config_option_with_setup_cfg(projdir): + (projdir / "tox.ini").unlink() + setup_cfg = projdir / "setup.cfg" + setup_cfg.write_text(textwrap.dedent(""" + [tox:tox] + env_list = + py310 + """)) + result = tox("-l", "--assert-config", check=False) + assert result.returncode == 0 + + +def test_assert_config_option_with_pyproject_toml(projdir): + (projdir / "tox.ini").unlink() + pyproject_toml = projdir / "pyproject.toml" + pyproject_toml.write_text(textwrap.dedent(''' + [tool.tox] + legacy_tox_ini = """ + [tox] + envlist = + py310 + """ + ''')) + result = tox("-l", "--assert-config", check=False) + assert result.returncode == 0 + + +def test_assert_config_option_with_pyproject_toml_native(projdir): + (projdir / "tox.ini").unlink() + pyproject_toml = projdir / "pyproject.toml" + pyproject_toml.write_text(textwrap.dedent(""" + [tool.tox] + env_list = ["3.13"] + """)) + result = tox("-l", "--assert-config", check=False) + assert result.returncode == 0