aury-boot 0.0.2__py3-none-any.whl → 0.0.4__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 +892 -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.4.dist-info}/METADATA +3 -2
  135. aury_boot-0.0.4.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.4.dist-info}/WHEEL +0 -0
  138. {aury_boot-0.0.2.dist-info → aury_boot-0.0.4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,76 @@
1
+ """给已有项目添加可选模块。
2
+
3
+ 用法:
4
+ aury add admin-console # 添加 Admin Console 模块
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from pathlib import Path
10
+
11
+ from rich.console import Console
12
+ import typer
13
+
14
+ from .config import get_project_config
15
+
16
+ console = Console()
17
+
18
+ app = typer.Typer(
19
+ name="add",
20
+ help="给已有项目添加可选模块",
21
+ no_args_is_help=True,
22
+ )
23
+
24
+
25
+ @app.command(name="admin-console")
26
+ def add_admin_console(
27
+ force: bool = typer.Option(False, "--force", "-f", help="强制覆盖已有 admin_console.py"),
28
+ enable_env: bool = typer.Option(True, "--enable-env", help="尝试在 .env.example 中开启 ADMIN_* 示例配置"),
29
+ ) -> None:
30
+ """添加 Admin Console 模块到现有项目。
31
+
32
+ 将在项目代码根(包根或平铺)下生成 `admin_console.py`,便于注册 SQLAdmin 的 ModelView / 自定义认证。
33
+
34
+ 同时(可选)在 `.env.example` 中启用 ADMIN 示例配置,方便快速启动。
35
+ """
36
+ from .init import init_admin_console_module
37
+
38
+ base_path = Path.cwd()
39
+ config = get_project_config(base_path)
40
+ code_root = config.get_package_dir(base_path)
41
+ import_prefix = config.get_import_prefix()
42
+
43
+ result = init_admin_console_module(
44
+ base_path=base_path,
45
+ code_root=code_root,
46
+ import_prefix=import_prefix,
47
+ force=force,
48
+ enable_env=enable_env,
49
+ )
50
+
51
+ # 输出结果
52
+ admin_pkg = code_root / "admin_console"
53
+ if result["file_created"]:
54
+ console.print(f"[green]✅ 已生成: {admin_pkg.relative_to(base_path)}/[/green]")
55
+ elif result["file_existed"]:
56
+ console.print(f"[yellow]⚠️ 已存在: {admin_pkg.relative_to(base_path)}/(使用 --force 覆盖)[/yellow]")
57
+
58
+ if enable_env:
59
+ if result["env_updated"]:
60
+ console.print("[green]✅ 已在 .env.example 中启用 ADMIN_* 示例配置[/green]")
61
+ elif (base_path / ".env.example").exists():
62
+ console.print("[dim]ℹ️ .env.example 已包含 ADMIN_* 配置示例[/dim]")
63
+ else:
64
+ console.print("[dim]ℹ️ 未找到 .env.example,已跳过环境示例更新[/dim]")
65
+
66
+ console.print()
67
+ console.print("[bold]下一步:[/bold]")
68
+ console.print(" 1. 安装扩展依赖(如未安装):")
69
+ console.print(' [cyan]uv add "aury-boot[admin]"[/cyan]')
70
+ console.print(" 2. 复制 .env.example 并按需修改:")
71
+ console.print(" [cyan]cp .env.example .env[/cyan]")
72
+ console.print(" 3. 启动开发服务器并访问:")
73
+ console.print(" [cyan]aury server dev[/cyan] → http://127.0.0.1:8000/api/admin-console")
74
+
75
+
76
+ __all__ = ["app"]
@@ -0,0 +1,105 @@
1
+ """Aury Boot 统一命令行入口。
2
+
3
+ 提供统一的 CLI 入口,整合所有子命令:
4
+ - aury init 项目脚手架初始化
5
+ - aury generate 代码生成器
6
+ - aury server 服务器管理
7
+ - aury scheduler 独立运行调度器
8
+ - aury worker 运行任务队列 Worker
9
+ - aury migrate 数据库迁移
10
+ - aury docker Docker 配置生成
11
+ - aury docs 生成/更新项目文档
12
+
13
+ 使用示例:
14
+ aury init # 初始化项目
15
+ aury generate crud user # 生成 CRUD 代码
16
+ aury server dev # 启动开发服务器
17
+ aury scheduler # 独立运行调度器
18
+ aury worker # 运行 Worker
19
+ aury migrate up # 执行数据库迁移
20
+ aury docs all --force # 更新所有文档
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import typer
26
+
27
+ app: typer.Typer | None = None
28
+ _registered = False
29
+
30
+
31
+ def _get_app() -> typer.Typer:
32
+ """获取并初始化 Typer 应用(延迟加载)。"""
33
+ global app, _registered
34
+
35
+ if app is None:
36
+ app = typer.Typer(
37
+ name="aury",
38
+ help="🚀 Aury Boot CLI - 现代化微服务开发工具",
39
+ add_completion=True,
40
+ no_args_is_help=True,
41
+ rich_markup_mode="rich",
42
+ )
43
+
44
+ @app.callback(invoke_without_command=True)
45
+ def callback(
46
+ ctx: typer.Context,
47
+ version: bool = typer.Option(
48
+ False,
49
+ "--version",
50
+ "-v",
51
+ help="显示版本信息",
52
+ is_eager=True,
53
+ ),
54
+ ) -> None:
55
+ """Aury Boot - 现代化微服务基础架构框架。"""
56
+ if version:
57
+ from rich.console import Console
58
+
59
+ from aury.boot import __version__
60
+ console = Console()
61
+ console.print(f"[bold cyan]Aury Boot[/bold cyan] v{__version__}")
62
+ raise typer.Exit()
63
+
64
+ if not _registered:
65
+ _registered = True
66
+ # 延迟导入子命令
67
+ from .add import app as add_app
68
+ from .docker import app as docker_app
69
+ from .docs import app as docs_app
70
+ from .generate import app as generate_app
71
+ from .init import init
72
+ from .migrate import app as migrate_app
73
+ from .scheduler import app as scheduler_app
74
+ from .server import app as server_app
75
+ from .worker import app as worker_app
76
+
77
+ app.command(name="init", help="🎯 初始化项目脚手架")(init)
78
+ app.add_typer(add_app, name="add", help="➕ 添加可选模块")
79
+ app.add_typer(generate_app, name="generate", help="⚡ 代码生成器")
80
+ app.add_typer(server_app, name="server", help="🖥️ 服务器管理")
81
+ app.add_typer(scheduler_app, name="scheduler", help="🕐 独立运行调度器")
82
+ app.add_typer(worker_app, name="worker", help="⚙️ 运行任务队列 Worker")
83
+ app.add_typer(migrate_app, name="migrate", help="🗃️ 数据库迁移")
84
+ app.add_typer(docker_app, name="docker", help="🐳 Docker 配置")
85
+ app.add_typer(docs_app, name="docs", help="📚 生成/更新项目文档")
86
+
87
+ return app
88
+
89
+
90
+ def main() -> None:
91
+ """CLI 入口点。"""
92
+ _get_app()()
93
+
94
+
95
+ # 为了向后兼容,允许 `from .app import app`
96
+ def __getattr__(name: str):
97
+ if name == "app":
98
+ return _get_app()
99
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
100
+
101
+
102
+ __all__ = [
103
+ "app",
104
+ "main",
105
+ ]
@@ -0,0 +1,177 @@
1
+ """项目配置读取工具。
2
+
3
+ 读取和写入 pyproject.toml 中的 [tool.aury] 配置。
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from dataclasses import dataclass
9
+ from pathlib import Path
10
+
11
+
12
+ @dataclass
13
+ class ProjectConfig:
14
+ """Aury 项目配置。"""
15
+
16
+ package: str | None = None # 顶层包名,None 表示无顶层包
17
+ app: str | None = None # 应用入口,形如 "main:app"
18
+
19
+ @property
20
+ def has_package(self) -> bool:
21
+ """是否有顶层包。"""
22
+ return self.package is not None and self.package != ""
23
+
24
+ def get_import_prefix(self) -> str:
25
+ """获取 import 前缀。
26
+
27
+ 有包名返回 "mypackage.",无包名返回 ""。
28
+ """
29
+ return f"{self.package}." if self.has_package else ""
30
+
31
+ def get_package_dir(self, base_path: Path) -> Path:
32
+ """获取包目录路径。
33
+
34
+ 有包名返回 base_path/mypackage,无包名返回 base_path。
35
+ """
36
+ return base_path / self.package if self.has_package else base_path
37
+
38
+
39
+ def get_project_config(base_path: Path | None = None) -> ProjectConfig:
40
+ """读取项目配置。
41
+
42
+ 从 pyproject.toml 的 [tool.aury] 读取配置。
43
+
44
+ Args:
45
+ base_path: 项目根目录,默认为当前目录
46
+
47
+ Returns:
48
+ ProjectConfig 实例
49
+ """
50
+ if base_path is None:
51
+ base_path = Path.cwd()
52
+
53
+ pyproject_path = base_path / "pyproject.toml"
54
+
55
+ if not pyproject_path.exists():
56
+ return ProjectConfig()
57
+
58
+ content = pyproject_path.read_text(encoding="utf-8")
59
+
60
+ # 简单解析 [tool.aury] 部分
61
+ package = _parse_toml_value(content, "tool.aury", "package")
62
+ app = _parse_toml_value(content, "tool.aury", "app")
63
+
64
+ return ProjectConfig(package=package, app=app)
65
+
66
+
67
+ def save_project_config(config: ProjectConfig, base_path: Path | None = None) -> bool:
68
+ """保存项目配置到 pyproject.toml。
69
+
70
+ Args:
71
+ config: 项目配置
72
+ base_path: 项目根目录
73
+
74
+ Returns:
75
+ 是否保存成功
76
+ """
77
+ if base_path is None:
78
+ base_path = Path.cwd()
79
+
80
+ pyproject_path = base_path / "pyproject.toml"
81
+
82
+ if not pyproject_path.exists():
83
+ return False
84
+
85
+ content = pyproject_path.read_text(encoding="utf-8")
86
+
87
+ # 检查是否已有 [tool.aury] 部分
88
+ if "[tool.aury]" in content:
89
+ # 更新现有配置
90
+ lines = content.split("\n")
91
+ new_lines = []
92
+ in_aury_section = False
93
+
94
+ for line in lines:
95
+ if line.strip() == "[tool.aury]":
96
+ in_aury_section = True
97
+ new_lines.append(line)
98
+ # 添加(或更新)配置项
99
+ if config.has_package:
100
+ new_lines.append(f'package = "{config.package}"')
101
+ if config.app:
102
+ new_lines.append(f'app = "{config.app}"')
103
+ continue
104
+
105
+ if in_aury_section:
106
+ # 跳过旧的 package/app 配置
107
+ if line.strip().startswith("package") or line.strip().startswith("app"):
108
+ continue
109
+ # 遇到新的 section 结束
110
+ if line.strip().startswith("["):
111
+ in_aury_section = False
112
+
113
+ new_lines.append(line)
114
+
115
+ content = "\n".join(new_lines)
116
+ else:
117
+ # 添加新的 [tool.aury] 部分
118
+ aury_section = "\n[tool.aury]\n"
119
+ if config.has_package:
120
+ aury_section += f'package = "{config.package}"\n'
121
+ if config.app:
122
+ aury_section += f'app = "{config.app}"\n'
123
+
124
+ content += aury_section
125
+
126
+ pyproject_path.write_text(content, encoding="utf-8")
127
+ return True
128
+
129
+
130
+ def _parse_toml_value(content: str, section: str, key: str) -> str | None:
131
+ """简单解析 TOML 值。
132
+
133
+ 注意:这是一个简单实现,不处理复杂情况。
134
+
135
+ Args:
136
+ content: TOML 文件内容
137
+ section: 节名(如 "tool.aury")
138
+ key: 键名
139
+
140
+ Returns:
141
+ 值字符串,找不到返回 None
142
+ """
143
+ import re
144
+
145
+ # 构建 section 匹配
146
+ section_pattern = r"\[" + re.escape(section) + r"\]"
147
+
148
+ # 查找 section
149
+ section_match = re.search(section_pattern, content)
150
+ if not section_match:
151
+ return None
152
+
153
+ # 从 section 开始查找 key
154
+ section_start = section_match.end()
155
+
156
+ # 查找下一个 section(或文件结尾)
157
+ next_section = re.search(r"\n\[", content[section_start:])
158
+ if next_section:
159
+ section_content = content[section_start : section_start + next_section.start()]
160
+ else:
161
+ section_content = content[section_start:]
162
+
163
+ # 查找 key = value
164
+ key_pattern = rf"^\s*{re.escape(key)}\s*=\s*[\"']?([^\"'\n]+)[\"']?\s*$"
165
+ key_match = re.search(key_pattern, section_content, re.MULTILINE)
166
+
167
+ if key_match:
168
+ return key_match.group(1).strip().strip("\"'")
169
+
170
+ return None
171
+
172
+
173
+ __all__ = [
174
+ "ProjectConfig",
175
+ "get_project_config",
176
+ "save_project_config",
177
+ ]