ErisPulse 1.1.13__py3-none-any.whl → 1.1.14__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.
ErisPulse/raiserr.py CHANGED
@@ -1,3 +1,161 @@
1
+ """
2
+ # 错误管理系统
3
+
4
+ 提供错误类型注册、抛出和管理功能,集成全局异常处理。支持自定义错误类型、错误链追踪和全局异常捕获。
5
+
6
+ ## 核心功能
7
+ 1. 错误类型注册和管理
8
+ 2. 动态错误抛出
9
+ 3. 全局异常处理
10
+ 4. 错误信息追踪
11
+ 5. 异步错误处理
12
+
13
+ ## API 文档
14
+
15
+ ### 错误注册
16
+ #### register(name: str, doc: str = "", base: type = Exception) -> type
17
+ 注册新的错误类型。
18
+ - 参数:
19
+ - name: 错误类型名称
20
+ - doc: 错误描述文档
21
+ - base: 基础异常类,默认为Exception
22
+ - 返回:
23
+ - type: 注册的错误类型类
24
+ - 示例:
25
+ ```python
26
+ # 注册一个简单错误
27
+ sdk.raiserr.register("SimpleError", "简单的错误类型")
28
+
29
+ # 注册带有自定义基类的错误
30
+ class CustomBase(Exception):
31
+ pass
32
+ sdk.raiserr.register("AdvancedError", "高级错误", CustomBase)
33
+ ```
34
+
35
+ #### info(name: str = None) -> dict | None
36
+ 获取错误类型信息。
37
+ - 参数:
38
+ - name: 错误类型名称,如果为None则返回所有错误类型信息
39
+ - 返回:
40
+ - dict: 包含错误类型信息的字典,包括类型名、文档和类引用
41
+ - None: 如果指定的错误类型不存在
42
+ - 示例:
43
+ ```python
44
+ # 获取特定错误信息
45
+ error_info = sdk.raiserr.info("SimpleError")
46
+ print(f"错误类型: {error_info['type']}")
47
+ print(f"错误描述: {error_info['doc']}")
48
+
49
+ # 获取所有注册的错误信息
50
+ all_errors = sdk.raiserr.info()
51
+ for name, info in all_errors.items():
52
+ print(f"{name}: {info['doc']}")
53
+ ```
54
+
55
+ ### 错误抛出
56
+ #### ErrorType(msg: str, exit: bool = False)
57
+ 动态生成的错误抛出函数。
58
+ - 参数:
59
+ - msg: 错误消息
60
+ - exit: 是否在抛出错误后退出程序
61
+ - 示例:
62
+ ```python
63
+ # 抛出不退出的错误
64
+ sdk.raiserr.SimpleError("操作失败")
65
+
66
+ # 抛出导致程序退出的错误
67
+ sdk.raiserr.CriticalError("致命错误", exit=True)
68
+
69
+ # 带有异常捕获的使用方式
70
+ try:
71
+ sdk.raiserr.ValidationError("数据验证失败")
72
+ except Exception as e:
73
+ print(f"捕获到错误: {e}")
74
+ ```
75
+
76
+ ### 全局异常处理
77
+ #### global_exception_handler(exc_type: type, exc_value: Exception, exc_traceback: traceback)
78
+ 全局同步异常处理器。
79
+ - 参数:
80
+ - exc_type: 异常类型
81
+ - exc_value: 异常值
82
+ - exc_traceback: 异常追踪信息
83
+ - 示例:
84
+ ```python
85
+ # 系统会自动捕获未处理的异常
86
+ def risky_operation():
87
+ raise Exception("未处理的异常")
88
+
89
+ # 异常会被global_exception_handler捕获并处理
90
+ risky_operation()
91
+ ```
92
+
93
+ #### async_exception_handler(loop: asyncio.AbstractEventLoop, context: dict)
94
+ 全局异步异常处理器。
95
+ - 参数:
96
+ - loop: 事件循环实例
97
+ - context: 异常上下文信息
98
+ - 示例:
99
+ ```python
100
+ async def async_operation():
101
+ raise Exception("异步操作错误")
102
+
103
+ # 异常会被async_exception_handler捕获并处理
104
+ asyncio.create_task(async_operation())
105
+ ```
106
+
107
+ ## 最佳实践
108
+ 1. 错误类型注册
109
+ ```python
110
+ # 为特定功能模块注册错误类型
111
+ sdk.raiserr.register("DatabaseError", "数据库操作错误")
112
+ sdk.raiserr.register("NetworkError", "网络连接错误")
113
+ sdk.raiserr.register("ValidationError", "数据验证错误")
114
+
115
+ # 使用继承关系组织错误类型
116
+ class ModuleError(Exception):
117
+ pass
118
+ sdk.raiserr.register("ConfigError", "配置错误", ModuleError)
119
+ sdk.raiserr.register("PluginError", "插件错误", ModuleError)
120
+ ```
121
+
122
+ 2. 错误处理流程
123
+ ```python
124
+ def process_data(data):
125
+ try:
126
+ if not data:
127
+ sdk.raiserr.ValidationError("数据不能为空")
128
+ if not isinstance(data, dict):
129
+ sdk.raiserr.ValidationError("数据必须是字典类型")
130
+
131
+ # 处理数据...
132
+
133
+ except Exception as e:
134
+ # 错误会被自动记录并处理
135
+ sdk.raiserr.ProcessingError(f"数据处理失败: {str(e)}")
136
+ ```
137
+
138
+ 3. 异步环境使用
139
+ ```python
140
+ async def async_task():
141
+ try:
142
+ result = await some_async_operation()
143
+ if not result.success:
144
+ sdk.raiserr.AsyncOperationError("异步操作失败")
145
+ except Exception as e:
146
+ # 异步错误会被async_exception_handler捕获
147
+ raise
148
+ ```
149
+
150
+ ## 注意事项
151
+ 1. 错误类型命名应具有描述性,便于理解错误来源
152
+ 2. 错误消息应包含足够的上下文信息,便于调试
153
+ 3. 适当使用exit参数,只在致命错误时设置为True
154
+ 4. 避免在全局异常处理器中执行耗时操作
155
+ 5. 确保异步代码中的错误能够被正确捕获和处理
156
+
157
+ """
158
+
1
159
  import sys
2
160
  import traceback
3
161
  import asyncio
@@ -71,4 +229,4 @@ def async_exception_handler(loop, context):
71
229
  )
72
230
  else:
73
231
  logger.warning(f"异步任务警告: {message}")
74
- asyncio.get_event_loop().set_exception_handler(async_exception_handler)
232
+ asyncio.get_event_loop().set_exception_handler(async_exception_handler)
ErisPulse/util.py CHANGED
@@ -1,7 +1,379 @@
1
+ """
2
+ # 工具函数集合
3
+
4
+ 提供各种实用工具函数和装饰器,简化开发流程。包括依赖关系处理、性能优化、异步执行和错误重试等功能。
5
+
6
+ ## 核心功能
7
+ 1. 依赖关系管理
8
+ 2. 函数结果缓存
9
+ 3. 异步执行支持
10
+ 4. 自动重试机制
11
+ 5. 可视化工具
12
+ 6. 版本管理和比较
13
+
14
+
15
+ ## API 文档
16
+
17
+ ### 依赖关系处理
18
+ #### topological_sort(elements: list, dependencies: dict, error: callable) -> list
19
+ 对元素进行拓扑排序,解析依赖关系。
20
+ - 参数:
21
+ - elements: 需要排序的元素列表
22
+ - dependencies: 依赖关系字典,键为元素,值为该元素依赖的元素列表
23
+ - error: 发生循环依赖时调用的错误处理函数
24
+ - 返回:
25
+ - list: 排序后的元素列表
26
+ - 异常:
27
+ - 当存在循环依赖时,调用error函数
28
+ - 示例:
29
+ ```python
30
+ # 基本使用
31
+ modules = ["ModuleA", "ModuleB", "ModuleC"]
32
+ dependencies = {
33
+ "ModuleB": ["ModuleA"],
34
+ "ModuleC": ["ModuleB"]
35
+ }
36
+ sorted_modules = sdk.util.topological_sort(modules, dependencies, sdk.raiserr.CycleDependencyError)
37
+
38
+ # 复杂依赖处理
39
+ modules = ["Database", "Cache", "API", "UI"]
40
+ dependencies = {
41
+ "Cache": ["Database"],
42
+ "API": ["Database", "Cache"],
43
+ "UI": ["API"]
44
+ }
45
+ try:
46
+ sorted_modules = sdk.util.topological_sort(
47
+ modules,
48
+ dependencies,
49
+ sdk.raiserr.CycleDependencyError
50
+ )
51
+ print("加载顺序:", sorted_modules)
52
+ except Exception as e:
53
+ print(f"依赖解析失败: {e}")
54
+ ```
55
+
56
+ #### show_topology() -> str
57
+ 可视化显示当前模块的依赖关系。
58
+ - 参数: 无
59
+ - 返回:
60
+ - str: 格式化的依赖关系树文本
61
+ - 示例:
62
+ ```python
63
+ # 显示所有模块依赖
64
+ topology = sdk.util.show_topology()
65
+ print(topology)
66
+
67
+ # 在日志中记录依赖关系
68
+ sdk.logger.info("模块依赖关系:\n" + sdk.util.show_topology())
69
+ ```
70
+
71
+ ### 性能优化装饰器
72
+ #### @cache
73
+ 缓存函数调用结果的装饰器。
74
+ - 参数: 无
75
+ - 返回:
76
+ - function: 被装饰的函数
77
+ - 示例:
78
+ ```python
79
+ # 缓存计算密集型函数结果
80
+ @sdk.util.cache
81
+ def calculate_complex_data(param1: int, param2: str) -> dict:
82
+ # 复杂计算...
83
+ return result
84
+
85
+ # 缓存配置读取
86
+ @sdk.util.cache
87
+ def get_config(config_name: str) -> dict:
88
+ return load_config_from_file(config_name)
89
+
90
+ # 带有可变参数的缓存
91
+ @sdk.util.cache
92
+ def process_data(*args, **kwargs) -> Any:
93
+ return complex_processing(args, kwargs)
94
+ ```
95
+
96
+ ### 异步执行工具
97
+ #### @run_in_executor
98
+ 将同步函数转换为异步执行的装饰器。
99
+ - 参数: 无
100
+ - 返回:
101
+ - function: 异步包装的函数
102
+ - 示例:
103
+ ```python
104
+ # 包装同步IO操作
105
+ @sdk.util.run_in_executor
106
+ def read_large_file(file_path: str) -> str:
107
+ with open(file_path, 'r') as f:
108
+ return f.read()
109
+
110
+ # 包装CPU密集型操作
111
+ @sdk.util.run_in_executor
112
+ def process_image(image_data: bytes) -> bytes:
113
+ # 图像处理...
114
+ return processed_data
115
+
116
+ # 在异步环境中使用
117
+ async def main():
118
+ # 这些操作会在线程池中执行,不会阻塞事件循环
119
+ file_content = await read_large_file("large_file.txt")
120
+ processed_image = await process_image(image_data)
121
+ ```
122
+
123
+ #### ExecAsync(async_func: Callable, *args, **kwargs) -> Any
124
+ 在当前线程中执行异步函数。
125
+ - 参数:
126
+ - async_func: 要执行的异步函数
127
+ - *args: 传递给异步函数的位置参数
128
+ - **kwargs: 传递给异步函数的关键字参数
129
+ - 返回:
130
+ - Any: 异步函数的执行结果
131
+ - 示例:
132
+ ```python
133
+ # 在同步环境中执行异步函数
134
+ async def fetch_data(url: str) -> dict:
135
+ async with aiohttp.ClientSession() as session:
136
+ async with session.get(url) as response:
137
+ return await response.json()
138
+
139
+ # 同步环境中调用
140
+ result = sdk.util.ExecAsync(fetch_data, "https://api.example.com/data")
141
+
142
+ # 批量异步操作
143
+ async def process_multiple(items: list) -> list:
144
+ results = []
145
+ for item in items:
146
+ result = await process_item(item)
147
+ results.append(result)
148
+ return results
149
+
150
+ # 在同步代码中执行
151
+ results = sdk.util.ExecAsync(process_multiple, items_list)
152
+ ```
153
+
154
+ ### 错误重试机制
155
+ #### @retry(max_attempts: int = 3, delay: int = 1)
156
+ 为不稳定的操作添加自动重试机制的装饰器。
157
+ - 参数:
158
+ - max_attempts: 最大重试次数,默认3次
159
+ - delay: 重试间隔时间(秒),默认1秒
160
+ - 返回:
161
+ - function: 包装了重试逻辑的函数
162
+ - 示例:
163
+ ```python
164
+ # 基本重试
165
+ @sdk.util.retry()
166
+ def unstable_network_call() -> dict:
167
+ return requests.get("https://api.example.com/data").json()
168
+
169
+ # 自定义重试参数
170
+ @sdk.util.retry(max_attempts=5, delay=2)
171
+ def connect_database() -> Connection:
172
+ return create_database_connection()
173
+
174
+ # 带有条件的重试
175
+ @sdk.util.retry(max_attempts=3)
176
+ def process_with_retry(data: dict) -> bool:
177
+ if not validate_data(data):
178
+ raise ValueError("Invalid data")
179
+ return process_data(data)
180
+ ```
181
+
182
+ ### 版本管理工具
183
+ #### parse_dependency_with_version(dependency_str: str) -> tuple
184
+ 解析带有版本要求的依赖字符串。
185
+ - 参数:
186
+ - dependency_str: 依赖字符串,如 "ModuleA==1.0.0", "ModuleB>=2.0.0"
187
+ - 返回:
188
+ - tuple: (模块名, 操作符, 版本号) 或 (模块名, None, None)
189
+ - 示例:
190
+ ```python
191
+ # 解析带版本要求的依赖
192
+ module_name, operator, version = sdk.util.parse_dependency_with_version("ModuleA==1.0.0")
193
+ print(f"模块: {module_name}, 操作符: {operator}, 版本: {version}")
194
+ # 输出: 模块: ModuleA, 操作符: ==, 版本: 1.0.0
195
+
196
+ # 解析不带版本要求的依赖
197
+ module_name, operator, version = sdk.util.parse_dependency_with_version("ModuleB")
198
+ print(f"模块: {module_name}, 操作符: {operator}, 版本: {version}")
199
+ # 输出: 模块: ModuleB, 操作符: None, 版本: None
200
+ ```
201
+
202
+ #### compare_versions(version1: str, version2: str) -> int
203
+ 比较两个版本号。
204
+ - 参数:
205
+ - version1: 第一个版本号字符串,如 "1.0.0"
206
+ - version2: 第二个版本号字符串,如 "2.0.0"
207
+ - 返回:
208
+ - int: 如果 version1 < version2 返回 -1,如果 version1 == version2 返回 0,如果 version1 > version2 返回 1
209
+ - 示例:
210
+ ```python
211
+ # 比较版本号
212
+ result = sdk.util.compare_versions("1.0.0", "2.0.0")
213
+ print(f"比较结果: {result}") # 输出: 比较结果: -1
214
+
215
+ result = sdk.util.compare_versions("2.0.0", "2.0.0")
216
+ print(f"比较结果: {result}") # 输出: 比较结果: 0
217
+
218
+ result = sdk.util.compare_versions("2.1.0", "2.0.5")
219
+ print(f"比较结果: {result}") # 输出: 比较结果: 1
220
+ ```
221
+
222
+ #### check_version_requirement(current_version: str, operator: str, required_version: str) -> bool
223
+ 检查当前版本是否满足版本要求。
224
+ - 参数:
225
+ - current_version: 当前版本号字符串,如 "1.0.0"
226
+ - operator: 操作符,如 "==", ">=", "<="
227
+ - required_version: 要求的版本号字符串,如 "2.0.0"
228
+ - 返回:
229
+ - bool: 如果满足要求返回 True,否则返回 False
230
+ - 示例:
231
+ ```python
232
+ # 检查版本要求
233
+ result = sdk.util.check_version_requirement("1.0.0", "==", "1.0.0")
234
+ print(f"版本匹配: {result}") # 输出: 版本匹配: True
235
+
236
+ result = sdk.util.check_version_requirement("1.5.0", ">=", "1.0.0")
237
+ print(f"版本匹配: {result}") # 输出: 版本匹配: True
238
+
239
+ result = sdk.util.check_version_requirement("2.0.0", "<", "1.0.0")
240
+ print(f"版本匹配: {result}") # 输出: 版本匹配: False
241
+ ```
242
+
243
+ ## 最佳实践
244
+ 1. 依赖管理
245
+ ```python
246
+ # 模块依赖定义
247
+ module_deps = {
248
+ "core": [],
249
+ "database": ["core"],
250
+ "api": ["database"],
251
+ "ui": ["api"]
252
+ }
253
+
254
+ # 验证并排序依赖
255
+ try:
256
+ load_order = sdk.util.topological_sort(
257
+ list(module_deps.keys()),
258
+ module_deps,
259
+ sdk.raiserr.CycleDependencyError
260
+ )
261
+
262
+ # 按顺序加载模块
263
+ for module in load_order:
264
+ load_module(module)
265
+ except Exception as e:
266
+ sdk.logger.error(f"模块加载失败: {e}")
267
+ ```
268
+
269
+ 2. 性能优化
270
+ ```python
271
+ # 合理使用缓存
272
+ @sdk.util.cache
273
+ def get_user_preferences(user_id: str) -> dict:
274
+ return database.fetch_user_preferences(user_id)
275
+
276
+ # 异步处理耗时操作
277
+ @sdk.util.run_in_executor
278
+ def process_large_dataset(data: list) -> list:
279
+ return [complex_calculation(item) for item in data]
280
+ ```
281
+
282
+ 3. 错误处理和重试
283
+ ```python
284
+ # 组合使用重试和异步
285
+ @sdk.util.retry(max_attempts=3, delay=2)
286
+ @sdk.util.run_in_executor
287
+ def reliable_network_operation():
288
+ response = requests.get("https://api.example.com")
289
+ response.raise_for_status()
290
+ return response.json()
291
+
292
+ # 带有自定义错误处理的重试
293
+ @sdk.util.retry(max_attempts=5)
294
+ def safe_operation():
295
+ try:
296
+ return perform_risky_operation()
297
+ except Exception as e:
298
+ sdk.logger.warning(f"操作失败,准备重试: {e}")
299
+ raise
300
+ ```
301
+
302
+ 4. 版本管理
303
+ ```python
304
+ # 在模块中定义依赖
305
+ moduleInfo = {
306
+ "meta": {
307
+ "name": "AdvancedFeatures",
308
+ "version": "1.2.0"
309
+ },
310
+ "dependencies": {
311
+ "requires": [
312
+ "CoreModule>=1.0.0",
313
+ "DatabaseModule==2.1.0"
314
+ ],
315
+ "optional": [
316
+ "VisualizationModule>=1.5.0",
317
+ ["CacheModule>2.0.0", "FastCacheModule>=1.0.0"]
318
+ ]
319
+ }
320
+ }
321
+
322
+ # 手动检查版本兼容性
323
+ def check_plugin_compatibility(plugin_info):
324
+ required_version = "2.0.0"
325
+ plugin_version = plugin_info.get("version", "0.0.0")
326
+
327
+ if sdk.util.check_version_requirement(plugin_version, ">=", required_version):
328
+ sdk.logger.info(f"插件 '{plugin_info['name']}' 版本兼容")
329
+ return True
330
+ else:
331
+ sdk.logger.warning(f"插件 '{plugin_info['name']}' 版本 {plugin_version} 不兼容,需要 >={required_version}")
332
+ return False
333
+
334
+ # 解析带版本要求的依赖字符串
335
+ def process_dependency(dependency_str):
336
+ module_name, operator, version = sdk.util.parse_dependency_with_version(dependency_str)
337
+ if operator and version:
338
+ return f"需要模块 {module_name} {operator}{version}"
339
+ else:
340
+ return f"需要模块 {module_name},无版本要求"
341
+ ```
342
+
343
+ ## 注意事项
344
+ 1. 缓存使用
345
+ - 注意内存占用,避免缓存过大数据
346
+ - 考虑缓存失效策略
347
+ - 不要缓存频繁变化的数据
348
+
349
+ 2. 异步执行
350
+ - 避免在 run_in_executor 中执行过长的操作
351
+ - 注意异常处理和资源清理
352
+ - 合理使用线程池
353
+
354
+ 3. 重试机制
355
+ - 设置合适的重试次数和间隔
356
+ - 只对可重试的操作使用重试装饰器
357
+ - 注意避免重试导致的资源浪费
358
+
359
+ 4. 依赖管理
360
+ - 保持依赖关系清晰简单
361
+ - 避免循环依赖
362
+ - 定期检查和更新依赖关系
363
+
364
+ 5. 版本管理
365
+ - 遵循语义化版本规范(主版本.次版本.修订版本)
366
+ - 明确指定版本要求,避免使用过于宽松的版本约束
367
+ - 在主版本更新时,注意可能的不兼容变更
368
+ - 测试不同版本依赖组合的兼容性
369
+ - 为模块提供明确的版本号和更新日志
370
+ """
371
+
1
372
  import time
2
373
  import asyncio
3
374
  import functools
4
375
  import traceback
376
+ import re
5
377
  from concurrent.futures import ThreadPoolExecutor
6
378
  from collections import defaultdict, deque
7
379
 
@@ -97,3 +469,52 @@ def retry(max_attempts=3, delay=1):
97
469
  time.sleep(delay)
98
470
  return wrapper
99
471
  return decorator
472
+
473
+ def parse_dependency_with_version(dependency_str):
474
+ pattern = r'^([a-zA-Z0-9_\-]+)(?:([=<>!]+)([0-9]+(?:\.[0-9]+)*))?\s**$'
475
+ match = re.match(pattern, dependency_str)
476
+
477
+ if not match:
478
+ return dependency_str, None, None
479
+
480
+ module_name, operator, version = match.groups()
481
+ return module_name, operator, version
482
+
483
+ def compare_versions(version1, version2):
484
+ v1_parts = [int(x) for x in version1.split('.')]
485
+ v2_parts = [int(x) for x in version2.split('.')]
486
+
487
+ # 确保两个版本号有相同的部分数
488
+ while len(v1_parts) < len(v2_parts):
489
+ v1_parts.append(0)
490
+ while len(v2_parts) < len(v1_parts):
491
+ v2_parts.append(0)
492
+
493
+ for i in range(len(v1_parts)):
494
+ if v1_parts[i] < v2_parts[i]:
495
+ return -1
496
+ elif v1_parts[i] > v2_parts[i]:
497
+ return 1
498
+
499
+ return 0
500
+
501
+ def check_version_requirement(current_version, operator, required_version):
502
+ if not operator or not required_version:
503
+ return True
504
+
505
+ comparison = compare_versions(current_version, required_version)
506
+
507
+ if operator == '==':
508
+ return comparison == 0
509
+ elif operator == '!=':
510
+ return comparison != 0
511
+ elif operator == '>':
512
+ return comparison > 0
513
+ elif operator == '>=':
514
+ return comparison >= 0
515
+ elif operator == '<':
516
+ return comparison < 0
517
+ elif operator == '<=':
518
+ return comparison <= 0
519
+
520
+ return False