aury-boot 0.0.2__py3-none-any.whl → 0.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. aury/boot/__init__.py +66 -0
  2. aury/boot/_version.py +2 -2
  3. aury/boot/application/__init__.py +120 -0
  4. aury/boot/application/app/__init__.py +39 -0
  5. aury/boot/application/app/base.py +511 -0
  6. aury/boot/application/app/components.py +434 -0
  7. aury/boot/application/app/middlewares.py +101 -0
  8. aury/boot/application/config/__init__.py +44 -0
  9. aury/boot/application/config/settings.py +663 -0
  10. aury/boot/application/constants/__init__.py +19 -0
  11. aury/boot/application/constants/components.py +50 -0
  12. aury/boot/application/constants/scheduler.py +28 -0
  13. aury/boot/application/constants/service.py +29 -0
  14. aury/boot/application/errors/__init__.py +55 -0
  15. aury/boot/application/errors/chain.py +80 -0
  16. aury/boot/application/errors/codes.py +67 -0
  17. aury/boot/application/errors/exceptions.py +238 -0
  18. aury/boot/application/errors/handlers.py +320 -0
  19. aury/boot/application/errors/response.py +120 -0
  20. aury/boot/application/interfaces/__init__.py +76 -0
  21. aury/boot/application/interfaces/egress.py +224 -0
  22. aury/boot/application/interfaces/ingress.py +98 -0
  23. aury/boot/application/middleware/__init__.py +22 -0
  24. aury/boot/application/middleware/logging.py +451 -0
  25. aury/boot/application/migrations/__init__.py +13 -0
  26. aury/boot/application/migrations/manager.py +685 -0
  27. aury/boot/application/migrations/setup.py +237 -0
  28. aury/boot/application/rpc/__init__.py +63 -0
  29. aury/boot/application/rpc/base.py +108 -0
  30. aury/boot/application/rpc/client.py +294 -0
  31. aury/boot/application/rpc/discovery.py +218 -0
  32. aury/boot/application/scheduler/__init__.py +13 -0
  33. aury/boot/application/scheduler/runner.py +123 -0
  34. aury/boot/application/server/__init__.py +296 -0
  35. aury/boot/commands/__init__.py +30 -0
  36. aury/boot/commands/add.py +76 -0
  37. aury/boot/commands/app.py +105 -0
  38. aury/boot/commands/config.py +177 -0
  39. aury/boot/commands/docker.py +367 -0
  40. aury/boot/commands/docs.py +284 -0
  41. aury/boot/commands/generate.py +1277 -0
  42. aury/boot/commands/init.py +890 -0
  43. aury/boot/commands/migrate/__init__.py +37 -0
  44. aury/boot/commands/migrate/app.py +54 -0
  45. aury/boot/commands/migrate/commands.py +303 -0
  46. aury/boot/commands/scheduler.py +124 -0
  47. aury/boot/commands/server/__init__.py +21 -0
  48. aury/boot/commands/server/app.py +541 -0
  49. aury/boot/commands/templates/generate/api.py.tpl +105 -0
  50. aury/boot/commands/templates/generate/model.py.tpl +17 -0
  51. aury/boot/commands/templates/generate/repository.py.tpl +19 -0
  52. aury/boot/commands/templates/generate/schema.py.tpl +29 -0
  53. aury/boot/commands/templates/generate/service.py.tpl +48 -0
  54. aury/boot/commands/templates/project/CLI.md.tpl +92 -0
  55. aury/boot/commands/templates/project/DEVELOPMENT.md.tpl +1397 -0
  56. aury/boot/commands/templates/project/README.md.tpl +111 -0
  57. aury/boot/commands/templates/project/admin_console_init.py.tpl +50 -0
  58. aury/boot/commands/templates/project/config.py.tpl +30 -0
  59. aury/boot/commands/templates/project/conftest.py.tpl +26 -0
  60. aury/boot/commands/templates/project/env.example.tpl +213 -0
  61. aury/boot/commands/templates/project/gitignore.tpl +128 -0
  62. aury/boot/commands/templates/project/main.py.tpl +41 -0
  63. aury/boot/commands/templates/project/modules/api.py.tpl +19 -0
  64. aury/boot/commands/templates/project/modules/exceptions.py.tpl +84 -0
  65. aury/boot/commands/templates/project/modules/schedules.py.tpl +18 -0
  66. aury/boot/commands/templates/project/modules/tasks.py.tpl +20 -0
  67. aury/boot/commands/worker.py +143 -0
  68. aury/boot/common/__init__.py +35 -0
  69. aury/boot/common/exceptions/__init__.py +114 -0
  70. aury/boot/common/i18n/__init__.py +16 -0
  71. aury/boot/common/i18n/translator.py +272 -0
  72. aury/boot/common/logging/__init__.py +716 -0
  73. aury/boot/contrib/__init__.py +10 -0
  74. aury/boot/contrib/admin_console/__init__.py +18 -0
  75. aury/boot/contrib/admin_console/auth.py +137 -0
  76. aury/boot/contrib/admin_console/discovery.py +69 -0
  77. aury/boot/contrib/admin_console/install.py +172 -0
  78. aury/boot/contrib/admin_console/utils.py +44 -0
  79. aury/boot/domain/__init__.py +79 -0
  80. aury/boot/domain/exceptions/__init__.py +132 -0
  81. aury/boot/domain/models/__init__.py +51 -0
  82. aury/boot/domain/models/base.py +69 -0
  83. aury/boot/domain/models/mixins.py +135 -0
  84. aury/boot/domain/models/models.py +96 -0
  85. aury/boot/domain/pagination/__init__.py +279 -0
  86. aury/boot/domain/repository/__init__.py +23 -0
  87. aury/boot/domain/repository/impl.py +423 -0
  88. aury/boot/domain/repository/interceptors.py +47 -0
  89. aury/boot/domain/repository/interface.py +106 -0
  90. aury/boot/domain/repository/query_builder.py +348 -0
  91. aury/boot/domain/service/__init__.py +11 -0
  92. aury/boot/domain/service/base.py +73 -0
  93. aury/boot/domain/transaction/__init__.py +404 -0
  94. aury/boot/infrastructure/__init__.py +104 -0
  95. aury/boot/infrastructure/cache/__init__.py +31 -0
  96. aury/boot/infrastructure/cache/backends.py +348 -0
  97. aury/boot/infrastructure/cache/base.py +68 -0
  98. aury/boot/infrastructure/cache/exceptions.py +37 -0
  99. aury/boot/infrastructure/cache/factory.py +94 -0
  100. aury/boot/infrastructure/cache/manager.py +274 -0
  101. aury/boot/infrastructure/database/__init__.py +39 -0
  102. aury/boot/infrastructure/database/config.py +71 -0
  103. aury/boot/infrastructure/database/exceptions.py +44 -0
  104. aury/boot/infrastructure/database/manager.py +317 -0
  105. aury/boot/infrastructure/database/query_tools/__init__.py +164 -0
  106. aury/boot/infrastructure/database/strategies/__init__.py +198 -0
  107. aury/boot/infrastructure/di/__init__.py +15 -0
  108. aury/boot/infrastructure/di/container.py +393 -0
  109. aury/boot/infrastructure/events/__init__.py +33 -0
  110. aury/boot/infrastructure/events/bus.py +362 -0
  111. aury/boot/infrastructure/events/config.py +52 -0
  112. aury/boot/infrastructure/events/consumer.py +134 -0
  113. aury/boot/infrastructure/events/middleware.py +51 -0
  114. aury/boot/infrastructure/events/models.py +63 -0
  115. aury/boot/infrastructure/monitoring/__init__.py +529 -0
  116. aury/boot/infrastructure/scheduler/__init__.py +19 -0
  117. aury/boot/infrastructure/scheduler/exceptions.py +37 -0
  118. aury/boot/infrastructure/scheduler/manager.py +478 -0
  119. aury/boot/infrastructure/storage/__init__.py +38 -0
  120. aury/boot/infrastructure/storage/base.py +164 -0
  121. aury/boot/infrastructure/storage/exceptions.py +37 -0
  122. aury/boot/infrastructure/storage/factory.py +88 -0
  123. aury/boot/infrastructure/tasks/__init__.py +24 -0
  124. aury/boot/infrastructure/tasks/config.py +45 -0
  125. aury/boot/infrastructure/tasks/constants.py +37 -0
  126. aury/boot/infrastructure/tasks/exceptions.py +37 -0
  127. aury/boot/infrastructure/tasks/manager.py +490 -0
  128. aury/boot/testing/__init__.py +24 -0
  129. aury/boot/testing/base.py +122 -0
  130. aury/boot/testing/client.py +163 -0
  131. aury/boot/testing/factory.py +154 -0
  132. aury/boot/toolkit/__init__.py +21 -0
  133. aury/boot/toolkit/http/__init__.py +367 -0
  134. {aury_boot-0.0.2.dist-info → aury_boot-0.0.3.dist-info}/METADATA +3 -2
  135. aury_boot-0.0.3.dist-info/RECORD +137 -0
  136. aury_boot-0.0.2.dist-info/RECORD +0 -5
  137. {aury_boot-0.0.2.dist-info → aury_boot-0.0.3.dist-info}/WHEEL +0 -0
  138. {aury_boot-0.0.2.dist-info → aury_boot-0.0.3.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,393 @@
1
+ """依赖注入容器 - 实现控制反转(IoC)。
2
+
3
+ 提供依赖管理、生命周期控制和自动注入功能。
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from collections.abc import Callable
9
+ from enum import Enum
10
+ import inspect
11
+ from typing import Any, TypeVar
12
+
13
+ from aury.boot.common.logging import logger
14
+
15
+ T = TypeVar("T")
16
+
17
+
18
+ class Lifetime(Enum):
19
+ """服务生命周期。"""
20
+
21
+ SINGLETON = "singleton" # 单例,整个应用生命周期只创建一次
22
+ SCOPED = "scoped" # 作用域,每个作用域创建一次
23
+ TRANSIENT = "transient" # 瞬时,每次请求都创建新实例
24
+
25
+
26
+ class ServiceDescriptor:
27
+ """服务描述符。
28
+
29
+ 记录服务的注册信息,包括类型、工厂函数和生命周期。
30
+ """
31
+
32
+ def __init__(
33
+ self,
34
+ service_type: type[T],
35
+ implementation: type[T] | None = None,
36
+ factory: Callable[..., T] | None = None,
37
+ lifetime: Lifetime = Lifetime.TRANSIENT,
38
+ ) -> None:
39
+ """初始化服务描述符。
40
+
41
+ Args:
42
+ service_type: 服务类型(通常是接口或抽象类)
43
+ implementation: 实现类型(具体类)
44
+ factory: 工厂函数
45
+ lifetime: 生命周期
46
+ """
47
+ self.service_type = service_type
48
+ self.implementation = implementation or service_type
49
+ self.factory = factory
50
+ self.lifetime = lifetime
51
+
52
+ def __repr__(self) -> str:
53
+ """字符串表示。"""
54
+ return (
55
+ f"<ServiceDescriptor "
56
+ f"service={self.service_type.__name__} "
57
+ f"impl={self.implementation.__name__} "
58
+ f"lifetime={self.lifetime.value}>"
59
+ )
60
+
61
+
62
+ class Container:
63
+ """依赖注入容器(单例模式)。
64
+
65
+ 职责:
66
+ 1. 服务注册
67
+ 2. 依赖解析
68
+ 3. 生命周期管理
69
+ 4. 作用域管理
70
+
71
+ 使用示例:
72
+ # 注册服务
73
+ container = Container.get_instance()
74
+ container.register(IUserRepository, UserRepository, Lifetime.SCOPED)
75
+ container.register(UserService, lifetime=Lifetime.TRANSIENT)
76
+
77
+ # 解析服务
78
+ service = container.resolve(UserService)
79
+
80
+ # 使用作用域
81
+ with container.create_scope() as scope:
82
+ service = scope.resolve(UserService)
83
+ """
84
+
85
+ _instance: Container | None = None
86
+
87
+ def __init__(self) -> None:
88
+ """私有构造函数,使用 get_instance() 获取实例。"""
89
+ if Container._instance is not None:
90
+ raise RuntimeError("Container 是单例类,请使用 get_instance() 获取实例")
91
+
92
+ self._descriptors: dict[type, ServiceDescriptor] = {}
93
+ self._singletons: dict[type, Any] = {}
94
+ logger.debug("依赖注入容器已创建")
95
+
96
+ @classmethod
97
+ def get_instance(cls) -> Container:
98
+ """获取单例实例。"""
99
+ if cls._instance is None:
100
+ cls._instance = cls()
101
+ return cls._instance
102
+
103
+ def register(
104
+ self,
105
+ service_type: type[T],
106
+ implementation: type[T] | None = None,
107
+ factory: Callable[..., T] | None = None,
108
+ lifetime: Lifetime = Lifetime.TRANSIENT,
109
+ ) -> Container:
110
+ """注册服务。
111
+
112
+ Args:
113
+ service_type: 服务类型
114
+ implementation: 实现类型
115
+ factory: 工厂函数
116
+ lifetime: 生命周期
117
+
118
+ Returns:
119
+ Container: 容器实例(支持链式调用)
120
+ """
121
+ descriptor = ServiceDescriptor(
122
+ service_type=service_type,
123
+ implementation=implementation,
124
+ factory=factory,
125
+ lifetime=lifetime,
126
+ )
127
+ self._descriptors[service_type] = descriptor
128
+ logger.debug(f"注册服务: {descriptor}")
129
+ return self
130
+
131
+ def register_singleton(
132
+ self,
133
+ service_type: type[T],
134
+ implementation: type[T] | None = None,
135
+ factory: Callable[..., T] | None = None,
136
+ ) -> Container:
137
+ """注册单例服务。
138
+
139
+ Args:
140
+ service_type: 服务类型
141
+ implementation: 实现类型
142
+ factory: 工厂函数
143
+
144
+ Returns:
145
+ Container: 容器实例(支持链式调用)
146
+ """
147
+ return self.register(service_type, implementation, factory, Lifetime.SINGLETON)
148
+
149
+ def register_scoped(
150
+ self,
151
+ service_type: type[T],
152
+ implementation: type[T] | None = None,
153
+ factory: Callable[..., T] | None = None,
154
+ ) -> Container:
155
+ """注册作用域服务。
156
+
157
+ Args:
158
+ service_type: 服务类型
159
+ implementation: 实现类型
160
+ factory: 工厂函数
161
+
162
+ Returns:
163
+ Container: 容器实例(支持链式调用)
164
+ """
165
+ return self.register(service_type, implementation, factory, Lifetime.SCOPED)
166
+
167
+ def register_transient(
168
+ self,
169
+ service_type: type[T],
170
+ implementation: type[T] | None = None,
171
+ factory: Callable[..., T] | None = None,
172
+ ) -> Container:
173
+ """注册瞬时服务。
174
+
175
+ Args:
176
+ service_type: 服务类型
177
+ implementation: 实现类型
178
+ factory: 工厂函数
179
+
180
+ Returns:
181
+ Container: 容器实例(支持链式调用)
182
+ """
183
+ return self.register(service_type, implementation, factory, Lifetime.TRANSIENT)
184
+
185
+ def register_instance(self, service_type: type[T], instance: T) -> Container:
186
+ """注册实例(作为单例)。
187
+
188
+ Args:
189
+ service_type: 服务类型
190
+ instance: 实例对象
191
+
192
+ Returns:
193
+ Container: 容器实例(支持链式调用)
194
+ """
195
+ self._singletons[service_type] = instance
196
+ self._descriptors[service_type] = ServiceDescriptor(
197
+ service_type=service_type,
198
+ lifetime=Lifetime.SINGLETON,
199
+ )
200
+ logger.debug(f"注册实例: {service_type.__name__}")
201
+ return self
202
+
203
+ def resolve(self, service_type: type[T]) -> T:
204
+ """解析服务。
205
+
206
+ Args:
207
+ service_type: 服务类型
208
+
209
+ Returns:
210
+ T: 服务实例
211
+
212
+ Raises:
213
+ ValueError: 服务未注册时抛出
214
+ """
215
+ # 检查是否已有单例实例
216
+ if service_type in self._singletons:
217
+ return self._singletons[service_type]
218
+
219
+ # 获取服务描述符
220
+ descriptor = self._descriptors.get(service_type)
221
+ if descriptor is None:
222
+ raise ValueError(f"服务未注册: {service_type.__name__}")
223
+
224
+ # 创建实例
225
+ instance = self._create_instance(descriptor)
226
+
227
+ # 单例模式:缓存实例
228
+ if descriptor.lifetime == Lifetime.SINGLETON:
229
+ self._singletons[service_type] = instance
230
+
231
+ return instance
232
+
233
+ def _create_instance(self, descriptor: ServiceDescriptor, scope: Scope | None = None) -> Any:
234
+ """创建服务实例。
235
+
236
+ Args:
237
+ descriptor: 服务描述符
238
+ scope: 作用域(用于解析 SCOPED 类型的依赖)
239
+
240
+ Returns:
241
+ Any: 服务实例
242
+ """
243
+ # 使用工厂函数创建
244
+ if descriptor.factory is not None:
245
+ logger.debug(f"通过工厂创建: {descriptor.service_type.__name__}")
246
+ # 工厂函数可以接收容器或作用域
247
+ if scope is not None:
248
+ return descriptor.factory(scope)
249
+ return descriptor.factory(self)
250
+
251
+ # 使用构造函数创建
252
+ try:
253
+ logger.debug(f"通过构造函数创建: {descriptor.implementation.__name__}")
254
+ return descriptor.implementation()
255
+ except TypeError:
256
+ # 尝试自动注入依赖
257
+ resolver = scope if scope is not None else self
258
+ return self._create_with_dependencies(descriptor.implementation, resolver)
259
+
260
+ def _create_with_dependencies(self, cls: type[T], resolver: Any = None) -> T:
261
+ """创建实例并自动注入依赖。
262
+
263
+ 通过 inspect 获取构造函数参数,自动从容器解析依赖。
264
+
265
+ Args:
266
+ cls: 类型
267
+ resolver: 解析器(Container 或 Scope),默认使用 self
268
+
269
+ Returns:
270
+ T: 实例
271
+ """
272
+ if resolver is None:
273
+ resolver = self
274
+
275
+ sig = inspect.signature(cls.__init__)
276
+ params = sig.parameters
277
+
278
+ # 跳过 self 参数
279
+ args = []
280
+ kwargs = {}
281
+
282
+ for param_name, param in list(params.items())[1:]: # 跳过 self
283
+ param_type = param.annotation
284
+
285
+ # 如果参数有类型注解且不是 Any
286
+ if param_type != inspect.Parameter.empty and param_type != Any:
287
+ try:
288
+ # 尝试从容器/作用域解析
289
+ dependency = resolver.resolve(param_type)
290
+ if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
291
+ args.append(dependency)
292
+ else:
293
+ kwargs[param_name] = dependency
294
+ except (ValueError, KeyError):
295
+ # 如果容器中没有,检查是否有默认值
296
+ if param.default != inspect.Parameter.empty:
297
+ kwargs[param_name] = param.default
298
+ else:
299
+ logger.warning(
300
+ f"无法解析依赖 {param_name}: {param_type} "
301
+ f"在类 {cls.__name__} 中,使用默认值 None"
302
+ )
303
+ kwargs[param_name] = None
304
+
305
+ logger.debug(f"自动注入依赖: {cls.__name__} args={len(args)} kwargs={list(kwargs.keys())}")
306
+ return cls(*args, **kwargs)
307
+
308
+ def create_scope(self) -> Scope:
309
+ """创建作用域。
310
+
311
+ Returns:
312
+ Scope: 作用域对象
313
+ """
314
+ return Scope(self)
315
+
316
+ def clear(self) -> None:
317
+ """清空容器。"""
318
+ self._descriptors.clear()
319
+ self._singletons.clear()
320
+ logger.debug("容器已清空")
321
+
322
+ def __repr__(self) -> str:
323
+ """字符串表示。"""
324
+ return (
325
+ f"<Container "
326
+ f"services={len(self._descriptors)} "
327
+ f"singletons={len(self._singletons)}>"
328
+ )
329
+
330
+
331
+ class Scope:
332
+ """依赖注入作用域。
333
+
334
+ 管理作用域内服务的生命周期。
335
+ """
336
+
337
+ def __init__(self, container: Container) -> None:
338
+ """初始化作用域。
339
+
340
+ Args:
341
+ container: 容器实例
342
+ """
343
+ self._container = container
344
+ self._scoped_instances: dict[type, Any] = {}
345
+ logger.debug("作用域已创建")
346
+
347
+ def resolve(self, service_type: type[T]) -> T:
348
+ """解析服务。
349
+
350
+ Args:
351
+ service_type: 服务类型
352
+
353
+ Returns:
354
+ T: 服务实例
355
+ """
356
+ descriptor = self._container._descriptors.get(service_type)
357
+ if descriptor is None:
358
+ raise ValueError(f"服务未注册: {service_type.__name__}")
359
+
360
+ # 单例:从容器获取
361
+ if descriptor.lifetime == Lifetime.SINGLETON:
362
+ return self._container.resolve(service_type)
363
+
364
+ # 作用域:从作用域缓存获取
365
+ if descriptor.lifetime == Lifetime.SCOPED:
366
+ if service_type not in self._scoped_instances:
367
+ self._scoped_instances[service_type] = self._container._create_instance(descriptor, scope=self)
368
+ return self._scoped_instances[service_type]
369
+
370
+ # 瞬时:每次创建新实例
371
+ return self._container._create_instance(descriptor, scope=self)
372
+
373
+ def __enter__(self) -> Scope:
374
+ """进入作用域。"""
375
+ return self
376
+
377
+ def __exit__(self, exc_type, exc_val, exc_tb) -> None:
378
+ """退出作用域。"""
379
+ self._scoped_instances.clear()
380
+ logger.debug("作用域已销毁")
381
+
382
+ def __repr__(self) -> str:
383
+ """字符串表示。"""
384
+ return f"<Scope instances={len(self._scoped_instances)}>"
385
+
386
+
387
+ __all__ = [
388
+ "Container",
389
+ "Lifetime",
390
+ "Scope",
391
+ "ServiceDescriptor",
392
+ ]
393
+
@@ -0,0 +1,33 @@
1
+ """事件系统 - 基于 Kombu 消息队列的分布式事件总线。
2
+
3
+ 提供事件基础定义、发布/订阅机制,实现模块间的解耦。
4
+ 支持本地模式(内存)和分布式模式(Kombu 消息队列)。
5
+
6
+ **架构说明**:
7
+ Event 基类定义在 infrastructure 层,这是最底层的公共数据结构。
8
+ Domain 层依赖 infrastructure.events 获取 Event 基类。
9
+ 这样完全断开了 infrastructure 对 domain 的循环依赖。
10
+
11
+ 事件模型定义在单独的 models.py 文件中,避免循环导入问题。
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from .bus import EventBus
17
+ from .config import EventConfig
18
+ from .consumer import EventConsumer
19
+ from .middleware import EventLoggingMiddleware, EventMiddleware
20
+ from .models import Event, EventHandler, EventType
21
+
22
+ __all__ = [
23
+ "Event",
24
+ "EventBus",
25
+ "EventConfig",
26
+ "EventConsumer",
27
+ "EventHandler",
28
+ "EventLoggingMiddleware",
29
+ "EventMiddleware",
30
+ "EventType",
31
+ ]
32
+
33
+