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

1# /////////////////////////////////////////////////////////////// 

2# SERVICES.BOOTSTRAP.INITIALIZER - Main application initializer 

3# Project: ezqt_app 

4# /////////////////////////////////////////////////////////////// 

5 

6"""High-level initializer that coordinates the complete EzQt_App boot sequence.""" 

7 

8from __future__ import annotations 

9 

10# /////////////////////////////////////////////////////////////// 

11# IMPORTS 

12# /////////////////////////////////////////////////////////////// 

13# Standard library imports 

14from pathlib import Path 

15 

16# Third-party imports 

17from ezplog.lib_mode import get_logger 

18 

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 

27 

28# /////////////////////////////////////////////////////////////// 

29# CLASSES 

30# /////////////////////////////////////////////////////////////// 

31_logger = get_logger("ezqt_app.bootstrap.initializer") 

32 

33 

34class Initializer: 

35 """Coordinates the complete EzQt_App initialization process. 

36 

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 """ 

43 

44 def __init__(self) -> None: 

45 self._startup_config = StartupConfig() 

46 self._file_service = FileService() 

47 self._sequence = InitializationSequence() 

48 self._init_service = InitService() 

49 

50 # ------------------------------------------------------------------ 

51 # Main entry points 

52 # ------------------------------------------------------------------ 

53 

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). 

61 

62 Parameters 

63 ---------- 

64 mk_theme: 

65 Generate theme files (default: ``True``). 

66 verbose: 

67 Print progress information (default: ``True``). 

68 

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) 

80 

81 def setup_project(self, base_path: str | None = None) -> bool: 

82 """Configure startup then scaffold a new project directory. 

83 

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() 

91 

92 # ------------------------------------------------------------------ 

93 # Granular helpers 

94 # ------------------------------------------------------------------ 

95 

96 def configure_startup(self) -> None: 

97 """Run system-level startup configuration only.""" 

98 self._startup_config.configure() 

99 

100 def generate_assets(self) -> bool: 

101 """Generate all required asset files.""" 

102 return self._file_service.generate_all_assets() 

103 

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 

112 

113 def make_required_files(self, mk_theme: bool = True) -> None: 

114 """Generate required config/resource files.""" 

115 AppService.make_required_files(mk_theme) 

116 

117 # ------------------------------------------------------------------ 

118 # State 

119 # ------------------------------------------------------------------ 

120 

121 def is_initialized(self) -> bool: 

122 return self._init_service.is_initialized() 

123 

124 def reset(self) -> None: 

125 self._init_service.reset() 

126 self._startup_config.reset() 

127 self._sequence.reset() 

128 

129 # ------------------------------------------------------------------ 

130 # Accessors (kept for compat) 

131 # ------------------------------------------------------------------ 

132 

133 def get_startup_config(self) -> StartupConfig: 

134 return self._startup_config 

135 

136 def get_file_service(self) -> FileService: 

137 return self._file_service 

138 

139 def get_sequence(self) -> InitializationSequence: 

140 return self._sequence