infomankit 0.3.23__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 (143) hide show
  1. infoman/__init__.py +1 -0
  2. infoman/cli/README.md +378 -0
  3. infoman/cli/__init__.py +7 -0
  4. infoman/cli/commands/__init__.py +3 -0
  5. infoman/cli/commands/init.py +312 -0
  6. infoman/cli/scaffold.py +634 -0
  7. infoman/cli/templates/Makefile.template +132 -0
  8. infoman/cli/templates/app/__init__.py.template +3 -0
  9. infoman/cli/templates/app/app.py.template +4 -0
  10. infoman/cli/templates/app/models_base.py.template +18 -0
  11. infoman/cli/templates/app/models_entity_init.py.template +11 -0
  12. infoman/cli/templates/app/models_schemas_init.py.template +11 -0
  13. infoman/cli/templates/app/repository_init.py.template +11 -0
  14. infoman/cli/templates/app/routers_init.py.template +15 -0
  15. infoman/cli/templates/app/services_init.py.template +11 -0
  16. infoman/cli/templates/app/static_index.html.template +39 -0
  17. infoman/cli/templates/app/static_main.js.template +31 -0
  18. infoman/cli/templates/app/static_style.css.template +111 -0
  19. infoman/cli/templates/app/utils_init.py.template +11 -0
  20. infoman/cli/templates/config/.env.dev.template +43 -0
  21. infoman/cli/templates/config/.env.prod.template +43 -0
  22. infoman/cli/templates/config/README.md.template +28 -0
  23. infoman/cli/templates/docker/.dockerignore.template +60 -0
  24. infoman/cli/templates/docker/Dockerfile.template +47 -0
  25. infoman/cli/templates/docker/README.md.template +240 -0
  26. infoman/cli/templates/docker/docker-compose.yml.template +81 -0
  27. infoman/cli/templates/docker/mysql_custom.cnf.template +42 -0
  28. infoman/cli/templates/docker/mysql_init.sql.template +15 -0
  29. infoman/cli/templates/project/.env.example.template +1 -0
  30. infoman/cli/templates/project/.gitignore.template +60 -0
  31. infoman/cli/templates/project/Makefile.template +38 -0
  32. infoman/cli/templates/project/README.md.template +137 -0
  33. infoman/cli/templates/project/deploy.sh.template +97 -0
  34. infoman/cli/templates/project/main.py.template +10 -0
  35. infoman/cli/templates/project/manage.sh.template +97 -0
  36. infoman/cli/templates/project/pyproject.toml.template +47 -0
  37. infoman/cli/templates/project/service.sh.template +203 -0
  38. infoman/config/__init__.py +25 -0
  39. infoman/config/base.py +67 -0
  40. infoman/config/db_cache.py +237 -0
  41. infoman/config/db_relation.py +181 -0
  42. infoman/config/db_vector.py +39 -0
  43. infoman/config/jwt.py +16 -0
  44. infoman/config/llm.py +16 -0
  45. infoman/config/log.py +627 -0
  46. infoman/config/mq.py +26 -0
  47. infoman/config/settings.py +65 -0
  48. infoman/llm/__init__.py +0 -0
  49. infoman/llm/llm.py +297 -0
  50. infoman/logger/__init__.py +57 -0
  51. infoman/logger/context.py +191 -0
  52. infoman/logger/core.py +358 -0
  53. infoman/logger/filters.py +157 -0
  54. infoman/logger/formatters.py +138 -0
  55. infoman/logger/handlers.py +276 -0
  56. infoman/logger/metrics.py +160 -0
  57. infoman/performance/README.md +583 -0
  58. infoman/performance/__init__.py +19 -0
  59. infoman/performance/cli.py +215 -0
  60. infoman/performance/config.py +166 -0
  61. infoman/performance/reporter.py +519 -0
  62. infoman/performance/runner.py +303 -0
  63. infoman/performance/standards.py +222 -0
  64. infoman/service/__init__.py +8 -0
  65. infoman/service/app.py +67 -0
  66. infoman/service/core/__init__.py +0 -0
  67. infoman/service/core/auth.py +105 -0
  68. infoman/service/core/lifespan.py +132 -0
  69. infoman/service/core/monitor.py +57 -0
  70. infoman/service/core/response.py +37 -0
  71. infoman/service/exception/__init__.py +7 -0
  72. infoman/service/exception/error.py +274 -0
  73. infoman/service/exception/exception.py +25 -0
  74. infoman/service/exception/handler.py +238 -0
  75. infoman/service/infrastructure/__init__.py +8 -0
  76. infoman/service/infrastructure/base.py +212 -0
  77. infoman/service/infrastructure/db_cache/__init__.py +8 -0
  78. infoman/service/infrastructure/db_cache/manager.py +194 -0
  79. infoman/service/infrastructure/db_relation/__init__.py +41 -0
  80. infoman/service/infrastructure/db_relation/manager.py +300 -0
  81. infoman/service/infrastructure/db_relation/manager_pro.py +408 -0
  82. infoman/service/infrastructure/db_relation/mysql.py +52 -0
  83. infoman/service/infrastructure/db_relation/pgsql.py +54 -0
  84. infoman/service/infrastructure/db_relation/sqllite.py +25 -0
  85. infoman/service/infrastructure/db_vector/__init__.py +40 -0
  86. infoman/service/infrastructure/db_vector/manager.py +201 -0
  87. infoman/service/infrastructure/db_vector/qdrant.py +322 -0
  88. infoman/service/infrastructure/mq/__init__.py +15 -0
  89. infoman/service/infrastructure/mq/manager.py +178 -0
  90. infoman/service/infrastructure/mq/nats/__init__.py +0 -0
  91. infoman/service/infrastructure/mq/nats/nats_client.py +57 -0
  92. infoman/service/infrastructure/mq/nats/nats_event_router.py +25 -0
  93. infoman/service/launch.py +284 -0
  94. infoman/service/middleware/__init__.py +7 -0
  95. infoman/service/middleware/base.py +41 -0
  96. infoman/service/middleware/logging.py +51 -0
  97. infoman/service/middleware/rate_limit.py +301 -0
  98. infoman/service/middleware/request_id.py +21 -0
  99. infoman/service/middleware/white_list.py +24 -0
  100. infoman/service/models/__init__.py +8 -0
  101. infoman/service/models/base.py +441 -0
  102. infoman/service/models/type/embed.py +70 -0
  103. infoman/service/routers/__init__.py +18 -0
  104. infoman/service/routers/health_router.py +311 -0
  105. infoman/service/routers/monitor_router.py +44 -0
  106. infoman/service/utils/__init__.py +8 -0
  107. infoman/service/utils/cache/__init__.py +0 -0
  108. infoman/service/utils/cache/cache.py +192 -0
  109. infoman/service/utils/module_loader.py +10 -0
  110. infoman/service/utils/parse.py +10 -0
  111. infoman/service/utils/resolver/__init__.py +8 -0
  112. infoman/service/utils/resolver/base.py +47 -0
  113. infoman/service/utils/resolver/resp.py +102 -0
  114. infoman/service/vector/__init__.py +20 -0
  115. infoman/service/vector/base.py +56 -0
  116. infoman/service/vector/qdrant.py +125 -0
  117. infoman/service/vector/service.py +67 -0
  118. infoman/utils/__init__.py +2 -0
  119. infoman/utils/decorators/__init__.py +8 -0
  120. infoman/utils/decorators/cache.py +137 -0
  121. infoman/utils/decorators/retry.py +99 -0
  122. infoman/utils/decorators/safe_execute.py +99 -0
  123. infoman/utils/decorators/timing.py +99 -0
  124. infoman/utils/encryption/__init__.py +8 -0
  125. infoman/utils/encryption/aes.py +66 -0
  126. infoman/utils/encryption/ecc.py +108 -0
  127. infoman/utils/encryption/rsa.py +112 -0
  128. infoman/utils/file/__init__.py +0 -0
  129. infoman/utils/file/handler.py +22 -0
  130. infoman/utils/hash/__init__.py +0 -0
  131. infoman/utils/hash/hash.py +61 -0
  132. infoman/utils/http/__init__.py +8 -0
  133. infoman/utils/http/client.py +62 -0
  134. infoman/utils/http/info.py +94 -0
  135. infoman/utils/http/result.py +19 -0
  136. infoman/utils/notification/__init__.py +8 -0
  137. infoman/utils/notification/feishu.py +35 -0
  138. infoman/utils/text/__init__.py +8 -0
  139. infoman/utils/text/extractor.py +111 -0
  140. infomankit-0.3.23.dist-info/METADATA +632 -0
  141. infomankit-0.3.23.dist-info/RECORD +143 -0
  142. infomankit-0.3.23.dist-info/WHEEL +4 -0
  143. infomankit-0.3.23.dist-info/entry_points.txt +5 -0
@@ -0,0 +1,132 @@
1
+ # service/core/lifespan.py
2
+ """
3
+ 应用生命周期管理(精简版)
4
+
5
+ 职责:
6
+ - 协调各个服务的启动和关闭
7
+ - 不包含具体的连接逻辑
8
+ - 支持可选依赖的优雅降级
9
+ """
10
+
11
+ from contextlib import asynccontextmanager
12
+ from fastapi import FastAPI
13
+ from loguru import logger
14
+
15
+ from infoman.config import settings
16
+
17
+ # ========== 数据库(必需) ==========
18
+ if settings.USE_PRO_ORM:
19
+ from infoman.service.infrastructure.db_relation.manager_pro import db_manager
20
+ _DB_MANAGER_TYPE = "pro"
21
+ else:
22
+ from infoman.service.infrastructure.db_relation.manager import db_manager
23
+ _DB_MANAGER_TYPE = "basic"
24
+
25
+ # ========== Redis(可选) ==========
26
+ try:
27
+ from infoman.service.infrastructure.db_cache.manager import RedisManager
28
+ REDIS_AVAILABLE = True
29
+ except ImportError:
30
+ logger.warning("⚠️ Redis 依赖未安装,缓存功能将不可用 (需要: redis, fastapi-cache2)")
31
+ RedisManager = None
32
+ REDIS_AVAILABLE = False
33
+
34
+ # ========== 向量数据库(可选) ==========
35
+ try:
36
+ from infoman.service.infrastructure.db_vector.manager import VectorDBManager
37
+ VECTOR_AVAILABLE = True
38
+ except ImportError:
39
+ logger.warning("⚠️ 向量数据库依赖未安装,向量搜索功能将不可用 (需要: qdrant-client)")
40
+ VectorDBManager = None
41
+ VECTOR_AVAILABLE = False
42
+
43
+ # ========== 消息队列(可选) ==========
44
+ try:
45
+ from infoman.service.infrastructure.mq import NATSManager
46
+ MQ_AVAILABLE = True
47
+ except ImportError:
48
+ logger.warning("⚠️ 消息队列依赖未安装,NATS 功能将不可用 (需要: nats-py)")
49
+ NATSManager = None
50
+ MQ_AVAILABLE = False
51
+
52
+
53
+ @asynccontextmanager
54
+ async def lifespan(app: FastAPI):
55
+ """应用生命周期管理(支持可选依赖)"""
56
+
57
+ # ========== 启动 ==========
58
+ logger.info(f"🚀 应用启动中 [{settings.APP_NAME} v{settings.APP_VERSION}]")
59
+ logger.info(f" 环境: {settings.ENV}")
60
+ logger.info(f" 数据库管理器: {_DB_MANAGER_TYPE}")
61
+ logger.info(f" 可选功能: Redis={REDIS_AVAILABLE}, Vector={VECTOR_AVAILABLE}, MQ={MQ_AVAILABLE}")
62
+
63
+ # 初始化管理器(仅限已安装的)
64
+ managers = {}
65
+
66
+ # 数据库(必需)
67
+ managers['db'] = db_manager
68
+ app.state.db_manager = db_manager
69
+
70
+ # Redis(可选)
71
+ if REDIS_AVAILABLE:
72
+ redis_manager = RedisManager()
73
+ managers['redis'] = redis_manager
74
+ app.state.redis_manager = redis_manager
75
+
76
+ # 向量数据库(可选)
77
+ if VECTOR_AVAILABLE:
78
+ vector_manager = VectorDBManager()
79
+ managers['vector'] = vector_manager
80
+ app.state.vector_manager = vector_manager
81
+
82
+ # 消息队列(可选)
83
+ if MQ_AVAILABLE:
84
+ nats_manager = NATSManager()
85
+ managers['mq'] = nats_manager
86
+ app.state.nats_manager = nats_manager
87
+
88
+ try:
89
+ # 1. 数据库
90
+ await db_manager.startup(app)
91
+
92
+ # 2. Redis(如果可用)
93
+ if 'redis' in managers:
94
+ await managers['redis'].startup(app)
95
+
96
+ # 3. 向量数据库(如果可用)
97
+ if 'vector' in managers:
98
+ await managers['vector'].startup(app)
99
+
100
+ # 4. 消息队列(如果可用)
101
+ if 'mq' in managers:
102
+ await managers['mq'].startup(app)
103
+
104
+ logger.success("✅ 所有服务启动完成")
105
+
106
+ except Exception as e:
107
+ logger.error(f"❌ 服务启动失败: {e}")
108
+ raise
109
+
110
+ # ========== 运行 ==========
111
+ yield
112
+
113
+ # ========== 关闭 ==========
114
+ logger.info("⏹️ 应用关闭中...")
115
+
116
+ try:
117
+ # 按相反顺序关闭(仅关闭已启动的)
118
+ if 'mq' in managers:
119
+ await managers['mq'].shutdown()
120
+
121
+ if 'vector' in managers:
122
+ await managers['vector'].shutdown()
123
+
124
+ if 'redis' in managers:
125
+ await managers['redis'].shutdown()
126
+
127
+ await db_manager.shutdown()
128
+
129
+ logger.success("✅ 所有服务已关闭")
130
+
131
+ except Exception as e:
132
+ logger.error(f"❌ 服务关闭失败: {e}")
@@ -0,0 +1,57 @@
1
+ from prometheus_fastapi_instrumentator import Instrumentator, metrics
2
+ from prometheus_client import Counter, Histogram, Gauge
3
+
4
+ # ===== 1. HTTP 指标(自动收集)=====
5
+ instrumentator = Instrumentator(
6
+ should_group_status_codes=True,
7
+ should_ignore_untemplated=True,
8
+ should_respect_env_var=True,
9
+ should_instrument_requests_inprogress=True,
10
+ excluded_handlers=["/health", "/metrics", "/doc", "/redoc", "/openapi.json"],
11
+ )
12
+
13
+ instrumentator.add(metrics.default())
14
+ instrumentator.add(metrics.request_size())
15
+ instrumentator.add(metrics.response_size())
16
+
17
+ # ===== 2. 业务指标(手动收集)=====
18
+
19
+ # 用户操作
20
+ user_operations = Counter(
21
+ "user_operations_total", "Total user operations", ["operation_type", "status"]
22
+ )
23
+
24
+ # 数据库查询
25
+ db_query_duration = Histogram(
26
+ "db_query_duration_seconds",
27
+ "Database query duration",
28
+ ["query_type"],
29
+ buckets=[0.001, 0.01, 0.05, 0.1, 0.5, 1.0, 2.5, 5.0],
30
+ )
31
+
32
+ # 缓存
33
+ cache_hits = Counter("cache_hits_total", "Cache hits", ["cache_type"])
34
+ cache_misses = Counter("cache_misses_total", "Cache misses", ["cache_type"])
35
+
36
+ # 连接数
37
+ active_db_connections = Gauge("active_db_connections", "Active database connections")
38
+ active_redis_connections = Gauge("active_redis_connections", "Active Redis connections")
39
+
40
+ # 队列
41
+ task_queue_length = Gauge("task_queue_length", "Task queue length")
42
+
43
+ # 在线用户
44
+ online_users = Gauge("online_users", "Online users count")
45
+
46
+ # ===== 3. 导出所有指标(方便使用)=====
47
+ __all__ = [
48
+ "instrumentator",
49
+ "user_operations",
50
+ "db_query_duration",
51
+ "cache_hits",
52
+ "cache_misses",
53
+ "active_db_connections",
54
+ "active_redis_connections",
55
+ "task_queue_length",
56
+ "online_users",
57
+ ]
@@ -0,0 +1,37 @@
1
+ # -*- coding:utf-8 -*-
2
+ """
3
+ # Time :2023/12/8 18:23
4
+ # Author :Maxwell
5
+ # version :python 3.9
6
+ # Description:
7
+ """
8
+ from infoman.service.exception.exception import AppError
9
+ from infoman.config import settings as config
10
+ from fastapi.responses import ORJSONResponse
11
+ import orjson
12
+
13
+
14
+ class ProRJSONResponse(ORJSONResponse):
15
+ def render(self, content) -> bytes:
16
+ return orjson.dumps(
17
+ content,
18
+ option=(
19
+ orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_UTC_Z
20
+ ),
21
+ )
22
+
23
+
24
+ def response(code, msg, data=None):
25
+ result = {"code": code, "message": msg, "data": data}
26
+ return result
27
+
28
+
29
+ def success(data=None, msg=""):
30
+ return response(200, msg, data)
31
+
32
+
33
+ def failed(error: AppError):
34
+ msg = error.message_en
35
+ if not config.DEFAULT_LANGUAGE_IS_EN:
36
+ msg = error.message
37
+ return response(code=error.code, msg=msg)
@@ -0,0 +1,7 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+ """
4
+ # Time :2023/12/9 13:48
5
+ # Author :Maxwell
6
+ # Description:
7
+ """
@@ -0,0 +1,274 @@
1
+ from enum import Enum
2
+ from dataclasses import dataclass
3
+ from typing import Optional, Dict, Any
4
+ from http import HTTPStatus
5
+
6
+
7
+ @dataclass
8
+ class ErrorProperties:
9
+ code: int
10
+ message: str
11
+ message_en: str
12
+ status_code: int = HTTPStatus.INTERNAL_SERVER_ERROR
13
+ details: Optional[Dict[str, Any]] = None
14
+
15
+
16
+ class AppError(Enum):
17
+
18
+ @property
19
+ def code(self) -> int:
20
+ return self.value.code
21
+
22
+ @property
23
+ def message(self) -> str:
24
+ return self.value.message
25
+
26
+ @property
27
+ def message_en(self) -> str:
28
+ return self.value.message_en
29
+
30
+ @property
31
+ def status_code(self) -> int:
32
+ return self.value.status_code
33
+
34
+ @property
35
+ def details(self) -> Optional[Dict[str, Any]]:
36
+ return self.value.details
37
+
38
+ def with_details(self, details: Dict[str, Any]) -> ErrorProperties:
39
+ return ErrorProperties(
40
+ code=self.code,
41
+ message=self.message,
42
+ message_en=self.message_en,
43
+ status_code=self.status_code,
44
+ details=details,
45
+ )
46
+
47
+
48
+ class AppSystemError(AppError):
49
+ UNKNOWN_ERROR = ErrorProperties(
50
+ 100000, "系统未知异常", "Unknown system error", HTTPStatus.INTERNAL_SERVER_ERROR
51
+ )
52
+
53
+ SYSTEM_ERROR = ErrorProperties(
54
+ 100001,
55
+ "系统内部错误",
56
+ "Internal server error",
57
+ HTTPStatus.INTERNAL_SERVER_ERROR,
58
+ )
59
+
60
+ TIMEOUT_ERROR = ErrorProperties(
61
+ 100002, "系统处理超时", "System processing timeout", HTTPStatus.GATEWAY_TIMEOUT
62
+ )
63
+
64
+ SERVICE_UNAVAILABLE = ErrorProperties(
65
+ 100003,
66
+ "服务暂时不可用",
67
+ "Service temporarily unavailable",
68
+ HTTPStatus.SERVICE_UNAVAILABLE,
69
+ )
70
+
71
+ RESOURCE_EXHAUSTED = ErrorProperties(
72
+ 100004,
73
+ "系统资源不足",
74
+ "System resources exhausted",
75
+ HTTPStatus.TOO_MANY_REQUESTS,
76
+ )
77
+
78
+ CONFIGURATION_ERROR = ErrorProperties(
79
+ 100005,
80
+ "系统配置错误",
81
+ "System configuration error",
82
+ HTTPStatus.INTERNAL_SERVER_ERROR,
83
+ )
84
+
85
+
86
+ class RequestError(AppError):
87
+ VALIDATION_ERROR = ErrorProperties(
88
+ 200000,
89
+ "请求数据验证失败",
90
+ "Request data validation failed",
91
+ HTTPStatus.BAD_REQUEST,
92
+ )
93
+
94
+ INVALID_PARAMETER = ErrorProperties(
95
+ 200001, "无效的请求参数", "Invalid request parameter", HTTPStatus.BAD_REQUEST
96
+ )
97
+
98
+ MISSING_PARAMETER = ErrorProperties(
99
+ 200002, "缺少必要参数", "Missing required parameter", HTTPStatus.BAD_REQUEST
100
+ )
101
+
102
+ INVALID_FORMAT = ErrorProperties(
103
+ 200003, "请求格式错误", "Invalid request format", HTTPStatus.BAD_REQUEST
104
+ )
105
+
106
+ REQUEST_TOO_LARGE = ErrorProperties(
107
+ 200004,
108
+ "请求体过大",
109
+ "Request body too large",
110
+ HTTPStatus.REQUEST_ENTITY_TOO_LARGE,
111
+ )
112
+
113
+ RATE_LIMITED = ErrorProperties(
114
+ 200005, "请求频率超限", "Request rate limited", HTTPStatus.TOO_MANY_REQUESTS
115
+ )
116
+
117
+ UNSUPPORTED_MEDIA_TYPE = ErrorProperties(
118
+ 200006,
119
+ "不支持的媒体类型",
120
+ "Unsupported media type",
121
+ HTTPStatus.UNSUPPORTED_MEDIA_TYPE,
122
+ )
123
+
124
+
125
+ class DatabaseError(AppError):
126
+ VALIDATION_ERROR = ErrorProperties(
127
+ 300000, "数据验证失败", "Data validation failed", HTTPStatus.BAD_REQUEST
128
+ )
129
+
130
+ INTEGRITY_ERROR = ErrorProperties(
131
+ 300001,
132
+ "数据完整性约束冲突",
133
+ "Data integrity constraint violation",
134
+ HTTPStatus.CONFLICT,
135
+ )
136
+
137
+ RECORD_NOT_FOUND = ErrorProperties(
138
+ 300002, "记录不存在", "Record not found", HTTPStatus.NOT_FOUND
139
+ )
140
+
141
+ DUPLICATE_ENTRY = ErrorProperties(
142
+ 300003, "记录已存在", "Duplicate record", HTTPStatus.CONFLICT
143
+ )
144
+
145
+ OPERATIONAL_ERROR = ErrorProperties(
146
+ 300004,
147
+ "数据库操作错误",
148
+ "Database operational error",
149
+ HTTPStatus.INTERNAL_SERVER_ERROR,
150
+ )
151
+
152
+ CONNECTION_ERROR = ErrorProperties(
153
+ 300005,
154
+ "数据库连接错误",
155
+ "Database connection error",
156
+ HTTPStatus.SERVICE_UNAVAILABLE,
157
+ )
158
+
159
+ TRANSACTION_ERROR = ErrorProperties(
160
+ 300006,
161
+ "事务处理错误",
162
+ "Transaction processing error",
163
+ HTTPStatus.INTERNAL_SERVER_ERROR,
164
+ )
165
+
166
+ QUERY_TIMEOUT = ErrorProperties(
167
+ 300007, "查询超时", "Query timeout", HTTPStatus.GATEWAY_TIMEOUT
168
+ )
169
+
170
+
171
+ class BusinessError(AppError):
172
+
173
+ INVALID_OPERATION = ErrorProperties(
174
+ 400000, "无效的操作", "Invalid operation", HTTPStatus.BAD_REQUEST
175
+ )
176
+
177
+ STATE_CONFLICT = ErrorProperties(
178
+ 400001, "状态冲突", "State conflict", HTTPStatus.CONFLICT
179
+ )
180
+
181
+ RESOURCE_LOCKED = ErrorProperties(
182
+ 400002, "资源已锁定", "Resource locked", HTTPStatus.LOCKED
183
+ )
184
+
185
+ QUOTA_EXCEEDED = ErrorProperties(
186
+ 400003, "配额超限", "Quota exceeded", HTTPStatus.FORBIDDEN
187
+ )
188
+
189
+ PAYMENT_REQUIRED = ErrorProperties(
190
+ 400004, "需要付款", "Payment required", HTTPStatus.PAYMENT_REQUIRED
191
+ )
192
+
193
+ BUSINESS_RULE_VIOLATION = ErrorProperties(
194
+ 400005, "违反业务规则", "Business rule violation", HTTPStatus.BAD_REQUEST
195
+ )
196
+
197
+
198
+ class SecurityError(AppError):
199
+ """
200
+ 安全相关错误
201
+
202
+ 包括认证、授权、访问控制等错误
203
+ 错误代码范围:500000-599999
204
+ """
205
+
206
+ UNAUTHORIZED = ErrorProperties(
207
+ 500000, "未授权访问", "Unauthorized access", HTTPStatus.UNAUTHORIZED
208
+ )
209
+
210
+ FORBIDDEN = ErrorProperties(
211
+ 500001, "禁止访问", "Access forbidden", HTTPStatus.FORBIDDEN
212
+ )
213
+
214
+ INVALID_CREDENTIALS = ErrorProperties(
215
+ 500002, "无效的凭证", "Invalid credentials", HTTPStatus.UNAUTHORIZED
216
+ )
217
+
218
+ TOKEN_EXPIRED = ErrorProperties(
219
+ 500003, "令牌已过期", "Token expired", HTTPStatus.UNAUTHORIZED
220
+ )
221
+
222
+ INVALID_TOKEN = ErrorProperties(
223
+ 500004, "无效的令牌", "Invalid token", HTTPStatus.UNAUTHORIZED
224
+ )
225
+
226
+ PERMISSION_DENIED = ErrorProperties(
227
+ 500005, "权限不足", "Permission denied", HTTPStatus.FORBIDDEN
228
+ )
229
+
230
+ ACCOUNT_LOCKED = ErrorProperties(
231
+ 500006, "账户已锁定", "Account locked", HTTPStatus.FORBIDDEN
232
+ )
233
+
234
+ IP_RESTRICTED = ErrorProperties(
235
+ 500007, "IP地址受限", "IP address restricted", HTTPStatus.FORBIDDEN
236
+ )
237
+
238
+
239
+ class ExternalServiceError(AppError):
240
+ """
241
+ 外部服务错误
242
+
243
+ 包括第三方API、外部依赖服务等错误
244
+ 错误代码范围:600000-699999
245
+ """
246
+
247
+ SERVICE_UNAVAILABLE = ErrorProperties(
248
+ 600000, "外部服务不可用", "External service unavailable", HTTPStatus.BAD_GATEWAY
249
+ )
250
+
251
+ REQUEST_FAILED = ErrorProperties(
252
+ 600001,
253
+ "外部服务请求失败",
254
+ "External service request failed",
255
+ HTTPStatus.BAD_GATEWAY,
256
+ )
257
+
258
+ RESPONSE_ERROR = ErrorProperties(
259
+ 600002,
260
+ "外部服务响应错误",
261
+ "External service response error",
262
+ HTTPStatus.BAD_GATEWAY,
263
+ )
264
+
265
+ TIMEOUT = ErrorProperties(
266
+ 600003, "外部服务超时", "External service timeout", HTTPStatus.GATEWAY_TIMEOUT
267
+ )
268
+
269
+ INVALID_RESPONSE = ErrorProperties(
270
+ 600004,
271
+ "外部服务返回无效数据",
272
+ "Invalid data returned from external service",
273
+ HTTPStatus.BAD_GATEWAY,
274
+ )
@@ -0,0 +1,25 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+
4
+ """
5
+ # Time :2025/6/21 21:51
6
+ # Author :Maxwell
7
+ # Description:
8
+ """
9
+ from infoman.service.exception.error import AppError
10
+ from infoman.config.settings import settings
11
+
12
+
13
+ class AppException(Exception):
14
+
15
+ def __init__(self, error: AppError):
16
+ self.error_code = error.code
17
+ self.message = error.message_en
18
+ if not settings.DEFAULT_LANGUAGE_IS_EN:
19
+ self.message = error.message
20
+ super().__init__(error.message)
21
+
22
+ def with_content(self, place_holder, content):
23
+ if self.message:
24
+ self.message = self.message.replace(place_holder, content)
25
+ return self