import os from datetime import date, timedelta from typing import Union from dotenv import load_dotenv load_dotenv(override=False) DEFAULT_REDMINE_VERIFY = "/etc/ssl/certs/ca-certificates.crt" FALSE_VALUES = {"0", "false", "no", "off"} 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 def get_redmine_user(cls) -> str: return os.getenv("REDMINE_USER", "").strip() @classmethod def get_redmine_password(cls) -> str: return os.getenv("REDMINE_PASSWORD", "").strip() @classmethod def get_redmine_verify(cls) -> Union[bool, str]: value = os.getenv("REDMINE_VERIFY", "").strip() if not value: return DEFAULT_REDMINE_VERIFY normalized = value.lower() if normalized in FALSE_VALUES: return False if normalized in TRUE_VALUES: return True return value @classmethod def get_author(cls, cli_author: str = "") -> str: """Возвращает автора: из CLI если задан, иначе из .env, иначе — заглушку.""" if cli_author: return cli_author return os.getenv("REDMINE_AUTHOR", "").strip() @classmethod def get_default_date_range(cls) -> str: default_from_date = os.getenv("DEFAULT_FROM_DATE", "").strip() 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: текущий месяц 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: if not cls.get_redmine_url(): raise ValueError("REDMINE_URL is required (set via env or .env)") if cls.get_redmine_api_key(): return if not (cls.get_redmine_user() and cls.get_redmine_password()): raise ValueError( "REDMINE_API_KEY is required, or set both REDMINE_USER and REDMINE_PASSWORD" )