From 1683b0f8933dfbd0b8363145422eb3c8be7d522f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D0=BA=D0=BE=D1=81=20=D0=90=D1=80=D1=82=D0=B5?= =?UTF-8?q?=D0=BC=20=D0=9D=D0=B8=D0=BA=D0=BE=D0=BB=D0=B0=D0=B5=D0=B2=D0=B8?= =?UTF-8?q?=D1=87?= Date: Fri, 17 Jul 2026 13:38:14 +0700 Subject: [PATCH] fix: default report period to current month MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Без --date, env и YAML отчёт строится за текущий месяц: начало периода — 1-е число текущего месяца, конец — сегодня (date.today()), согласовано с fallback default_to→today из #50. Приоритеты источников (CLI > env > .env > YAML > дефолт) и precision=datetime не затронуты. Сам fallback уже существовал в коде (хардкод устаревшего периода был убран ранее); коммит фиксирует поведение детерминированными тестами с моком date.today (RED проверен регрессионным зондом: при возврате хардкода 2025-12-19--2026-01-31 тесты падают) и обновляет README и docs/CONFIG.md: дефолт явно описан как «текущий месяц». Closes #56 --- README.md | 5 +++-- docs/CONFIG.md | 7 ++++++ tests/test_config.py | 53 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a79c6c3..ae21a33 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ DEFAULT_TO_DATE=2026-01-31 | `REDMINE_USER` | Да, если нет токена | Логин Redmine. | | `REDMINE_PASSWORD` | Да, если нет токена | Пароль Redmine. | | `REDMINE_AUTHOR` | Нет | Имя автора для отчёта. | -| `DEFAULT_FROM_DATE` | Нет | Начальная дата периода по умолчанию (`YYYY-MM-DD`). | +| `DEFAULT_FROM_DATE` | Нет | Начальная дата периода по умолчанию (`YYYY-MM-DD`). Если не задана (и нет в YAML) — 1-е число текущего месяца. | | `DEFAULT_TO_DATE` | Нет | Конечная дата периода по умолчанию (`YYYY-MM-DD`). Если не задана, а `DEFAULT_FROM_DATE` задана — используется сегодняшняя дата. | | `REDMINE_VERIFY` | Нет | TLS-проверка: `true` (по умолчанию — стандартная проверка средствами requests) / `false` / путь к CA bundle. Семантика совпадает с `redmine.verify_ssl` в YAML. | @@ -141,7 +141,8 @@ source .venv/bin/activate ### Основные сценарии -Отчёт за период по умолчанию: +Отчёт за период по умолчанию — текущий месяц (с 1-го числа по сегодня), +если период не задан через `--date`, env или YAML: ```bash redmine-reporter diff --git a/docs/CONFIG.md b/docs/CONFIG.md index d057356..2fa65dd 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -107,6 +107,13 @@ period: Аналогично работает `DEFAULT_TO_DATE`: если переменная не задана, а `DEFAULT_FROM_DATE` задана, конец периода = сегодня. +### Период по умолчанию — текущий месяц + +Если период не задан ни одним из источников (`--date`, `DEFAULT_FROM_DATE`, +`period.default_from`), отчёт строится за текущий месяц: начало периода — +1-е число текущего месяца, конец — сегодняшняя дата. Период вычисляется +на момент запуска и не хранится в коде или конфиге. + ### `--commit` — автофиксация периода Флаг `--commit` сохраняет использованный период в YAML-конфиг, чтобы следующий запуск автоматически начинался с нового периода. diff --git a/tests/test_config.py b/tests/test_config.py index f3f89bd..8922100 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -99,6 +99,59 @@ def test_get_default_date_range_fallback(): assert result == f"{start.isoformat()}--{today.isoformat()}" +# -- #56: дефолтный период — текущий месяц (детерминированные тесты) -- + + +class TestDefaultPeriodIsCurrentMonth: + """Без --date, env и YAML период = с 1-го числа текущего месяца по сегодня.""" + + @mock.patch.dict(os.environ, {}, clear=True) + def test_mid_month(self): + from datetime import date + + with mock.patch("redmine_reporter.config.date") as mock_date: + mock_date.today.return_value = date(2026, 3, 14) + mock_date.side_effect = lambda *a, **kw: date(*a, **kw) + Config._app = None + assert Config.get_default_date_range() == "2026-03-01--2026-03-14" + + @mock.patch.dict(os.environ, {}, clear=True) + def test_first_day_of_month(self): + from datetime import date + + with mock.patch("redmine_reporter.config.date") as mock_date: + mock_date.today.return_value = date(2026, 5, 1) + mock_date.side_effect = lambda *a, **kw: date(*a, **kw) + Config._app = None + assert Config.get_default_date_range() == "2026-05-01--2026-05-01" + + @mock.patch.dict(os.environ, {}, clear=True) + def test_yaml_default_from_falls_back_to_today(self): + """default_from задан, default_to нет → конец периода = сегодня.""" + from datetime import date + + with tempfile.TemporaryDirectory() as tmp: + yaml_path = Path(tmp) / "config.yml" + yaml_path.write_text("period:\n default_from: '2026-04-01'\n") + Config._app = AppConfig.from_yaml(yaml_path) + + with mock.patch("redmine_reporter.config.date") as mock_date: + mock_date.today.return_value = date(2026, 4, 20) + mock_date.side_effect = lambda *a, **kw: date(*a, **kw) + assert Config.get_default_date_range() == "2026-04-01--2026-04-20" + + @mock.patch.dict(os.environ, {"DEFAULT_FROM_DATE": "2026-02-01"}, clear=True) + def test_env_from_without_to_falls_back_to_today(self): + """DEFAULT_FROM_DATE задана, DEFAULT_TO_DATE нет → конец = сегодня.""" + from datetime import date + + Config._app = None + with mock.patch("redmine_reporter.config.date") as mock_date: + mock_date.today.return_value = date(2026, 2, 10) + mock_date.side_effect = lambda *a, **kw: date(*a, **kw) + assert Config.get_default_date_range() == "2026-02-01--2026-02-10" + + @mock.patch.dict(os.environ, {}, clear=True) def test_get_redmine_verify_default(): """Без явной настройки проверка TLS включена (стандартные CA requests)."""