"""Configuration from a dotenv file, including the archived CLI's variable names. An operator who already has a ``photo_analyzer.env`` should not have to rewrite it to run the application it was replaced by. The file is standing configuration; the shell is what you meant this time, so the shell always wins. """ from __future__ import annotations import os from photo_pipeline.config import Config, load_env_file, parse_env_file SAMPLE = """ # The archived CLI's shape, comments and all. LLM_API_KEY=not-real LLM_BASE_URL="https://example.invalid/v1beta/openai/" LLM_MODEL='gemini-2.5-flash' LIBRARY=/tmp/pictures MAX_WORKERS=4 # commented=ignored malformed line without an equals sign """ def test_the_file_is_parsed_and_never_executed(): values = parse_env_file(SAMPLE) assert values["LLM_BASE_URL"] == "https://example.invalid/v1beta/openai/" # quotes stripped assert values["LLM_MODEL"] == "gemini-2.5-flash" assert values["MAX_WORKERS"] == "4" assert "commented" not in values and "malformed line without an equals sign" not in values def test_the_archived_cli_names_still_configure_the_application(): values = parse_env_file(SAMPLE) assert values["OPENAI_API_KEY"] == "not-real" assert values["OPENAI_BASE_URL"] == "https://example.invalid/v1beta/openai/" assert values["PHOTO_PIPELINE_LIBRARY_ROOTS"] == "/tmp/pictures" def test_an_explicit_shell_variable_beats_the_file(tmp_path, monkeypatch): path = tmp_path / "photo_analyzer.env" path.write_text(SAMPLE) monkeypatch.setenv("OPENAI_API_KEY", "from-the-shell") monkeypatch.delenv("PHOTO_PIPELINE_LIBRARY_ROOTS", raising=False) applied = load_env_file(path) assert "OPENAI_API_KEY" not in applied, "the file overrode an exported value" assert os.environ["OPENAI_API_KEY"] == "from-the-shell" assert os.environ["PHOTO_PIPELINE_LIBRARY_ROOTS"] == "/tmp/pictures" assert Config.from_env().library_roots[0].name == "pictures" def test_the_file_is_found_through_its_variable(tmp_path, monkeypatch): path = tmp_path / "custom.env" path.write_text("PHOTO_PIPELINE_PORT=9123\n") monkeypatch.delenv("PHOTO_PIPELINE_PORT", raising=False) monkeypatch.setenv("PHOTO_PIPELINE_ENV_FILE", str(path)) monkeypatch.chdir(tmp_path) # no ./.env here, so only the variable can find it assert Config.from_env().port == 9123 def test_a_missing_file_is_not_an_error(tmp_path): assert load_env_file(tmp_path / "nothing-here.env") == {}