diff --git a/docs/changelog/2340.bugfix.rst b/docs/changelog/2340.bugfix.rst new file mode 100644 index 000000000..b6575860f --- /dev/null +++ b/docs/changelog/2340.bugfix.rst @@ -0,0 +1 @@ +Allow passing config directory without filename. - by :user:`ssbarnea`. diff --git a/docs/config.rst b/docs/config.rst index 804896c4d..64bbcdd45 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -79,8 +79,9 @@ examples first and use this page as a reference. .. code-block:: toml - [tool:tox] + [tool.tox] legacy_tox_ini = """ + [tox] min_version = 4.0 env_list = py310 diff --git a/src/tox/config/cli/parser.py b/src/tox/config/cli/parser.py index 403aed294..c2a842d64 100644 --- a/src/tox/config/cli/parser.py +++ b/src/tox/config/cli/parser.py @@ -316,7 +316,7 @@ def add_core_arguments(parser: ArgumentParser) -> None: default=None, type=Path, of_type=Optional[Path], - help="configuration file for tox (if not specified will discover one)", + help="configuration file/folder for tox (if not specified will discover one)", ) parser.add_argument( "--workdir", diff --git a/src/tox/config/source/discover.py b/src/tox/config/source/discover.py index 49232a0eb..d9e8e507d 100644 --- a/src/tox/config/source/discover.py +++ b/src/tox/config/source/discover.py @@ -26,6 +26,17 @@ def discover_source(config_file: Path | None, root_dir: Path | None) -> Source: src = _locate_source() if src is None: src = _create_default_source(root_dir) + elif config_file.is_dir(): + src = None + for src_type in SOURCE_TYPES: + candidate: Path = config_file / src_type.FILENAME + try: + src = src_type(candidate) + break + except ValueError: + continue + if src is None: + raise HandledError(f"could not find any config file in {config_file}") else: src = _load_exact_source(config_file) return src diff --git a/tests/config/cli/test_cli_ini.py b/tests/config/cli/test_cli_ini.py index efe3776d1..7f3d43e5e 100644 --- a/tests/config/cli/test_cli_ini.py +++ b/tests/config/cli/test_cli_ini.py @@ -11,7 +11,10 @@ from tox.config.cli.ini import IniConfig from tox.config.cli.parse import get_options +from tox.config.cli.parser import Parsed from tox.config.loader.api import Override +from tox.config.main import Config +from tox.config.source import discover_source from tox.pytest import CaptureFixture, LogCaptureFixture, MonkeyPatch from tox.session.env_select import CliEnv from tox.session.state import State @@ -199,3 +202,31 @@ def test_cli_ini_with_interpolated(tmp_path: Path, monkeypatch: MonkeyPatch) -> monkeypatch.setenv("TOX_CONFIG_FILE", str(to)) conf = IniConfig() assert conf.get("a", str) + + +@pytest.mark.parametrize( + ("conf_arg", "filename", "content"), + [ + pytest.param("", "tox.ini", "[tox]", id="ini-dir"), + pytest.param("tox.ini", "tox.ini", "[tox]", id="ini"), + pytest.param("", "setup.cfg", "[tox:tox]", id="cfg-dir"), + pytest.param("setup.cfg", "setup.cfg", "[tox:tox]", id="cfg"), + pytest.param("", "pyproject.toml", '[tool.tox]\nlegacy_tox_ini = """\n[tox]\n"""\n', id="toml-dir"), + pytest.param("pyproject.toml", "pyproject.toml", '[tool.tox]\nlegacy_tox_ini = """\n[tox]\n"""\n', id="toml"), + ], +) +def test_conf_arg(tmp_path: Path, conf_arg: str, filename: str, content: str) -> None: + dest = tmp_path / "c" + dest.mkdir() + if filename: + cfg = dest / filename + cfg.write_bytes(content.encode(encoding="utf-8")) + + config_file = dest / conf_arg + source = discover_source(config_file, None) + + Config.make( + Parsed(work_dir=dest, override=[], config_file=config_file, root_dir=None), + pos_args=[], + source=source, + )