Coverage for  / home / runner / work / bijux-cli / bijux-cli / src / bijux_cli / services / __init__.py: 98%

63 statements  

« prev     ^ index     » next       coverage.py v7.13.2, created at 2026-01-26 17:59 +0000

1# SPDX-License-Identifier: Apache-2.0 

2# Copyright © 2025 Bijan Mousavi 

3 

4"""Registers the default services for the Bijux CLI application. 

5 

6This module serves as the primary composition root for the application's 

7service layer. It provides a single function, `register_default_services`, 

8which is responsible for binding all core service protocols to their 

9concrete implementations within the Dependency Injection (DI) container. 

10 

11This centralized registration is a key part of the application's Inversion of 

12Control (IoC) architecture, allowing components to be easily swapped or mocked 

13for testing. 

14""" 

15 

16from __future__ import annotations 

17 

18import os 

19from typing import TYPE_CHECKING, cast 

20 

21from bijux_cli.core.contracts import ExecutionContext 

22from bijux_cli.core.enums import OutputFormat 

23from bijux_cli.infra.contracts import Emitter, ProcessRunner, RetryPolicy, Serializer 

24from bijux_cli.services.config.contracts import ConfigProtocol 

25from bijux_cli.services.contracts import ObservabilityProtocol, TelemetryProtocol 

26from bijux_cli.services.diagnostics.contracts import ( 

27 AuditProtocol, 

28 DiagnosticsConfig, 

29 DocsProtocol, 

30 DoctorProtocol, 

31 MemoryProtocol, 

32) 

33from bijux_cli.services.history.contracts import HistoryProtocol 

34from bijux_cli.services.logging.contracts import LoggingConfig 

35 

36if TYPE_CHECKING: 

37 from bijux_cli.core.di import DIContainer 

38 from bijux_cli.core.enums import OutputFormat 

39 

40 

41def register_default_services( 

42 di: DIContainer, 

43 *, 

44 logging_config: LoggingConfig, 

45 output_format: OutputFormat, 

46 diagnostics_config: DiagnosticsConfig | None = None, 

47) -> None: 

48 """Registers all default service implementations with the DI container. 

49 

50 This function populates the container with lazy-loading factories for each 

51 core service the application requires, from configuration and logging to 

52 plugin management and command history. 

53 

54 Args: 

55 di (DIContainer): The dependency injection container instance. 

56 logging_config (LoggingConfig): Logging configuration for services. 

57 output_format (OutputFormat): The default output format for services 

58 like the emitter and serializer. 

59 

60 Returns: 

61 None: 

62 """ 

63 import bijux_cli.core.context 

64 import bijux_cli.infra.emitter 

65 import bijux_cli.infra.process 

66 import bijux_cli.infra.retry 

67 import bijux_cli.infra.serializer 

68 import bijux_cli.infra.telemetry 

69 import bijux_cli.services.config 

70 import bijux_cli.services.diagnostics.audit 

71 import bijux_cli.services.diagnostics.docs 

72 import bijux_cli.services.diagnostics.doctor 

73 import bijux_cli.services.diagnostics.memory 

74 import bijux_cli.services.diagnostics.telemetry 

75 import bijux_cli.services.history 

76 import bijux_cli.services.logging.observability 

77 

78 if diagnostics_config is None: 78 ↛ 81line 78 didn't jump to line 81 because the condition on line 78 was always true

79 diagnostics_config = DiagnosticsConfig(enabled=True, telemetry_enabled=True) 

80 

81 di.register(DiagnosticsConfig, lambda: diagnostics_config) 

82 

83 noop_telemetry = bijux_cli.infra.telemetry.NoopTelemetry() 

84 obs_service = bijux_cli.services.logging.observability.Observability( 

85 log_level=logging_config.log_level, 

86 telemetry=noop_telemetry, 

87 ) 

88 

89 di.register( 

90 bijux_cli.services.logging.observability.Observability, lambda: obs_service 

91 ) 

92 di.register( 

93 ObservabilityProtocol, 

94 lambda: di.resolve(bijux_cli.services.logging.observability.Observability), 

95 ) 

96 

97 di.register( 

98 bijux_cli.infra.telemetry.LoggingTelemetry, 

99 lambda: bijux_cli.infra.telemetry.LoggingTelemetry( 

100 observability=di.resolve( 

101 bijux_cli.services.logging.observability.Observability 

102 ) 

103 ), 

104 ) 

105 di.register(bijux_cli.infra.telemetry.NoopTelemetry, lambda: noop_telemetry) 

106 di.register( 

107 TelemetryProtocol, 

108 lambda: bijux_cli.services.diagnostics.telemetry.resolve_telemetry(di), 

109 ) 

110 

111 di.register( 

112 bijux_cli.infra.emitter.ConsoleEmitter, 

113 lambda: bijux_cli.infra.emitter.ConsoleEmitter( 

114 telemetry=di.resolve(TelemetryProtocol), 

115 output_format=output_format, 

116 ), 

117 ) 

118 di.register(Emitter, lambda: di.resolve(bijux_cli.infra.emitter.ConsoleEmitter)) 

119 

120 di.register( 

121 bijux_cli.infra.serializer.OrjsonSerializer, 

122 lambda: bijux_cli.infra.serializer.OrjsonSerializer( 

123 telemetry=di.resolve(TelemetryProtocol) 

124 ), 

125 ) 

126 di.register( 

127 bijux_cli.infra.serializer.PyYAMLSerializer, 

128 lambda: bijux_cli.infra.serializer.PyYAMLSerializer( 

129 telemetry=di.resolve(TelemetryProtocol) 

130 ), 

131 ) 

132 di.register( 

133 Serializer, 

134 lambda: ( 

135 di.resolve(bijux_cli.infra.serializer.OrjsonSerializer) 

136 if output_format is OutputFormat.JSON 

137 else di.resolve(bijux_cli.infra.serializer.PyYAMLSerializer) 

138 ), 

139 ) 

140 

141 di.register( 

142 bijux_cli.infra.process.ProcessPool, 

143 lambda: bijux_cli.infra.process.ProcessPool( 

144 observability=di.resolve( 

145 bijux_cli.services.logging.observability.Observability 

146 ), 

147 telemetry=di.resolve(TelemetryProtocol), 

148 max_workers=int(os.getenv("BIJUXCLI_MAX_WORKERS", "4")), 

149 allowed_commands=os.getenv( 

150 "BIJUXCLI_ALLOWED_COMMANDS", "echo,ls,cat,grep" 

151 ).split(","), 

152 ), 

153 ) 

154 di.register(ProcessRunner, lambda: di.resolve(bijux_cli.infra.process.ProcessPool)) 

155 

156 di.register( 

157 bijux_cli.infra.retry.TimeoutRetryPolicy, 

158 lambda: bijux_cli.infra.retry.TimeoutRetryPolicy( 

159 telemetry=di.resolve(TelemetryProtocol) 

160 ), 

161 ) 

162 di.register( 

163 bijux_cli.infra.retry.ExponentialBackoffRetryPolicy, 

164 lambda: bijux_cli.infra.retry.ExponentialBackoffRetryPolicy( 

165 telemetry=di.resolve(TelemetryProtocol) 

166 ), 

167 ) 

168 di.register( 

169 RetryPolicy, 

170 lambda: cast( 

171 RetryPolicy, 

172 di.resolve(bijux_cli.infra.retry.TimeoutRetryPolicy), 

173 ), 

174 ) 

175 

176 di.register(LoggingConfig, lambda: logging_config) 

177 

178 di.register( 

179 bijux_cli.core.context.Context, 

180 lambda: bijux_cli.core.context.Context(di), 

181 ) 

182 di.register(ExecutionContext, lambda: di.resolve(bijux_cli.core.context.Context)) 

183 

184 di.register( 

185 bijux_cli.services.config.Config, 

186 lambda: bijux_cli.services.config.Config(di), 

187 ) 

188 di.register(ConfigProtocol, lambda: di.resolve(bijux_cli.services.config.Config)) 

189 

190 di.register( 

191 bijux_cli.services.diagnostics.audit.DryRunAudit, 

192 lambda: bijux_cli.services.diagnostics.audit.DryRunAudit( 

193 di.resolve(bijux_cli.services.logging.observability.Observability), 

194 di.resolve(TelemetryProtocol), 

195 ), 

196 ) 

197 di.register( 

198 bijux_cli.services.diagnostics.audit.RealAudit, 

199 lambda: bijux_cli.services.diagnostics.audit.RealAudit( 

200 di.resolve(bijux_cli.services.logging.observability.Observability), 

201 di.resolve(TelemetryProtocol), 

202 allowed_commands=os.getenv( 

203 "BIJUXCLI_ALLOWED_COMMANDS", "echo,ls,cat,grep" 

204 ).split(","), 

205 ), 

206 ) 

207 di.register( 

208 AuditProtocol, 

209 lambda: bijux_cli.services.diagnostics.audit.get_audit_service( 

210 observability=di.resolve( 

211 bijux_cli.services.logging.observability.Observability 

212 ), 

213 telemetry=di.resolve(TelemetryProtocol), 

214 dry_run=False, 

215 ), 

216 ) 

217 

218 di.register( 

219 bijux_cli.services.diagnostics.docs.Docs, 

220 lambda: bijux_cli.services.diagnostics.docs.Docs( 

221 observability=di.resolve( 

222 bijux_cli.services.logging.observability.Observability 

223 ), 

224 serializer=di.resolve(Serializer), 

225 telemetry=di.resolve(TelemetryProtocol), 

226 ), 

227 ) 

228 di.register( 

229 DocsProtocol, lambda: di.resolve(bijux_cli.services.diagnostics.docs.Docs) 

230 ) 

231 

232 di.register( 

233 bijux_cli.services.diagnostics.doctor.Doctor, 

234 lambda: bijux_cli.services.diagnostics.doctor.Doctor(), 

235 ) 

236 di.register( 

237 DoctorProtocol, lambda: di.resolve(bijux_cli.services.diagnostics.doctor.Doctor) 

238 ) 

239 

240 di.register( 

241 bijux_cli.services.history.History, 

242 lambda: bijux_cli.services.history.History( 

243 telemetry=di.resolve(TelemetryProtocol), 

244 observability=di.resolve( 

245 bijux_cli.services.logging.observability.Observability 

246 ), 

247 ), 

248 ) 

249 di.register(HistoryProtocol, lambda: di.resolve(bijux_cli.services.history.History)) 

250 

251 di.register( 

252 bijux_cli.services.diagnostics.memory.Memory, 

253 lambda: bijux_cli.services.diagnostics.memory.Memory(), 

254 ) 

255 di.register( 

256 MemoryProtocol, lambda: di.resolve(bijux_cli.services.diagnostics.memory.Memory) 

257 ) 

258 

259 

260__all__ = ["register_default_services"]