ErisPulse 1.0.13__py3-none-any.whl → 1.0.14.dev2__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,227 +1,227 @@
1
- import os
2
- import json
3
- import sqlite3
4
- import importlib.util
5
- from pathlib import Path
6
-
7
- class EnvManager:
8
- _instance = None
9
- db_path = os.path.join(os.path.dirname(__file__), "config.db")
10
-
11
- def __new__(cls, *args, **kwargs):
12
- if not cls._instance:
13
- cls._instance = super().__new__(cls)
14
- cls._instance.dev_mode = kwargs.get('dev_mode', False)
15
- return cls._instance
16
-
17
- def __init__(self, dev_mode=False):
18
- if not hasattr(self, "_initialized"):
19
- self.dev_mode = dev_mode
20
- self._init_db()
21
-
22
- def _init_db(self):
23
- os.makedirs(os.path.dirname(self.db_path), exist_ok=True)
24
-
25
- conn = sqlite3.connect(self.db_path)
26
- cursor = conn.cursor()
27
- cursor.execute("""
28
- CREATE TABLE IF NOT EXISTS config (
29
- key TEXT PRIMARY KEY,
30
- value TEXT NOT NULL
31
- )
32
- """)
33
- cursor.execute("""
34
- CREATE TABLE IF NOT EXISTS modules (
35
- module_name TEXT PRIMARY KEY,
36
- status INTEGER NOT NULL,
37
- version TEXT,
38
- description TEXT,
39
- author TEXT,
40
- dependencies TEXT,
41
- optional_dependencies TEXT,
42
- pip_dependencies TEXT
43
- )
44
- """)
45
- conn.commit()
46
- conn.close()
47
-
48
- def get(self, key, default=None):
49
- try:
50
- with sqlite3.connect(self.db_path) as conn:
51
- cursor = conn.cursor()
52
- cursor.execute("SELECT value FROM config WHERE key = ?", (key,))
53
- result = cursor.fetchone()
54
- if result:
55
- try:
56
- return json.loads(result[0])
57
- except json.JSONDecodeError:
58
- return result[0]
59
- return default
60
- except sqlite3.OperationalError as e:
61
- if "no such table" in str(e):
62
- self._init_db()
63
- return self.get(key, default)
64
- else:
65
- raise
66
-
67
- def set(self, key, value):
68
- serialized_value = json.dumps(value) if isinstance(value, (dict, list)) else str(value)
69
- conn = sqlite3.connect(self.db_path)
70
- cursor = conn.cursor()
71
- cursor.execute("INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)", (key, serialized_value))
72
- conn.commit()
73
- conn.close()
74
-
75
- def delete(self, key):
76
- conn = sqlite3.connect(self.db_path)
77
- cursor = conn.cursor()
78
- cursor.execute("DELETE FROM config WHERE key = ?", (key,))
79
- conn.commit()
80
- conn.close()
81
-
82
- def clear(self):
83
- conn = sqlite3.connect(self.db_path)
84
- cursor = conn.cursor()
85
- cursor.execute("DELETE FROM config")
86
- conn.commit()
87
- conn.close()
88
-
89
- def load_env_file(self):
90
- env_file = Path("env.py")
91
- if env_file.exists():
92
- spec = importlib.util.spec_from_file_location("env_module", env_file)
93
- env_module = importlib.util.module_from_spec(spec)
94
- spec.loader.exec_module(env_module)
95
- for key, value in vars(env_module).items():
96
- if not key.startswith("__") and isinstance(value, (dict, list, str, int, float, bool)):
97
- self.set(key, value)
98
- def set_module_status(self, module_name, status):
99
- with sqlite3.connect(self.db_path) as conn:
100
- cursor = conn.cursor()
101
- cursor.execute("""
102
- UPDATE modules SET status = ? WHERE module_name = ?
103
- """, (int(status), module_name))
104
- conn.commit()
105
-
106
- def get_module_status(self, module_name):
107
- with sqlite3.connect(self.db_path) as conn:
108
- cursor = conn.cursor()
109
- cursor.execute("""
110
- SELECT status FROM modules WHERE module_name = ?
111
- """, (module_name,))
112
- result = cursor.fetchone()
113
- return bool(result[0]) if result else True
114
-
115
- def set_all_modules(self, modules_info):
116
- with sqlite3.connect(self.db_path) as conn:
117
- cursor = conn.cursor()
118
- for module_name, module_info in modules_info.items():
119
- meta = module_info.get('info', {}).get('meta', {})
120
- dependencies = module_info.get('info', {}).get('dependencies', {})
121
- cursor.execute("""
122
- INSERT OR REPLACE INTO modules (
123
- module_name, status, version, description, author,
124
- dependencies, optional_dependencies, pip_dependencies
125
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
126
- """, (
127
- module_name,
128
- int(module_info.get('status', True)),
129
- meta.get('version', ''),
130
- meta.get('description', ''),
131
- meta.get('author', ''),
132
- json.dumps(dependencies.get('requires', [])),
133
- json.dumps(dependencies.get('optional', [])),
134
- json.dumps(dependencies.get('pip', []))
135
- ))
136
- conn.commit()
137
-
138
- def get_all_modules(self):
139
- with sqlite3.connect(self.db_path) as conn:
140
- cursor = conn.cursor()
141
- cursor.execute("SELECT * FROM modules")
142
- rows = cursor.fetchall()
143
- modules_info = {}
144
- for row in rows:
145
- module_name, status, version, description, author, dependencies, optional_dependencies, pip_dependencies = row
146
- modules_info[module_name] = {
147
- 'status': bool(status),
148
- 'info': {
149
- 'meta': {
150
- 'version': version,
151
- 'description': description,
152
- 'author': author,
153
- 'pip_dependencies': json.loads(pip_dependencies) if pip_dependencies else []
154
- },
155
- 'dependencies': {
156
- 'requires': json.loads(dependencies) if dependencies else [],
157
- 'optional': json.loads(optional_dependencies) if optional_dependencies else [],
158
- 'pip': json.loads(pip_dependencies) if pip_dependencies else []
159
- }
160
- }
161
- }
162
- return modules_info
163
-
164
- def set_module(self, module_name, module_info):
165
- with sqlite3.connect(self.db_path) as conn:
166
- cursor = conn.cursor()
167
- meta = module_info.get('info', {}).get('meta', {})
168
- dependencies = module_info.get('info', {}).get('dependencies', {})
169
- cursor.execute("""
170
- INSERT OR REPLACE INTO modules (
171
- module_name, status, version, description, author,
172
- dependencies, optional_dependencies, pip_dependencies
173
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
174
- """, (
175
- module_name,
176
- int(module_info.get('status', True)),
177
- meta.get('version', ''),
178
- meta.get('description', ''),
179
- meta.get('author', ''),
180
- json.dumps(dependencies.get('requires', [])),
181
- json.dumps(dependencies.get('optional', [])),
182
- json.dumps(dependencies.get('pip', []))
183
- ))
184
- conn.commit()
185
-
186
- def get_module(self, module_name):
187
- with sqlite3.connect(self.db_path) as conn:
188
- cursor = conn.cursor()
189
- cursor.execute("SELECT * FROM modules WHERE module_name = ?", (module_name,))
190
- row = cursor.fetchone()
191
- if row:
192
- module_name, status, version, description, author, dependencies, optional_dependencies, pip_dependencies = row
193
- return {
194
- 'status': bool(status),
195
- 'info': {
196
- 'meta': {
197
- 'version': version,
198
- 'description': description,
199
- 'author': author,
200
- 'pip_dependencies': json.loads(pip_dependencies) if pip_dependencies else []
201
- },
202
- 'dependencies': {
203
- 'requires': json.loads(dependencies) if dependencies else [],
204
- 'optional': json.loads(optional_dependencies) if optional_dependencies else [],
205
- 'pip': json.loads(pip_dependencies) if pip_dependencies else []
206
- }
207
- }
208
- }
209
- return None
210
-
211
- def update_module(self, module_name, module_info):
212
- self.set_module(module_name, module_info)
213
-
214
- def remove_module(self, module_name):
215
- with sqlite3.connect(self.db_path) as conn:
216
- cursor = conn.cursor()
217
- cursor.execute("DELETE FROM modules WHERE module_name = ?", (module_name,))
218
- conn.commit()
219
- return cursor.rowcount > 0
220
-
221
- def __getattr__(self, key):
222
- try:
223
- return self.get(key)
224
- except KeyError:
225
- raise AttributeError(f"配置项 {key} 不存在")
226
-
227
- env = EnvManager()
1
+ import os
2
+ import json
3
+ import sqlite3
4
+ import importlib.util
5
+ from pathlib import Path
6
+
7
+ class EnvManager:
8
+ _instance = None
9
+ db_path = os.path.join(os.path.dirname(__file__), "config.db")
10
+
11
+ def __new__(cls, *args, **kwargs):
12
+ if not cls._instance:
13
+ cls._instance = super().__new__(cls)
14
+ cls._instance.dev_mode = kwargs.get('dev_mode', False)
15
+ return cls._instance
16
+
17
+ def __init__(self, dev_mode=False):
18
+ if not hasattr(self, "_initialized"):
19
+ self.dev_mode = dev_mode
20
+ self._init_db()
21
+
22
+ def _init_db(self):
23
+ os.makedirs(os.path.dirname(self.db_path), exist_ok=True)
24
+
25
+ conn = sqlite3.connect(self.db_path)
26
+ cursor = conn.cursor()
27
+ cursor.execute("""
28
+ CREATE TABLE IF NOT EXISTS config (
29
+ key TEXT PRIMARY KEY,
30
+ value TEXT NOT NULL
31
+ )
32
+ """)
33
+ cursor.execute("""
34
+ CREATE TABLE IF NOT EXISTS modules (
35
+ module_name TEXT PRIMARY KEY,
36
+ status INTEGER NOT NULL,
37
+ version TEXT,
38
+ description TEXT,
39
+ author TEXT,
40
+ dependencies TEXT,
41
+ optional_dependencies TEXT,
42
+ pip_dependencies TEXT
43
+ )
44
+ """)
45
+ conn.commit()
46
+ conn.close()
47
+
48
+ def get(self, key, default=None):
49
+ try:
50
+ with sqlite3.connect(self.db_path) as conn:
51
+ cursor = conn.cursor()
52
+ cursor.execute("SELECT value FROM config WHERE key = ?", (key,))
53
+ result = cursor.fetchone()
54
+ if result:
55
+ try:
56
+ return json.loads(result[0])
57
+ except json.JSONDecodeError:
58
+ return result[0]
59
+ return default
60
+ except sqlite3.OperationalError as e:
61
+ if "no such table" in str(e):
62
+ self._init_db()
63
+ return self.get(key, default)
64
+ else:
65
+ raise
66
+
67
+ def set(self, key, value):
68
+ serialized_value = json.dumps(value) if isinstance(value, (dict, list)) else str(value)
69
+ conn = sqlite3.connect(self.db_path)
70
+ cursor = conn.cursor()
71
+ cursor.execute("INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)", (key, serialized_value))
72
+ conn.commit()
73
+ conn.close()
74
+
75
+ def delete(self, key):
76
+ conn = sqlite3.connect(self.db_path)
77
+ cursor = conn.cursor()
78
+ cursor.execute("DELETE FROM config WHERE key = ?", (key,))
79
+ conn.commit()
80
+ conn.close()
81
+
82
+ def clear(self):
83
+ conn = sqlite3.connect(self.db_path)
84
+ cursor = conn.cursor()
85
+ cursor.execute("DELETE FROM config")
86
+ conn.commit()
87
+ conn.close()
88
+
89
+ def load_env_file(self):
90
+ env_file = Path("env.py")
91
+ if env_file.exists():
92
+ spec = importlib.util.spec_from_file_location("env_module", env_file)
93
+ env_module = importlib.util.module_from_spec(spec)
94
+ spec.loader.exec_module(env_module)
95
+ for key, value in vars(env_module).items():
96
+ if not key.startswith("__") and isinstance(value, (dict, list, str, int, float, bool)):
97
+ self.set(key, value)
98
+ def set_module_status(self, module_name, status):
99
+ with sqlite3.connect(self.db_path) as conn:
100
+ cursor = conn.cursor()
101
+ cursor.execute("""
102
+ UPDATE modules SET status = ? WHERE module_name = ?
103
+ """, (int(status), module_name))
104
+ conn.commit()
105
+
106
+ def get_module_status(self, module_name):
107
+ with sqlite3.connect(self.db_path) as conn:
108
+ cursor = conn.cursor()
109
+ cursor.execute("""
110
+ SELECT status FROM modules WHERE module_name = ?
111
+ """, (module_name,))
112
+ result = cursor.fetchone()
113
+ return bool(result[0]) if result else True
114
+
115
+ def set_all_modules(self, modules_info):
116
+ with sqlite3.connect(self.db_path) as conn:
117
+ cursor = conn.cursor()
118
+ for module_name, module_info in modules_info.items():
119
+ meta = module_info.get('info', {}).get('meta', {})
120
+ dependencies = module_info.get('info', {}).get('dependencies', {})
121
+ cursor.execute("""
122
+ INSERT OR REPLACE INTO modules (
123
+ module_name, status, version, description, author,
124
+ dependencies, optional_dependencies, pip_dependencies
125
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
126
+ """, (
127
+ module_name,
128
+ int(module_info.get('status', True)),
129
+ meta.get('version', ''),
130
+ meta.get('description', ''),
131
+ meta.get('author', ''),
132
+ json.dumps(dependencies.get('requires', [])),
133
+ json.dumps(dependencies.get('optional', [])),
134
+ json.dumps(dependencies.get('pip', []))
135
+ ))
136
+ conn.commit()
137
+
138
+ def get_all_modules(self):
139
+ with sqlite3.connect(self.db_path) as conn:
140
+ cursor = conn.cursor()
141
+ cursor.execute("SELECT * FROM modules")
142
+ rows = cursor.fetchall()
143
+ modules_info = {}
144
+ for row in rows:
145
+ module_name, status, version, description, author, dependencies, optional_dependencies, pip_dependencies = row
146
+ modules_info[module_name] = {
147
+ 'status': bool(status),
148
+ 'info': {
149
+ 'meta': {
150
+ 'version': version,
151
+ 'description': description,
152
+ 'author': author,
153
+ 'pip_dependencies': json.loads(pip_dependencies) if pip_dependencies else []
154
+ },
155
+ 'dependencies': {
156
+ 'requires': json.loads(dependencies) if dependencies else [],
157
+ 'optional': json.loads(optional_dependencies) if optional_dependencies else [],
158
+ 'pip': json.loads(pip_dependencies) if pip_dependencies else []
159
+ }
160
+ }
161
+ }
162
+ return modules_info
163
+
164
+ def set_module(self, module_name, module_info):
165
+ with sqlite3.connect(self.db_path) as conn:
166
+ cursor = conn.cursor()
167
+ meta = module_info.get('info', {}).get('meta', {})
168
+ dependencies = module_info.get('info', {}).get('dependencies', {})
169
+ cursor.execute("""
170
+ INSERT OR REPLACE INTO modules (
171
+ module_name, status, version, description, author,
172
+ dependencies, optional_dependencies, pip_dependencies
173
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
174
+ """, (
175
+ module_name,
176
+ int(module_info.get('status', True)),
177
+ meta.get('version', ''),
178
+ meta.get('description', ''),
179
+ meta.get('author', ''),
180
+ json.dumps(dependencies.get('requires', [])),
181
+ json.dumps(dependencies.get('optional', [])),
182
+ json.dumps(dependencies.get('pip', []))
183
+ ))
184
+ conn.commit()
185
+
186
+ def get_module(self, module_name):
187
+ with sqlite3.connect(self.db_path) as conn:
188
+ cursor = conn.cursor()
189
+ cursor.execute("SELECT * FROM modules WHERE module_name = ?", (module_name,))
190
+ row = cursor.fetchone()
191
+ if row:
192
+ module_name, status, version, description, author, dependencies, optional_dependencies, pip_dependencies = row
193
+ return {
194
+ 'status': bool(status),
195
+ 'info': {
196
+ 'meta': {
197
+ 'version': version,
198
+ 'description': description,
199
+ 'author': author,
200
+ 'pip_dependencies': json.loads(pip_dependencies) if pip_dependencies else []
201
+ },
202
+ 'dependencies': {
203
+ 'requires': json.loads(dependencies) if dependencies else [],
204
+ 'optional': json.loads(optional_dependencies) if optional_dependencies else [],
205
+ 'pip': json.loads(pip_dependencies) if pip_dependencies else []
206
+ }
207
+ }
208
+ }
209
+ return None
210
+
211
+ def update_module(self, module_name, module_info):
212
+ self.set_module(module_name, module_info)
213
+
214
+ def remove_module(self, module_name):
215
+ with sqlite3.connect(self.db_path) as conn:
216
+ cursor = conn.cursor()
217
+ cursor.execute("DELETE FROM modules WHERE module_name = ?", (module_name,))
218
+ conn.commit()
219
+ return cursor.rowcount > 0
220
+
221
+ def __getattr__(self, key):
222
+ try:
223
+ return self.get(key)
224
+ except KeyError:
225
+ raise AttributeError(f"配置项 {key} 不存在")
226
+
227
+ env = EnvManager()
ErisPulse/logger.py CHANGED
@@ -1,48 +1,152 @@
1
- import logging
2
- import inspect
3
- from .envManager import env
4
-
5
- _logger = logging.getLogger("RyhBot")
6
- _log_level = env.get("LOG_LEVEL", "DEBUG")
7
- if _log_level is None:
8
- _log_level = logging.DEBUG
9
- _logger.setLevel(_log_level)
10
-
11
- if not _logger.handlers:
12
- console_handler = logging.StreamHandler()
13
- console_handler.setFormatter(logging.Formatter("%(message)s"))
14
- _logger.addHandler(console_handler)
15
-
16
- def _get_caller():
17
- frame = inspect.currentframe().f_back.f_back
18
- module = inspect.getmodule(frame)
19
- module_name = module.__name__
20
- if module_name == "__main__":
21
- module_name = "Main"
22
- if module_name.endswith(".Core"):
23
- module_name = module_name[:-5]
24
- return module_name
25
-
26
- def debug(msg, *args, **kwargs):
27
- caller_module = _get_caller()
28
- _logger.debug(f"[{caller_module}] {msg}", *args, **kwargs)
29
-
30
-
31
- def info(msg, *args, **kwargs):
32
- caller_module = _get_caller()
33
- _logger.info(f"[{caller_module}] {msg}", *args, **kwargs)
34
-
35
-
36
- def warning(msg, *args, **kwargs):
37
- caller_module = _get_caller()
38
- _logger.warning(f"[{caller_module}] {msg}", *args, **kwargs)
39
-
40
-
41
- def error(msg, *args, **kwargs):
42
- caller_module = _get_caller()
43
- _logger.error(f"[{caller_module}] {msg}", *args, **kwargs)
44
-
45
-
46
- def critical(msg, *args, **kwargs):
47
- caller_module = _get_caller()
48
- _logger.critical(f"[{caller_module}] {msg}", *args, **kwargs)
1
+ import logging
2
+ import inspect
3
+ import datetime
4
+ import functools
5
+
6
+ class Logger:
7
+ def __init__(self):
8
+ self._logs = {}
9
+ self._module_levels = {}
10
+ self._logger = logging.getLogger("ErisPulse")
11
+ self._logger.setLevel(logging.DEBUG)
12
+ self._file_handler = None
13
+ if not self._logger.handlers:
14
+ console_handler = logging.StreamHandler()
15
+ console_handler.setFormatter(logging.Formatter("%(message)s"))
16
+ self._logger.addHandler(console_handler)
17
+
18
+ def set_level(self, level: str):
19
+ level = level.upper()
20
+ if hasattr(logging, level):
21
+ self._logger.setLevel(getattr(logging, level))
22
+
23
+ def set_module_level(self, module_name: str, level: str) -> bool:
24
+ from .db import env
25
+ if not env.get_module_status(module_name):
26
+ self._logger.warning(f"模块 {module_name} 未启用,无法设置日志等级。")
27
+ return False
28
+ level = level.upper()
29
+ if hasattr(logging, level):
30
+ self._module_levels[module_name] = getattr(logging, level)
31
+ self._logger.info(f"模块 {module_name} 日志等级已设置为 {level}")
32
+ return True
33
+ else:
34
+ self._logger.error(f"无效的日志等级: {level}")
35
+ return False
36
+
37
+ def set_output_file(self, path: str | list):
38
+ if self._file_handler:
39
+ self._logger.removeHandler(self._file_handler)
40
+ self._file_handler.close()
41
+
42
+ if isinstance(path, str):
43
+ path = [path]
44
+
45
+ for p in path:
46
+ try:
47
+ file_handler = logging.FileHandler(p, encoding='utf-8')
48
+ file_handler.setFormatter(logging.Formatter("%(message)s"))
49
+ self._logger.addHandler(file_handler)
50
+ self._logger.info(f"日志输出已设置到文件: {p}")
51
+ except Exception as e:
52
+ self._logger.error(f"无法设置日志文件 {p}: {e}")
53
+ raise e
54
+
55
+ def save_logs(self, path: str | list):
56
+ if self._logs == None:
57
+ self._logger.warning("没有log记录可供保存。")
58
+ return
59
+ if isinstance(path, str):
60
+ path = [path]
61
+
62
+ for p in path:
63
+ try:
64
+ with open(p, "w", encoding="utf-8") as file:
65
+ for module, logs in self._logs.items():
66
+ file.write(f"Module: {module}\n")
67
+ for log in logs:
68
+ file.write(f" {log}\n")
69
+ self._logger.info(f"日志已被保存到:{p}。")
70
+ except Exception as e:
71
+ self._logger.error(f"无法保存日志到 {p}: {e}。")
72
+ raise e
73
+
74
+ def catch(self, func_or_level=None, level="error"):
75
+ if isinstance(func_or_level, str):
76
+ return lambda func: self.catch(func, level=func_or_level)
77
+ if func_or_level is None:
78
+ return lambda func: self.catch(func, level=level)
79
+ func = func_or_level
80
+
81
+ @functools.wraps(func)
82
+ def wrapper(*args, **kwargs):
83
+ try:
84
+ return func(*args, **kwargs)
85
+ except Exception as e:
86
+ import traceback
87
+ error_info = traceback.format_exc()
88
+
89
+ module_name = func.__module__
90
+ if module_name == "__main__":
91
+ module_name = "Main"
92
+ func_name = func.__name__
93
+
94
+ error_msg = f"Exception in {func_name}: {str(e)}\n{error_info}"
95
+
96
+ log_method = getattr(self, level, self.error)
97
+ log_method(error_msg)
98
+
99
+ return None
100
+ return wrapper
101
+
102
+ def _save_in_memory(self, ModuleName, msg):
103
+ if ModuleName not in self._logs:
104
+ self._logs[ModuleName] = []
105
+ timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
106
+ msg = f"{timestamp} - {msg}"
107
+ self._logs[ModuleName].append(msg)
108
+
109
+ def _get_effective_level(self, module_name):
110
+ return self._module_levels.get(module_name, self._logger.level)
111
+
112
+ def _get_caller(self):
113
+ frame = inspect.currentframe().f_back.f_back
114
+ module = inspect.getmodule(frame)
115
+ module_name = module.__name__
116
+ if module_name == "__main__":
117
+ module_name = "Main"
118
+ if module_name.endswith(".Core"):
119
+ module_name = module_name[:-5]
120
+ return module_name
121
+
122
+ def debug(self, msg, *args, **kwargs):
123
+ caller_module = self._get_caller()
124
+ if self._get_effective_level(caller_module) <= logging.DEBUG:
125
+ self._save_in_memory(caller_module, msg)
126
+ self._logger.debug(f"[{caller_module}] {msg}", *args, **kwargs)
127
+
128
+ def info(self, msg, *args, **kwargs):
129
+ caller_module = self._get_caller()
130
+ if self._get_effective_level(caller_module) <= logging.INFO:
131
+ self._save_in_memory(caller_module, msg)
132
+ self._logger.info(f"[{caller_module}] {msg}", *args, **kwargs)
133
+
134
+ def warning(self, msg, *args, **kwargs):
135
+ caller_module = self._get_caller()
136
+ if self._get_effective_level(caller_module) <= logging.WARNING:
137
+ self._save_in_memory(caller_module, msg)
138
+ self._logger.warning(f"[{caller_module}] {msg}", *args, **kwargs)
139
+
140
+ def error(self, msg, *args, **kwargs):
141
+ caller_module = self._get_caller()
142
+ if self._get_effective_level(caller_module) <= logging.ERROR:
143
+ self._save_in_memory(caller_module, msg)
144
+ self._logger.error(f"[{caller_module}] {msg}", *args, **kwargs)
145
+
146
+ def critical(self, msg, *args, **kwargs):
147
+ caller_module = self._get_caller()
148
+ if self._get_effective_level(caller_module) <= logging.CRITICAL:
149
+ self._save_in_memory(caller_module, msg)
150
+ self._logger.critical(f"[{caller_module}] {msg}", *args, **kwargs)
151
+
152
+ logger = Logger()