Coverage for src / ezqt_app / domain / results / init_result.py: 94.44%
18 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-26 07:07 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-26 07:07 +0000
1# ///////////////////////////////////////////////////////////////
2# DOMAIN.RESULTS.INIT_RESULT - Initialization aggregate result model
3# Project: ezqt_app
4# ///////////////////////////////////////////////////////////////
6"""Typed aggregate result for initialization workflows."""
8from __future__ import annotations
10# ///////////////////////////////////////////////////////////////
11# IMPORTS
12# ///////////////////////////////////////////////////////////////
13# Standard library imports
14from dataclasses import dataclass, field
16# Local imports
17from ...shared.types import JsonMap
18from .init_step_result import InitStepResult
19from .result_error import ResultError
22# ///////////////////////////////////////////////////////////////
23# DATACLASSES
24# ///////////////////////////////////////////////////////////////
25@dataclass(slots=True)
26class InitResult:
27 """Aggregate initialization result consumed by API/CLI façades."""
29 success: bool
30 message: str | None = None
31 total_steps: int = 0
32 successful: int = 0
33 failed: int = 0
34 skipped: int = 0
35 total_time: float = 0.0
36 steps: list[InitStepResult] = field(default_factory=list)
37 error: ResultError | None = None
39 def to_dict(self) -> JsonMap:
40 """Convert to a dictionary for backward-compatible public API."""
41 return {
42 "success": self.success,
43 "message": self.message,
44 "total_steps": self.total_steps,
45 "successful": self.successful,
46 "failed": self.failed,
47 "skipped": self.skipped,
48 "total_time": self.total_time,
49 "steps": [
50 {
51 "name": step.name,
52 "description": step.description,
53 "required": step.required,
54 "status": step.status,
55 "error_message": step.error_message,
56 "duration": step.duration,
57 }
58 for step in self.steps
59 ],
60 "error": (
61 {
62 "code": self.error.code,
63 "message": self.error.message,
64 "context": self.error.context,
65 }
66 if self.error is not None
67 else None
68 ),
69 }