fix: restore .env loading for --init-config
Регрессия от 1df1194 (#64): load_dotenv переехал с module-level в
Config.load_yaml(), но --init-config выходит до этого вызова, поэтому
_run_init_config больше не видел значения из .env — пользователь с
настройками только в .env получал пустой YAML, хотя docs/CONFIG.md
обещает чтение текущих значений из .env.
В начале _run_init_config добавлен load_dotenv(find_dotenv(usecwd=True),
override=False): поиск .env идёт от текущей директории (plain-вызов без
usecwd стартует от директории cli.py и .env пользователя не находит),
переменные окружения не перебиваются. Импорт модуля по-прежнему без
side effects — вызов внутри функции.
Регрессионный тест: test_init_config_reads_dotenv_file (реальный .env
в tmp_path + chdir, без мока os.environ на целевые переменные).
Refs #64
This commit is contained in:
@@ -8,6 +8,7 @@ from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
import yaml
|
||||
from dotenv import find_dotenv, load_dotenv
|
||||
|
||||
from . import __version__
|
||||
from .client import RedmineAPIError, fetch_issues_with_spent_time
|
||||
@@ -70,7 +71,16 @@ def parse_date_range(date_arg: str) -> tuple[str, str]:
|
||||
|
||||
|
||||
def _run_init_config(config_path: str, force: bool) -> int:
|
||||
"""Создаёт YAML-конфиг из текущих настроек окружения."""
|
||||
"""Создаёт YAML-конфиг из текущих настроек окружения.
|
||||
|
||||
Подгружает .env из текущей директории (override=False: реальные
|
||||
переменные окружения не перебиваются), чтобы --init-config видел
|
||||
значения, заданные только в .env (#64). Поиск идёт от cwd
|
||||
(usecwd=True): find_dotenv() без него стартует от директории
|
||||
cli.py и .env пользователя не находит.
|
||||
"""
|
||||
load_dotenv(find_dotenv(usecwd=True), override=False)
|
||||
|
||||
path = Path(config_path)
|
||||
|
||||
if path.exists() and not force:
|
||||
|
||||
@@ -425,6 +425,49 @@ class TestInitConfig:
|
||||
assert data["redmine"]["url"] == ""
|
||||
assert data["redmine"]["api_key"] == ""
|
||||
|
||||
def test_init_config_reads_dotenv_file(self, tmp_path, monkeypatch):
|
||||
"""#64: --init-config подхватывает значения из реального .env в cwd.
|
||||
|
||||
Регрессионный тест: после 1df1194 load_dotenv перестал выполняться
|
||||
до _run_init_config, и пользователь с настройками только в .env
|
||||
получал пустой YAML.
|
||||
"""
|
||||
import yaml
|
||||
|
||||
(tmp_path / ".env").write_text(
|
||||
"REDMINE_URL=https://redmine.example.com\n"
|
||||
"REDMINE_API_KEY=secret-from-dotenv\n"
|
||||
"REDMINE_AUTHOR=ivan.ivanov\n"
|
||||
"DEFAULT_FROM_DATE=2026-01-01\n"
|
||||
"DEFAULT_TO_DATE=2026-01-31\n"
|
||||
"SMTP_PASSWORD=smtp-secret\n"
|
||||
)
|
||||
monkeypatch.chdir(tmp_path)
|
||||
# Целевые переменные не мокаются: значения должны прийти только из .env.
|
||||
for var in (
|
||||
"REDMINE_URL",
|
||||
"REDMINE_API_KEY",
|
||||
"REDMINE_AUTHOR",
|
||||
"DEFAULT_FROM_DATE",
|
||||
"DEFAULT_TO_DATE",
|
||||
"SMTP_PASSWORD",
|
||||
):
|
||||
monkeypatch.delenv(var, raising=False)
|
||||
|
||||
config_path = tmp_path / "config.yml"
|
||||
code = main(["--init-config", "--config-path", str(config_path)])
|
||||
assert code == 0
|
||||
|
||||
with open(config_path) as fh:
|
||||
data = yaml.safe_load(fh)
|
||||
|
||||
assert data["redmine"]["url"] == "https://redmine.example.com"
|
||||
assert data["redmine"]["api_key"] == "${REDMINE_API_KEY}"
|
||||
assert data["redmine"]["author"] == "ivan.ivanov"
|
||||
assert data["period"]["default_from"] == "2026-01-01"
|
||||
assert data["period"]["default_to"] == "2026-01-31"
|
||||
assert data["email"]["smtp"]["password"] == "${SMTP_PASSWORD}"
|
||||
|
||||
@mock.patch.dict(os.environ, VALID_ENV, clear=True)
|
||||
def test_init_config_includes_report_section(self, tmp_path):
|
||||
"""--init-config генерирует секцию report с no_time: false."""
|
||||
|
||||
Reference in New Issue
Block a user