ErisPulse 2.1.14.dev2__py3-none-any.whl → 2.1.15__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.
@@ -1,4 +1,5 @@
1
1
  from .adapter import AdapterFather, SendDSL, adapter
2
+ from .storage import storage
2
3
  from .env import env
3
4
  from .logger import logger
4
5
  from .mods import mods
@@ -13,6 +14,7 @@ __all__ = [
13
14
  'AdapterFather',
14
15
  'SendDSL',
15
16
  'adapter',
17
+ 'storage',
16
18
  'env',
17
19
  'logger',
18
20
  'mods',
ErisPulse/Core/adapter.py CHANGED
@@ -545,4 +545,10 @@ class AdapterManager:
545
545
 
546
546
  AdapterFather = BaseAdapter
547
547
  adapter = AdapterManager()
548
- SendDSL = SendDSLBase
548
+ SendDSL = SendDSLBase
549
+
550
+ __all__ = [
551
+ "AdapterFather",
552
+ "adapter",
553
+ "SendDSL"
554
+ ]
ErisPulse/Core/config.py CHANGED
@@ -72,3 +72,7 @@ class ConfigManager:
72
72
  return False
73
73
 
74
74
  config = ConfigManager()
75
+
76
+ __all__ = [
77
+ "config"
78
+ ]
ErisPulse/Core/env.py CHANGED
@@ -1,542 +1,15 @@
1
1
  """
2
- ErisPulse 环境配置模块
2
+ ErisPulse 环境模块 (已弃用)
3
3
 
4
- 提供键值存储、事务支持、快照和恢复功能,用于管理框架配置数据。基于SQLite实现持久化存储,支持复杂数据类型和原子操作。
4
+ 此模块已重命名为 storage,为保持向后兼容性而保留。
5
+ 建议使用 from ErisPulse.Core import storage 替代 from ErisPulse.Core import env
5
6
 
6
- {!--< tips >!--}
7
- 1. 支持JSON序列化存储复杂数据类型
8
- 2. 提供事务支持确保数据一致性
9
- 3. 自动快照功能防止数据丢失
10
- {!--< /tips >!--}
7
+ {!--< deprecated >!--} 请使用 storage 模块替代
11
8
  """
12
9
 
13
- import os
14
- import json
15
- import sqlite3
16
- import shutil
17
- import time
18
- from datetime import datetime
19
- from typing import List, Dict, Optional, Any, Tuple, Type
10
+ from .storage import storage
20
11
 
21
- class EnvManager:
22
- """
23
- 环境配置管理器
24
-
25
- 单例模式实现,提供配置的增删改查、事务和快照管理
26
-
27
- {!--< tips >!--}
28
- 1. 使用get/set方法操作配置项
29
- 2. 使用transaction上下文管理事务
30
- 3. 使用snapshot/restore管理数据快照
31
- {!--< /tips >!--}
32
- """
33
-
34
- _instance = None
35
- db_path = os.path.join(os.path.dirname(__file__), "../data/config.db")
36
- SNAPSHOT_DIR = os.path.join(os.path.dirname(__file__), "../data/snapshots")
37
-
12
+ # 向后兼容性
13
+ env = storage
38
14
 
39
- def __new__(cls, *args, **kwargs):
40
- if not cls._instance:
41
- cls._instance = super().__new__(cls)
42
- return cls._instance
43
-
44
- def __init__(self):
45
- if not hasattr(self, "_initialized"):
46
- # 确保关键属性在初始化时都有默认值
47
- self._last_snapshot_time = time.time()
48
- self._snapshot_interval = 3600
49
- self._init_db()
50
- self._initialized = True
51
-
52
- def _init_db(self) -> None:
53
- """
54
- {!--< internal-use >!--}
55
- 初始化数据库
56
- """
57
- os.makedirs(os.path.dirname(self.db_path), exist_ok=True)
58
- os.makedirs(self.SNAPSHOT_DIR, exist_ok=True)
59
- conn = sqlite3.connect(self.db_path)
60
-
61
- # 启用WAL模式提高并发性能
62
- conn.execute("PRAGMA journal_mode=WAL")
63
- conn.execute("PRAGMA synchronous=NORMAL")
64
-
65
- cursor = conn.cursor()
66
- cursor.execute("""
67
- CREATE TABLE IF NOT EXISTS config (
68
- key TEXT PRIMARY KEY,
69
- value TEXT NOT NULL
70
- )
71
- """)
72
- conn.commit()
73
- conn.close()
74
-
75
- # 初始化自动快照调度器
76
- self._last_snapshot_time = time.time() # 初始化为当前时间
77
- self._snapshot_interval = 3600 # 默认每小时自动快照
78
-
79
- def get(self, key: str, default: Any = None) -> Any:
80
- """
81
- 获取配置项的值
82
-
83
- :param key: 配置项键名
84
- :param default: 默认值(当键不存在时返回)
85
- :return: 配置项的值
86
-
87
- :example:
88
- >>> timeout = env.get("network.timeout", 30)
89
- >>> user_settings = env.get("user.settings", {})
90
- """
91
- try:
92
- with sqlite3.connect(self.db_path) as conn:
93
- cursor = conn.cursor()
94
- cursor.execute("SELECT value FROM config WHERE key = ?", (key,))
95
- result = cursor.fetchone()
96
- if result:
97
- try:
98
- return json.loads(result[0])
99
- except json.JSONDecodeError:
100
- return result[0]
101
- return default
102
- except sqlite3.OperationalError as e:
103
- if "no such table" in str(e):
104
- self._init_db()
105
- return self.get(key, default)
106
- else:
107
- from . import logger
108
- logger.error(f"数据库操作错误: {e}")
109
- def get_all_keys(self) -> List[str]:
110
- """
111
- 获取所有配置项的键名
112
-
113
- :return: 键名列表
114
-
115
- :example:
116
- >>> all_keys = env.get_all_keys()
117
- >>> print(f"共有 {len(all_keys)} 个配置项")
118
- """
119
- with sqlite3.connect(self.db_path) as conn:
120
- cursor = conn.cursor()
121
- cursor.execute("SELECT key FROM config")
122
- return [row[0] for row in cursor.fetchall()]
123
- def set(self, key: str, value: Any) -> bool:
124
- """
125
- 设置配置项的值
126
-
127
- :param key: 配置项键名
128
- :param value: 配置项的值
129
- :return: 操作是否成功
130
-
131
- :example:
132
- >>> env.set("app.name", "MyApp")
133
- >>> env.set("user.settings", {"theme": "dark"})
134
- """
135
- try:
136
- serialized_value = json.dumps(value) if isinstance(value, (dict, list)) else str(value)
137
- with self.transaction():
138
- conn = sqlite3.connect(self.db_path)
139
- cursor = conn.cursor()
140
- cursor.execute("INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)", (key, serialized_value))
141
- conn.commit()
142
- conn.close()
143
-
144
- self._check_auto_snapshot()
145
- return True
146
- except Exception as e:
147
- return False
148
-
149
- def set_multi(self, items: Dict[str, Any]) -> bool:
150
- """
151
- 批量设置多个配置项
152
-
153
- :param items: 键值对字典
154
- :return: 操作是否成功
155
-
156
- :example:
157
- >>> env.set_multi({
158
- >>> "app.name": "MyApp",
159
- >>> "app.version": "1.0.0",
160
- >>> "app.debug": True
161
- >>> })
162
- """
163
- try:
164
- with self.transaction():
165
- conn = sqlite3.connect(self.db_path)
166
- cursor = conn.cursor()
167
- for key, value in items.items():
168
- serialized_value = json.dumps(value) if isinstance(value, (dict, list)) else str(value)
169
- cursor.execute("INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)",
170
- (key, serialized_value))
171
- conn.commit()
172
- conn.close()
173
-
174
- self._check_auto_snapshot()
175
- return True
176
- except Exception as e:
177
- return False
178
-
179
- def getConfig(self, key: str, default: Any = None) -> Any:
180
- """
181
- 获取模块/适配器配置项
182
- :param key: 配置项的键(支持点分隔符如"module.sub.key")
183
- :param default: 默认值
184
- :return: 配置项的值
185
- """
186
- try:
187
- from .config import config
188
- return config.getConfig(key, default)
189
- except Exception as e:
190
- return default
191
-
192
- def setConfig(self, key: str, value: Any) -> bool:
193
- """
194
- 设置模块/适配器配置
195
- :param key: 配置项键名(支持点分隔符如"module.sub.key")
196
- :param value: 配置项值
197
- :return: 操作是否成功
198
- """
199
- try:
200
- from .config import config
201
- return config.setConfig(key, value)
202
- except Exception as e:
203
- return False
204
-
205
- def delete(self, key: str) -> bool:
206
- """
207
- 删除配置项
208
-
209
- :param key: 配置项键名
210
- :return: 操作是否成功
211
-
212
- :example:
213
- >>> env.delete("temp.session")
214
- """
215
- try:
216
- with self.transaction():
217
- conn = sqlite3.connect(self.db_path)
218
- cursor = conn.cursor()
219
- cursor.execute("DELETE FROM config WHERE key = ?", (key,))
220
- conn.commit()
221
- conn.close()
222
-
223
- self._check_auto_snapshot()
224
- return True
225
- except Exception as e:
226
- return False
227
-
228
- def delete_multi(self, keys: List[str]) -> bool:
229
- """
230
- 批量删除多个配置项
231
-
232
- :param keys: 键名列表
233
- :return: 操作是否成功
234
-
235
- :example:
236
- >>> env.delete_multi(["temp.key1", "temp.key2"])
237
- """
238
- try:
239
- with self.transaction():
240
- conn = sqlite3.connect(self.db_path)
241
- cursor = conn.cursor()
242
- cursor.executemany("DELETE FROM config WHERE key = ?", [(k,) for k in keys])
243
- conn.commit()
244
- conn.close()
245
-
246
- self._check_auto_snapshot()
247
- return True
248
- except Exception as e:
249
- return False
250
-
251
- def get_multi(self, keys: List[str]) -> Dict[str, Any]:
252
- """
253
- 批量获取多个配置项的值
254
-
255
- :param keys: 键名列表
256
- :return: 键值对字典
257
-
258
- :example:
259
- >>> settings = env.get_multi(["app.name", "app.version"])
260
- """
261
- conn = sqlite3.connect(self.db_path)
262
- cursor = conn.cursor()
263
- placeholders = ','.join(['?'] * len(keys))
264
- cursor.execute(f"SELECT key, value FROM config WHERE key IN ({placeholders})", keys)
265
- results = {row[0]: json.loads(row[1]) if row[1].startswith(('{', '[')) else row[1]
266
- for row in cursor.fetchall()}
267
- conn.close()
268
- return results
269
-
270
- def transaction(self) -> 'EnvManager._Transaction':
271
- """
272
- 创建事务上下文
273
-
274
- :return: 事务上下文管理器
275
-
276
- :example:
277
- >>> with env.transaction():
278
- >>> env.set("key1", "value1")
279
- >>> env.set("key2", "value2")
280
- """
281
- return self._Transaction(self)
282
-
283
- class _Transaction:
284
- """
285
- 事务上下文管理器
286
-
287
- {!--< internal-use >!--}
288
- 确保多个操作的原子性
289
- """
290
-
291
- def __init__(self, env_manager: 'EnvManager'):
292
- self.env_manager = env_manager
293
- self.conn = None
294
- self.cursor = None
295
-
296
- def __enter__(self) -> 'EnvManager._Transaction':
297
- """
298
- 进入事务上下文
299
- """
300
- self.conn = sqlite3.connect(self.env_manager.db_path)
301
- self.cursor = self.conn.cursor()
302
- self.cursor.execute("BEGIN TRANSACTION")
303
- return self
304
-
305
- def __exit__(self, exc_type: Type[Exception], exc_val: Exception, exc_tb: Any) -> None:
306
- """
307
- 退出事务上下文
308
- """
309
- if exc_type is None:
310
- self.conn.commit()
311
- else:
312
- self.conn.rollback()
313
- from .logger import logger
314
- logger.error(f"事务执行失败: {exc_val}")
315
- self.conn.close()
316
-
317
- def _check_auto_snapshot(self) -> None:
318
- """
319
- {!--< internal-use >!--}
320
- 检查并执行自动快照
321
- """
322
- from .logger import logger
323
-
324
- if not hasattr(self, '_last_snapshot_time') or self._last_snapshot_time is None:
325
- self._last_snapshot_time = time.time()
326
-
327
- if not hasattr(self, '_snapshot_interval') or self._snapshot_interval is None:
328
- self._snapshot_interval = 3600
329
-
330
- current_time = time.time()
331
-
332
- try:
333
- time_diff = current_time - self._last_snapshot_time
334
- if not isinstance(time_diff, (int, float)):
335
- raise ValueError("时间差应为数值类型")
336
-
337
- if not isinstance(self._snapshot_interval, (int, float)):
338
- raise ValueError("快照间隔应为数值类型")
339
-
340
- if time_diff > self._snapshot_interval:
341
- self._last_snapshot_time = current_time
342
- self.snapshot(f"auto_{datetime.now().strftime('%Y%m%d_%H%M%S')}")
343
-
344
- except Exception as e:
345
- logger.error(f"自动快照检查失败: {e}")
346
- self._last_snapshot_time = current_time
347
- self._snapshot_interval = 3600
348
-
349
- def set_snapshot_interval(self, seconds: int) -> None:
350
- """
351
- 设置自动快照间隔
352
-
353
- :param seconds: 间隔秒数
354
-
355
- :example:
356
- >>> # 每30分钟自动快照
357
- >>> env.set_snapshot_interval(1800)
358
- """
359
- self._snapshot_interval = seconds
360
-
361
- def clear(self) -> bool:
362
- """
363
- 清空所有配置项
364
-
365
- :return: 操作是否成功
366
-
367
- :example:
368
- >>> env.clear() # 清空所有配置
369
- """
370
- try:
371
- conn = sqlite3.connect(self.db_path)
372
- cursor = conn.cursor()
373
- cursor.execute("DELETE FROM config")
374
- conn.commit()
375
- conn.close()
376
- return True
377
- except Exception as e:
378
- return False
379
-
380
- def __getattr__(self, key: str) -> Any:
381
- """
382
- 通过属性访问配置项
383
-
384
- :param key: 配置项键名
385
- :return: 配置项的值
386
-
387
- :raises KeyError: 当配置项不存在时抛出
388
-
389
- :example:
390
- >>> app_name = env.app_name
391
- """
392
- try:
393
- return self.get(key)
394
- except KeyError:
395
- from . import logger
396
- logger.error(f"配置项 {key} 不存在")
397
-
398
- def __setattr__(self, key: str, value: Any) -> None:
399
- """
400
- 通过属性设置配置项
401
-
402
- :param key: 配置项键名
403
- :param value: 配置项的值
404
-
405
- :example:
406
- >>> env.app_name = "MyApp"
407
- """
408
- try:
409
- self.set(key, value)
410
- except Exception as e:
411
- from . import logger
412
- logger.error(f"设置配置项 {key} 失败: {e}")
413
-
414
- def snapshot(self, name: Optional[str] = None) -> str:
415
- """
416
- 创建数据库快照
417
-
418
- :param name: 快照名称(可选)
419
- :return: 快照文件路径
420
-
421
- :example:
422
- >>> # 创建命名快照
423
- >>> snapshot_path = env.snapshot("before_update")
424
- >>> # 创建时间戳快照
425
- >>> snapshot_path = env.snapshot()
426
- """
427
- if not name:
428
- name = datetime.now().strftime("%Y%m%d_%H%M%S")
429
- snapshot_path = os.path.join(self.SNAPSHOT_DIR, f"{name}.db")
430
-
431
- try:
432
- # 快照目录
433
- os.makedirs(self.SNAPSHOT_DIR, exist_ok=True)
434
-
435
- # 安全关闭连接
436
- if hasattr(self, "_conn") and self._conn is not None:
437
- try:
438
- self._conn.close()
439
- except Exception as e:
440
- from . import logger
441
- logger.warning(f"关闭数据库连接时出错: {e}")
442
-
443
- # 创建快照
444
- shutil.copy2(self.db_path, snapshot_path)
445
- from . import logger
446
- logger.info(f"数据库快照已创建: {snapshot_path}")
447
- return snapshot_path
448
- except Exception as e:
449
- from . import logger
450
- logger.error(f"创建快照失败: {e}")
451
- raise
452
-
453
- def restore(self, snapshot_name: str) -> bool:
454
- """
455
- 从快照恢复数据库
456
-
457
- :param snapshot_name: 快照名称或路径
458
- :return: 恢复是否成功
459
-
460
- :example:
461
- >>> env.restore("before_update")
462
- """
463
- snapshot_path = os.path.join(self.SNAPSHOT_DIR, f"{snapshot_name}.db") \
464
- if not snapshot_name.endswith('.db') else snapshot_name
465
-
466
- if not os.path.exists(snapshot_path):
467
- from . import logger
468
- logger.error(f"快照文件不存在: {snapshot_path}")
469
- return False
470
-
471
- try:
472
- # 安全关闭连接
473
- if hasattr(self, "_conn") and self._conn is not None:
474
- try:
475
- self._conn.close()
476
- except Exception as e:
477
- from . import logger
478
- logger.warning(f"关闭数据库连接时出错: {e}")
479
-
480
- # 执行恢复操作
481
- shutil.copy2(snapshot_path, self.db_path)
482
- self._init_db() # 恢复后重新初始化数据库连接
483
- from . import logger
484
- logger.info(f"数据库已从快照恢复: {snapshot_path}")
485
- return True
486
- except Exception as e:
487
- from . import logger
488
- logger.error(f"恢复快照失败: {e}")
489
- return False
490
-
491
- def list_snapshots(self) -> List[Tuple[str, datetime, int]]:
492
- """
493
- 列出所有可用的快照
494
-
495
- :return: 快照信息列表(名称, 创建时间, 大小)
496
-
497
- :example:
498
- >>> for name, date, size in env.list_snapshots():
499
- >>> print(f"{name} - {date} ({size} bytes)")
500
- """
501
- snapshots = []
502
- for f in os.listdir(self.SNAPSHOT_DIR):
503
- if f.endswith('.db'):
504
- path = os.path.join(self.SNAPSHOT_DIR, f)
505
- stat = os.stat(path)
506
- snapshots.append((
507
- f[:-3], # 去掉.db后缀
508
- datetime.fromtimestamp(stat.st_ctime),
509
- stat.st_size
510
- ))
511
- return sorted(snapshots, key=lambda x: x[1], reverse=True)
512
-
513
- def delete_snapshot(self, snapshot_name: str) -> bool:
514
- """
515
- 删除指定的快照
516
-
517
- :param snapshot_name: 快照名称
518
- :return: 删除是否成功
519
-
520
- :example:
521
- >>> env.delete_snapshot("old_backup")
522
- """
523
- snapshot_path = os.path.join(self.SNAPSHOT_DIR, f"{snapshot_name}.db") \
524
- if not snapshot_name.endswith('.db') else snapshot_name
525
-
526
- if not os.path.exists(snapshot_path):
527
- from . import logger
528
- logger.error(f"快照文件不存在: {snapshot_path}")
529
- return False
530
-
531
- try:
532
- os.remove(snapshot_path)
533
- from . import logger
534
- logger.info(f"快照已删除: {snapshot_path}")
535
- return True
536
- except Exception as e:
537
- from . import logger
538
- logger.error(f"删除快照失败: {e}")
539
- return False
540
-
541
-
542
- env = EnvManager()
15
+ __all__ = ['env']
ErisPulse/Core/logger.py CHANGED
@@ -56,6 +56,10 @@ class Logger:
56
56
  """
57
57
  if limit > 0:
58
58
  self._max_logs = limit
59
+ # 更新所有已存在的日志列表大小
60
+ for module_name in self._logs:
61
+ while len(self._logs[module_name]) > self._max_logs:
62
+ self._logs[module_name].pop(0)
59
63
  return True
60
64
  else:
61
65
  self._logger.warning("日志存储上限必须大于0。")
@@ -198,6 +202,20 @@ class Logger:
198
202
  module_name = "ErisPulse"
199
203
  return module_name
200
204
 
205
+ def get_child(self, child_name: str = None):
206
+ """
207
+ 获取子日志记录器
208
+
209
+ :param child_name: 子模块名称(可选)
210
+ :return: LoggerChild 子日志记录器实例
211
+ """
212
+ caller_module = self._get_caller()
213
+ if child_name:
214
+ full_module_name = f"{caller_module}.{child_name}"
215
+ else:
216
+ full_module_name = caller_module
217
+ return LoggerChild(self, full_module_name)
218
+
201
219
  def debug(self, msg, *args, **kwargs):
202
220
  caller_module = self._get_caller()
203
221
  if self._get_effective_level(caller_module) <= logging.DEBUG:
@@ -229,4 +247,63 @@ class Logger:
229
247
  self._logger.critical(f"[{caller_module}] {msg}", *args, **kwargs)
230
248
  raise Exception(msg)
231
249
 
232
- logger = Logger()
250
+
251
+ class LoggerChild:
252
+ """
253
+ 子日志记录器
254
+
255
+ 用于创建具有特定名称的子日志记录器,仅改变模块名称,其他功能全部委托给父日志记录器
256
+ """
257
+
258
+ def __init__(self, parent_logger: Logger, name: str):
259
+ """
260
+ 初始化子日志记录器
261
+
262
+ :param parent_logger: 父日志记录器实例
263
+ :param name: 子日志记录器名称
264
+ """
265
+ self._parent = parent_logger
266
+ self._name = name
267
+
268
+ def debug(self, msg, *args, **kwargs):
269
+ if self._parent._get_effective_level(self._name.split('.')[0]) <= logging.DEBUG:
270
+ self._parent._save_in_memory(self._name, msg)
271
+ self._parent._logger.debug(f"[{self._name}] {msg}", *args, **kwargs)
272
+
273
+ def info(self, msg, *args, **kwargs):
274
+ if self._parent._get_effective_level(self._name.split('.')[0]) <= logging.INFO:
275
+ self._parent._save_in_memory(self._name, msg)
276
+ self._parent._logger.info(f"[{self._name}] {msg}", *args, **kwargs)
277
+
278
+ def warning(self, msg, *args, **kwargs):
279
+ if self._parent._get_effective_level(self._name.split('.')[0]) <= logging.WARNING:
280
+ self._parent._save_in_memory(self._name, msg)
281
+ self._parent._logger.warning(f"[{self._name}] {msg}", *args, **kwargs)
282
+
283
+ def error(self, msg, *args, **kwargs):
284
+ if self._parent._get_effective_level(self._name.split('.')[0]) <= logging.ERROR:
285
+ self._parent._save_in_memory(self._name, msg)
286
+ self._parent._logger.error(f"[{self._name}] {msg}", *args, **kwargs)
287
+
288
+ def critical(self, msg, *args, **kwargs):
289
+ if self._parent._get_effective_level(self._name.split('.')[0]) <= logging.CRITICAL:
290
+ self._parent._save_in_memory(self._name, msg)
291
+ self._parent._logger.critical(f"[{self._name}] {msg}", *args, **kwargs)
292
+ raise Exception(msg)
293
+
294
+ def get_child(self, child_name: str):
295
+ """
296
+ 获取子日志记录器的子记录器
297
+
298
+ :param child_name: 子模块名称
299
+ :return: LoggerChild 子日志记录器实例
300
+ """
301
+ full_child_name = f"{self._name}.{child_name}"
302
+ return LoggerChild(self._parent, full_child_name)
303
+
304
+
305
+ logger = Logger()
306
+
307
+ __all__ = [
308
+ "logger"
309
+ ]