refactor: период через period.from вместо last_used; дедуп удалён

Удалены last_used, precision, dynamic и дедупликация по created_on/updated_on. Период задаётся одним полем period.from (env FROM_DATE), окно -- от этой даты до сегодня. После успешного --commit/--send начало окна сдвигается на конец отчёта; datetime-границы --date приводятся к полным дням. Схема конфига ломающая: старые ключи игнорируются, миграция описана в документации.
This commit is contained in:
Кокос Артем Николаевич
2026-09-30 12:37:00 +07:00
parent db069dfb4b
commit 27d21ef639
11 changed files with 726 additions and 1365 deletions

View File

@@ -4,11 +4,14 @@ import tempfile
from pathlib import Path
from unittest import mock
import yaml
from redmine_reporter.yaml_config import (
check_file_permissions,
ensure_config_dir,
expand_filename_template,
resolve_env_vars,
save_period_to_config,
)
@@ -211,120 +214,65 @@ class TestResolveOutputPath:
class TestSavePeriodToConfig:
"""Tests for save_period_to_config()."""
def test_creates_last_used_in_empty_config(self, tmp_path):
import yaml
from redmine_reporter.yaml_config import save_period_to_config
def test_creates_period_from_in_empty_config(self, tmp_path):
config_path = tmp_path / "config.yml"
save_period_to_config(
str(config_path), "2026-06-01", "2026-06-30", "date", True
)
config_path.write_text("")
save_period_to_config(str(config_path), "2026-06-01")
with open(config_path) as fh:
data = yaml.safe_load(fh)
assert data["period"]["last_used"]["from"] == "2026-06-01"
assert data["period"]["last_used"]["to"] == "2026-06-30"
assert "default_from" not in data["period"]
def test_overwrites_existing_last_used(self, tmp_path):
import yaml
from redmine_reporter.yaml_config import save_period_to_config
assert data["period"]["from"] == "2026-06-01"
def test_overwrites_existing_period_from(self, tmp_path):
config_path = tmp_path / "config.yml"
config_path.write_text(
"period:\n last_used:\n from: '2026-05-01'\n to: '2026-05-31'\n"
)
config_path.write_text("period:\n from: '2026-05-01'\n")
save_period_to_config(
str(config_path), "2026-06-01", "2026-06-30", "date", True
)
save_period_to_config(str(config_path), "2026-06-01")
with open(config_path) as fh:
data = yaml.safe_load(fh)
assert data["period"]["last_used"]["from"] == "2026-06-01"
assert data["period"]["last_used"]["to"] == "2026-06-30"
def test_dynamic_false_overwrites_defaults(self, tmp_path):
import yaml
from redmine_reporter.yaml_config import save_period_to_config
config_path = tmp_path / "config.yml"
config_path.write_text(
"period:\n default_from: '2026-01-01'\n default_to: '2026-01-31'\n"
)
save_period_to_config(
str(config_path), "2026-06-01", "2026-06-30", "date", False
)
with open(config_path) as fh:
data = yaml.safe_load(fh)
assert data["period"]["default_from"] == "2026-06-01"
assert data["period"]["default_to"] == "2026-06-30"
assert data["period"]["last_used"]["from"] == "2026-06-01"
assert data["period"]["last_used"]["to"] == "2026-06-30"
def test_datetime_precision_stores_timestamps(self, tmp_path):
import yaml
from redmine_reporter.yaml_config import save_period_to_config
config_path = tmp_path / "config.yml"
save_period_to_config(
str(config_path),
"2026-06-30T09:00:00",
"2026-06-30T12:00:00",
"datetime",
True,
)
with open(config_path) as fh:
data = yaml.safe_load(fh)
assert data["period"]["last_used"]["from"] == "2026-06-30T09:00:00"
assert data["period"]["last_used"]["to"] == "2026-06-30T12:00:00"
def test_preserves_existing_sections(self, tmp_path):
import yaml
from redmine_reporter.yaml_config import save_period_to_config
assert data["period"]["from"] == "2026-06-01"
def test_preserves_other_sections_and_keys(self, tmp_path):
config_path = tmp_path / "config.yml"
config_path.write_text(
"redmine:\n"
" url: https://example.com\n"
" author: Test\n"
"email:\n"
" enabled: true\n"
"output:\n"
" dir: /tmp\n"
)
save_period_to_config(
str(config_path), "2026-06-01", "2026-06-30", "date", True
)
save_period_to_config(str(config_path), "2026-06-01")
with open(config_path) as fh:
data = yaml.safe_load(fh)
assert data["redmine"]["url"] == "https://example.com"
assert data["redmine"]["author"] == "Test"
assert data["output"]["dir"] == "/tmp"
assert data["period"]["last_used"]["from"] == "2026-06-01"
assert data["redmine"] == {"url": "https://example.com", "author": "Test"}
assert data["email"] == {"enabled": True}
assert data["output"] == {"dir": "/tmp"}
assert data["period"] == {"from": "2026-06-01"}
def test_sets_permissions_0600(self, tmp_path):
from redmine_reporter.yaml_config import save_period_to_config
config_path = tmp_path / "config.yml"
save_period_to_config(
str(config_path), "2026-06-01", "2026-06-30", "date", True
)
save_period_to_config(str(config_path), "2026-06-01")
mode = config_path.stat().st_mode & 0o777
assert mode == 0o600
def test_creates_config_file_and_dir_when_missing(self, tmp_path):
config_path = tmp_path / "nested" / "config.yml"
assert not config_path.exists()
save_period_to_config(str(config_path), "2026-06-01")
assert config_path.exists()
with open(config_path) as fh:
data = yaml.safe_load(fh)
assert data["period"]["from"] == "2026-06-01"