feat(cli): dynamic default range, --version, --verbose, --debug, --url, --api-key, --config
- #17: default date range falls back to current month when .env dates are missing - #18: add --version, --verbose, --debug flags - #20: add --url, --api-key, --config CLI overrides - Config supports CLI overrides for URL/API key and explicit config file loading - Update README with new CLI options - Add tests for new flags and config overrides Closes #17, closes #18, closes #20
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
from datetime import date, timedelta
|
||||
from typing import Union
|
||||
|
||||
from dotenv import load_dotenv
|
||||
@@ -11,12 +12,32 @@ TRUE_VALUES = {"1", "true", "yes", "on"}
|
||||
|
||||
|
||||
class Config:
|
||||
_cli_url: str | None = None
|
||||
_cli_api_key: str | None = None
|
||||
|
||||
@classmethod
|
||||
def load_config(cls, path: str) -> None:
|
||||
"""Загружает переменные из указанного .env-файла с override."""
|
||||
load_dotenv(path, override=True)
|
||||
|
||||
@classmethod
|
||||
def set_redmine_url(cls, url: str) -> None:
|
||||
cls._cli_url = url.strip().rstrip("/") if url else None
|
||||
|
||||
@classmethod
|
||||
def set_redmine_api_key(cls, key: str) -> None:
|
||||
cls._cli_api_key = key.strip() if key else None
|
||||
|
||||
@classmethod
|
||||
def get_redmine_url(cls) -> str:
|
||||
if cls._cli_url is not None:
|
||||
return cls._cli_url
|
||||
return os.getenv("REDMINE_URL", "").strip().rstrip("/")
|
||||
|
||||
@classmethod
|
||||
def get_redmine_api_key(cls) -> str:
|
||||
if cls._cli_api_key is not None:
|
||||
return cls._cli_api_key
|
||||
return os.getenv("REDMINE_API_KEY", "").strip()
|
||||
|
||||
@classmethod
|
||||
@@ -53,8 +74,17 @@ class Config:
|
||||
default_to_date = os.getenv("DEFAULT_TO_DATE", "").strip()
|
||||
if default_from_date and default_to_date:
|
||||
return f"{default_from_date}--{default_to_date}"
|
||||
# fallback hardcoded
|
||||
return "2025-12-19--2026-01-31"
|
||||
|
||||
# fallback: текущий месяц
|
||||
today = date.today()
|
||||
start = today.replace(day=1)
|
||||
# последний день месяца: берём первое число следующего месяца и вычитаем день
|
||||
if today.month == 12:
|
||||
next_month = today.replace(year=today.year + 1, month=1, day=1)
|
||||
else:
|
||||
next_month = today.replace(month=today.month + 1, day=1)
|
||||
end = next_month - timedelta(days=1)
|
||||
return f"{start.isoformat()}--{end.isoformat()}"
|
||||
|
||||
@classmethod
|
||||
def validate(cls) -> None:
|
||||
|
||||
Reference in New Issue
Block a user