Coverage for src / ezqt_app / services / bootstrap / initializer.py: 50.00%
48 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-06 13:12 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-06 13:12 +0000
1# ///////////////////////////////////////////////////////////////
2# SERVICES.BOOTSTRAP.INITIALIZER - Main application initializer
3# Project: ezqt_app
4# ///////////////////////////////////////////////////////////////
6"""High-level initializer that coordinates the complete EzQt_App boot sequence."""
8from __future__ import annotations
10# ///////////////////////////////////////////////////////////////
11# IMPORTS
12# ///////////////////////////////////////////////////////////////
13# Standard library imports
14from pathlib import Path
16# Third-party imports
17from ezplog.lib_mode import get_logger
19# Local imports
20from ...domain.results import InitResult
21from ..application.app_service import AppService
22from ..application.file_service import FileService
23from .contracts.options import InitOptions, OverwritePolicy
24from .init_service import InitService
25from .sequence import InitializationSequence
26from .startup_config import StartupConfig
28# ///////////////////////////////////////////////////////////////
29# CLASSES
30# ///////////////////////////////////////////////////////////////
31_logger = get_logger("ezqt_app.bootstrap.initializer")
34class Initializer:
35 """Coordinates the complete EzQt_App initialization process.
37 Orchestrates:
38 - Startup configuration (encoding, locale, env)
39 - Asset and file generation via :class:`FileService`
40 - Application requirements via :class:`AppService`
41 - Idempotent guard (subsequent :meth:`initialize` calls are no-ops)
42 """
44 def __init__(self) -> None:
45 self._startup_config = StartupConfig()
46 self._file_service = FileService()
47 self._sequence = InitializationSequence()
48 self._init_service = InitService()
50 # ------------------------------------------------------------------
51 # Main entry points
52 # ------------------------------------------------------------------
54 def initialize(
55 self,
56 _mk_theme: bool = True,
57 verbose: bool = True,
58 options: InitOptions | None = None,
59 ) -> InitResult:
60 """Run the complete boot sequence (idempotent).
62 Parameters
63 ----------
64 mk_theme:
65 Generate theme files (default: ``True``).
66 verbose:
67 Print progress information (default: ``True``).
69 Returns
70 -------
71 dict
72 Initialization summary (see :meth:`InitializationSequence.execute`).
73 """
74 resolved = options or InitOptions(
75 mk_theme=_mk_theme,
76 verbose=verbose,
77 overwrite_policy=OverwritePolicy.ASK,
78 )
79 return self._init_service.run(resolved)
81 def setup_project(self, base_path: str | None = None) -> bool:
82 """Configure startup then scaffold a new project directory.
84 Parameters
85 ----------
86 base_path:
87 Root directory for the new project. Defaults to ``cwd``.
88 """
89 self._startup_config.configure()
90 return FileService(Path(base_path) if base_path else None).setup_project()
92 # ------------------------------------------------------------------
93 # Granular helpers
94 # ------------------------------------------------------------------
96 def configure_startup(self) -> None:
97 """Run system-level startup configuration only."""
98 self._startup_config.configure()
100 def generate_assets(self) -> bool:
101 """Generate all required asset files."""
102 return self._file_service.generate_all_assets()
104 def check_requirements(self) -> bool:
105 """Return ``True`` if asset requirements are satisfied."""
106 try:
107 AppService.check_assets_requirements()
108 return True
109 except Exception as e:
110 _logger.error(f"Asset requirements check failed: {e}")
111 return False
113 def make_required_files(self, mk_theme: bool = True) -> None:
114 """Generate required config/resource files."""
115 AppService.make_required_files(mk_theme)
117 # ------------------------------------------------------------------
118 # State
119 # ------------------------------------------------------------------
121 def is_initialized(self) -> bool:
122 return self._init_service.is_initialized()
124 def reset(self) -> None:
125 self._init_service.reset()
126 self._startup_config.reset()
127 self._sequence.reset()
129 # ------------------------------------------------------------------
130 # Accessors (kept for compat)
131 # ------------------------------------------------------------------
133 def get_startup_config(self) -> StartupConfig:
134 return self._startup_config
136 def get_file_service(self) -> FileService:
137 return self._file_service
139 def get_sequence(self) -> InitializationSequence:
140 return self._sequence