diff --git a/docs/adr/0012-settings-as-a-seam.md b/docs/adr/0012-settings-as-a-seam.md index 82efe6e..3743a4e 100644 --- a/docs/adr/0012-settings-as-a-seam.md +++ b/docs/adr/0012-settings-as-a-seam.md @@ -53,3 +53,4 @@ for Python tooling. - `resolve_docs_dir()` (ADR-0007's four-tier, `docs_dir`-only function) stays in `settings.py` unused by the CLI; nothing currently calls it outside tests. It is not removed by this decision, since removing it is out of scope for the settings-seam work. + (Removed later by issue #166.) diff --git a/tests/test_settings.py b/tests/test_settings.py index 8520550..3a69f43 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -7,102 +7,12 @@ import pytest -from wiki_toolkit.settings import build_context, resolve_docs_dir +from wiki_toolkit.settings import build_context if TYPE_CHECKING: from pathlib import Path -def test_resolve_docs_dir_defaults_to_cwd_docs(tmp_path: Path) -> None: - """With nothing else set, docs_dir is cwd/docs, source is 'default'.""" - result = resolve_docs_dir(cwd=tmp_path) - - assert result.docs_dir == tmp_path / "docs" - assert result.source == "default" - - -def test_resolve_docs_dir_reads_pyproject_table(tmp_path: Path) -> None: - """A [tool.wiki_toolkit] docs_dir in pyproject.toml is used when no flag/env is set.""" - (tmp_path / "pyproject.toml").write_text('[tool.wiki_toolkit]\ndocs_dir = "custom-docs"\n') - - result = resolve_docs_dir(cwd=tmp_path) - - assert result.docs_dir == tmp_path / "custom-docs" - assert result.source == "pyproject" - - -def test_resolve_docs_dir_walks_upward_for_pyproject(tmp_path: Path) -> None: - """The nearest pyproject.toml is found from a nested cwd, same convention as ruff/mypy.""" - (tmp_path / "pyproject.toml").write_text('[tool.wiki_toolkit]\ndocs_dir = "custom-docs"\n') - nested = tmp_path / "a" / "b" - nested.mkdir(parents=True) - - result = resolve_docs_dir(cwd=nested) - - assert result.docs_dir == tmp_path / "custom-docs" - assert result.source == "pyproject" - - -def test_resolve_docs_dir_env_overrides_pyproject(tmp_path: Path, monkeypatch) -> None: - """WIKI_TOOLKIT_DOCS_DIR wins over a pyproject.toml table.""" - (tmp_path / "pyproject.toml").write_text('[tool.wiki_toolkit]\ndocs_dir = "custom-docs"\n') - monkeypatch.setenv("WIKI_TOOLKIT_DOCS_DIR", str(tmp_path / "env-docs")) - - result = resolve_docs_dir(cwd=tmp_path) - - assert result.docs_dir == tmp_path / "env-docs" - assert result.source == "env" - - -def test_resolve_docs_dir_flag_overrides_env(tmp_path: Path, monkeypatch) -> None: - """A CLI flag wins over both env and pyproject.toml.""" - monkeypatch.setenv("WIKI_TOOLKIT_DOCS_DIR", str(tmp_path / "env-docs")) - - result = resolve_docs_dir(flag=tmp_path / "flag-docs", cwd=tmp_path) - - assert result.docs_dir == tmp_path / "flag-docs" - assert result.source == "flag" - - -def test_resolve_docs_dir_missing_env_falls_through(tmp_path: Path, monkeypatch) -> None: - """No env var set falls through to pyproject/default, doesn't error.""" - monkeypatch.delenv("WIKI_TOOLKIT_DOCS_DIR", raising=False) - - result = resolve_docs_dir(cwd=tmp_path) - - assert result.source == "default" - - -def test_resolve_docs_dir_missing_table_falls_through_to_default(tmp_path: Path) -> None: - """A pyproject.toml with no [tool.wiki_toolkit] table falls through to default.""" - (tmp_path / "pyproject.toml").write_text('[tool.other]\nfoo = "bar"\n') - - result = resolve_docs_dir(cwd=tmp_path) - - assert result.docs_dir == tmp_path / "docs" - assert result.source == "default" - - -def test_resolve_docs_dir_wrong_type_docs_dir_falls_through_to_default(tmp_path: Path) -> None: - """A [tool.wiki_toolkit] table whose docs_dir isn't a valid path falls through to default.""" - (tmp_path / "pyproject.toml").write_text("[tool.wiki_toolkit]\ndocs_dir = 5\n") - - result = resolve_docs_dir(cwd=tmp_path) - - assert result.docs_dir == tmp_path / "docs" - assert result.source == "default" - - -def test_resolve_docs_dir_malformed_toml_falls_through_to_default(tmp_path: Path) -> None: - """A pyproject.toml that fails to parse falls through to default rather than raising.""" - (tmp_path / "pyproject.toml").write_text("not [ valid toml") - - result = resolve_docs_dir(cwd=tmp_path) - - assert result.docs_dir == tmp_path / "docs" - assert result.source == "default" - - def test_build_context_defaults(tmp_path: Path) -> None: """With nothing else set, every field resolves to its built-in default.""" context, sources = build_context(cwd=tmp_path) diff --git a/wiki_toolkit/settings.py b/wiki_toolkit/settings.py index 31146f4..e37fa28 100644 --- a/wiki_toolkit/settings.py +++ b/wiki_toolkit/settings.py @@ -1,9 +1,5 @@ """Resolves wiki_toolkit configuration. -`resolve_docs_dir()` resolves just `docs_dir` (precedence: CLI flag > -`WIKI_TOOLKIT_DOCS_DIR` env var > nearest `pyproject.toml`'s `[tool.wiki_toolkit]` -table > built-in default). - `build_context()` resolves the full `Context` (docs_dir, repo_root, branch_prefix, batch_byte_cap, batch_file_cap) through a five-tier precedence chain: CLI flag > `WIKI_TOOLKIT_` env var > nearest `.wiki-toolkit.toml` (dedicated file, @@ -29,7 +25,6 @@ TomlConfigSettingsSource, ) -ConfigSource = Literal["flag", "env", "pyproject", "default"] ContextConfigSource = Literal["flag", "env", "dedicated_file", "pyproject", "default"] DEDICATED_FILENAME = ".wiki-toolkit.toml" @@ -39,52 +34,6 @@ _DEFAULT_BATCH_FILE_CAP = 20 -class _EnvSettings(BaseSettings): - """Reads `docs_dir` from the `WIKI_TOOLKIT_DOCS_DIR` environment variable.""" - - model_config = SettingsConfigDict(env_prefix="WIKI_TOOLKIT_") - - docs_dir: Path | None = None - - -@dataclass -class ResolvedConfig: - """The resolved `docs_dir` and which source produced it.""" - - docs_dir: Path - source: ConfigSource - - -def _find_pyproject_docs_dir(start: Path) -> Path | None: - """Walk upward from `start` for the nearest pyproject.toml's `[tool.wiki_toolkit].docs_dir`.""" - directory = _find_upward(start, "pyproject.toml") - if directory is None: - return None - result = _pyproject_context_fields(directory) - docs_dir = result[0].docs_dir if result is not None else None - if docs_dir is None: - return None - return docs_dir if docs_dir.is_absolute() else directory / docs_dir - - -def resolve_docs_dir(flag: Path | None = None, cwd: Path | None = None) -> ResolvedConfig: - """Resolve `docs_dir` per precedence: flag > env > pyproject > default.""" - if flag is not None: - return ResolvedConfig(docs_dir=flag, source="flag") - - cwd = cwd or Path.cwd() - - env_docs_dir = _EnvSettings().docs_dir - if env_docs_dir is not None: - return ResolvedConfig(docs_dir=env_docs_dir, source="env") - - pyproject_docs_dir = _find_pyproject_docs_dir(cwd) - if pyproject_docs_dir is not None: - return ResolvedConfig(docs_dir=pyproject_docs_dir, source="pyproject") - - return ResolvedConfig(docs_dir=cwd / "docs", source="default") - - class Context(BaseModel): """The full resolved wiki_toolkit configuration."""