# -*- coding: utf-8 -*- # hub/ticket/state/repository.py """Файловый репозиторий Ticket для хранения задач.""" from __future__ import annotations import json from datetime import datetime from pathlib import Path from typing import Any from error_logger import log_exception from domain.task import TicketTask from .paths import ensure_storage_directories class TicketStateRepository: """Канонический файловый репозиторий состояния Ticket.""" def __init__(self, tasks_file: Path): self._tasks_file = tasks_file ensure_storage_directories() self._tasks_file.parent.mkdir(parents=True, exist_ok=True) def load_tasks(self) -> list[TicketTask]: """Загрузить все задачи из хранилища.""" try: if not self._tasks_file.exists(): return [] with open(self._tasks_file, "r", encoding="utf-8") as handle: raw_tasks = json.load(handle) except Exception as exc: log_exception(__name__, "TicketStateRepository.load_tasks", exc) return [] if not isinstance(raw_tasks, list): return [] tasks: list[TicketTask] = [] for raw_task in raw_tasks: if not isinstance(raw_task, dict): continue task = TicketTask.from_record(raw_task) if task is not None: tasks.append(task) return tasks def save_tasks(self, tasks: list[TicketTask]) -> bool: """Сохранить все задачи в каноническое JSON-хранилище.""" try: payload = [task.to_record() for task in tasks] with open(self._tasks_file, "w", encoding="utf-8") as handle: json.dump( payload, handle, indent=2, ensure_ascii=False, default=self._json_serializer, ) except Exception as exc: log_exception(__name__, "TicketStateRepository.save_tasks", exc) return False return True @staticmethod def _json_serializer(value: Any) -> str: """Сериализовать datetime и родственные значения для JSON.""" if isinstance(value, datetime): return value.isoformat() raise TypeError(f"Object of type {type(value)} is not JSON serializable")