logger-36 2025.20__py3-none-any.whl → 2025.22__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.
- logger_36/catalog/config/optional.py +10 -1
- logger_36/catalog/handler/console.py +1 -1
- logger_36/catalog/handler/console_rich.py +2 -2
- logger_36/catalog/handler/file.py +1 -1
- logger_36/catalog/handler/generic.py +7 -7
- logger_36/constant/record.py +4 -1
- logger_36/type/handler.py +7 -7
- logger_36/type/logger.py +165 -91
- logger_36/version.py +1 -1
- {logger_36-2025.20.dist-info → logger_36-2025.22.dist-info}/METADATA +1 -1
- {logger_36-2025.20.dist-info → logger_36-2025.22.dist-info}/RECORD +13 -13
- {logger_36-2025.20.dist-info → logger_36-2025.22.dist-info}/WHEEL +0 -0
- {logger_36-2025.20.dist-info → logger_36-2025.22.dist-info}/top_level.txt +0 -0
@@ -8,11 +8,20 @@ try:
|
|
8
8
|
import rich # noqa
|
9
9
|
except ModuleNotFoundError:
|
10
10
|
RICH_IS_AVAILABLE = False
|
11
|
-
from logger_36.constant.error import MISSING_RICH_MESSAGE
|
11
|
+
from logger_36.constant.error import MISSING_RICH_MESSAGE # noqa
|
12
12
|
else:
|
13
13
|
RICH_IS_AVAILABLE = True
|
14
14
|
MISSING_RICH_MESSAGE = None
|
15
15
|
|
16
|
+
from logger_36.task.measure.memory import CanCheckUsage as CanCheckMemoryUsage
|
17
|
+
|
18
|
+
if CanCheckMemoryUsage():
|
19
|
+
MEMORY_MEASURE_IS_AVAILABLE = True
|
20
|
+
MEMORY_MEASURE_ERROR = None
|
21
|
+
else:
|
22
|
+
MEMORY_MEASURE_IS_AVAILABLE = False
|
23
|
+
from logger_36.constant.error import MEMORY_MEASURE_ERROR # noqa
|
24
|
+
|
16
25
|
"""
|
17
26
|
COPYRIGHT NOTICE
|
18
27
|
|
@@ -96,7 +96,7 @@ class console_rich_handler_t(base_t):
|
|
96
96
|
""""""
|
97
97
|
return cls(name, message_width, level, kwargs)
|
98
98
|
|
99
|
-
def Rule(self, text: str | None
|
99
|
+
def Rule(self, /, *, text: str | None = None, color: str = "black") -> str | rule_t:
|
100
100
|
""""""
|
101
101
|
if text is None:
|
102
102
|
return rule_t(style=color)
|
@@ -116,7 +116,7 @@ class console_rich_handler_t(base_t):
|
|
116
116
|
self.console.print(message, crop=False, overflow="ignore")
|
117
117
|
self._log_parity = not self._log_parity
|
118
118
|
|
119
|
-
def
|
119
|
+
def EmitMessage(self, message: str | renderable_t, /) -> None:
|
120
120
|
""""""
|
121
121
|
self.console.print(message, crop=False, overflow="ignore")
|
122
122
|
|
@@ -32,7 +32,7 @@ class file_handler_t(base_t):
|
|
32
32
|
self.stream.write(output[0] + "\n")
|
33
33
|
self.stream.flush()
|
34
34
|
|
35
|
-
def
|
35
|
+
def EmitMessage(self, message: str, /) -> None:
|
36
36
|
""""""
|
37
37
|
self.stream.write(message + "\n")
|
38
38
|
self.stream.flush()
|
@@ -38,10 +38,10 @@ class generic_handler_t(base_t):
|
|
38
38
|
self, name: str | None, message_width: int, level: int, kwargs
|
39
39
|
) -> None:
|
40
40
|
"""
|
41
|
-
|
41
|
+
EmitMessage: By definition, the generic handler does not know how to output
|
42
42
|
messages. If not passed, it defaults to output-ing messages in the console.
|
43
43
|
"""
|
44
|
-
|
44
|
+
EmitMessage = kwargs.pop(base_t.EmitMessage.__name__, None)
|
45
45
|
alternating_logs = kwargs.pop("alternating_logs", 0)
|
46
46
|
supports_html = kwargs.pop("supports_html", False)
|
47
47
|
|
@@ -49,8 +49,8 @@ class generic_handler_t(base_t):
|
|
49
49
|
|
50
50
|
base_t.__init__(self, name, message_width, None, level, kwargs)
|
51
51
|
|
52
|
-
if
|
53
|
-
self.
|
52
|
+
if EmitMessage is not None:
|
53
|
+
self.EmitMessage = EmitMessage
|
54
54
|
self.is_rich = False
|
55
55
|
self.console = None # console_t | None.
|
56
56
|
self.console_options = None # rich.console.ConsoleOptions | None.
|
@@ -82,14 +82,14 @@ class generic_handler_t(base_t):
|
|
82
82
|
""""""
|
83
83
|
return cls(name, message_width, level, kwargs)
|
84
84
|
|
85
|
-
def Rule(self, text: str | None
|
85
|
+
def Rule(self, /, *, text: str | None = None, color: str = "black") -> str | rule_t:
|
86
86
|
""""""
|
87
87
|
if self.is_rich:
|
88
88
|
if text is None:
|
89
89
|
return rule_t(style=color)
|
90
90
|
return rule_t(title=text_t(text, style=f"bold {color}"), style=color)
|
91
91
|
|
92
|
-
return base_t.Rule(self, text, color=color)
|
92
|
+
return base_t.Rule(self, text=text, color=color)
|
93
93
|
|
94
94
|
def emit(self, record: l.LogRecord, /) -> None:
|
95
95
|
""""""
|
@@ -131,7 +131,7 @@ class generic_handler_t(base_t):
|
|
131
131
|
else:
|
132
132
|
message = self.MessageFromRecord(record)[0]
|
133
133
|
|
134
|
-
self.
|
134
|
+
self.EmitMessage(message)
|
135
135
|
self._log_parity = not self._log_parity
|
136
136
|
|
137
137
|
|
logger_36/constant/record.py
CHANGED
@@ -4,8 +4,11 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
|
|
4
4
|
SEE COPYRIGHT NOTICE BELOW
|
5
5
|
"""
|
6
6
|
|
7
|
-
|
7
|
+
INTERNAL_INFO_ATTR = "internal_info"
|
8
8
|
SHOW_WHERE_ATTR = "should_show_where"
|
9
|
+
SHOW_W_RULE_ATTR = "should_show_w_rule"
|
10
|
+
WHEN_OR_ELAPSED_ATTR = "when_or_elapsed"
|
11
|
+
WHERE_ATTR = "where"
|
9
12
|
|
10
13
|
"""
|
11
14
|
COPYRIGHT NOTICE
|
logger_36/type/handler.py
CHANGED
@@ -16,7 +16,7 @@ from logger_36.config.message import (
|
|
16
16
|
WHERE_SEPARATOR,
|
17
17
|
)
|
18
18
|
from logger_36.constant.message import NEXT_LINE_PROLOGUE
|
19
|
-
from logger_36.constant.record import SHOW_W_RULE_ATTR
|
19
|
+
from logger_36.constant.record import SHOW_W_RULE_ATTR, WHEN_OR_ELAPSED_ATTR, WHERE_ATTR
|
20
20
|
from logger_36.constant.rule import (
|
21
21
|
DEFAULT_RULE,
|
22
22
|
DEFAULT_RULE_LENGTH,
|
@@ -66,7 +66,7 @@ class extension_t:
|
|
66
66
|
message = self.PreProcessedMessage(message)
|
67
67
|
|
68
68
|
if hasattr(record, SHOW_W_RULE_ATTR):
|
69
|
-
return self.Rule(message, color=rule_color), False
|
69
|
+
return self.Rule(text=message, color=rule_color), False
|
70
70
|
|
71
71
|
if (self.message_width <= 0) or (message.__len__() <= self.message_width):
|
72
72
|
if "\n" in message:
|
@@ -78,11 +78,11 @@ class extension_t:
|
|
78
78
|
lines = WrappedLines([message], self.message_width)
|
79
79
|
message = NEXT_LINE_PROLOGUE.join(lines)
|
80
80
|
|
81
|
-
when_or_elapsed = getattr(record,
|
81
|
+
when_or_elapsed = getattr(record, WHEN_OR_ELAPSED_ATTR, None)
|
82
82
|
if when_or_elapsed is None:
|
83
83
|
return message, True
|
84
84
|
|
85
|
-
if (where := getattr(record,
|
85
|
+
if (where := getattr(record, WHERE_ATTR, None)) is None:
|
86
86
|
where = ""
|
87
87
|
else:
|
88
88
|
where = f"{NEXT_LINE_PROLOGUE}{WHERE_SEPARATOR} {where}"
|
@@ -93,7 +93,7 @@ class extension_t:
|
|
93
93
|
f"{MESSAGE_MARKER} {message}{where}"
|
94
94
|
), True
|
95
95
|
|
96
|
-
def Rule(self, text: str | None
|
96
|
+
def Rule(self, /, *, text: str | None = None, color: str = "black") -> str | h.Any:
|
97
97
|
"""
|
98
98
|
Return type hint h.Any: For Rich, for example.
|
99
99
|
"""
|
@@ -113,13 +113,13 @@ class extension_t:
|
|
113
113
|
|
114
114
|
return f"{half_rule} {text} {half_rule}"
|
115
115
|
|
116
|
-
def
|
116
|
+
def EmitMessage(self, message: str, /) -> None:
|
117
117
|
""""""
|
118
118
|
raise NotImplementedError
|
119
119
|
|
120
120
|
def EmitRule(self, /, *, text: str | None = None, color: str = "black") -> None:
|
121
121
|
""""""
|
122
|
-
self.
|
122
|
+
self.EmitMessage(self.Rule(text=text, color=color))
|
123
123
|
|
124
124
|
|
125
125
|
class handler_t(l.Handler, extension_t):
|
logger_36/type/logger.py
CHANGED
@@ -19,7 +19,12 @@ from os import sep as FOLDER_SEPARATOR
|
|
19
19
|
from pathlib import Path as path_t
|
20
20
|
from traceback import TracebackException as traceback_t
|
21
21
|
|
22
|
-
from logger_36.catalog.config.optional import
|
22
|
+
from logger_36.catalog.config.optional import (
|
23
|
+
MEMORY_MEASURE_ERROR,
|
24
|
+
MEMORY_MEASURE_IS_AVAILABLE,
|
25
|
+
MISSING_RICH_MESSAGE,
|
26
|
+
RICH_IS_AVAILABLE,
|
27
|
+
)
|
23
28
|
from logger_36.catalog.handler.console import console_handler_t
|
24
29
|
from logger_36.catalog.handler.file import file_handler_t
|
25
30
|
from logger_36.config.issue import ISSUE_CONTEXT_END, ISSUE_CONTEXT_SEPARATOR
|
@@ -30,17 +35,19 @@ from logger_36.config.message import (
|
|
30
35
|
TIME_FORMAT,
|
31
36
|
WHERE_SEPARATOR,
|
32
37
|
)
|
33
|
-
from logger_36.constant.error import MEMORY_MEASURE_ERROR
|
34
38
|
from logger_36.constant.generic import NOT_PASSED
|
35
39
|
from logger_36.constant.issue import ISSUE_LEVEL_SEPARATOR, ORDER, order_h
|
36
40
|
from logger_36.constant.logger import WARNING_LOGGER_NAME, WARNING_TYPE_COMPILED_PATTERN
|
37
41
|
from logger_36.constant.memory import UNKNOWN_MEMORY_USAGE
|
38
42
|
from logger_36.constant.message import LINE_INDENT, TIME_LENGTH_m_1, expected_op_h
|
39
43
|
from logger_36.constant.path import PROJECT_FILE_RELATIVE, USER_FOLDER
|
40
|
-
from logger_36.constant.record import
|
44
|
+
from logger_36.constant.record import (
|
45
|
+
INTERNAL_INFO_ATTR,
|
46
|
+
SHOW_W_RULE_ATTR,
|
47
|
+
SHOW_WHERE_ATTR,
|
48
|
+
)
|
41
49
|
from logger_36.task.format.message import MessageWithActualExpected
|
42
50
|
from logger_36.task.measure.chronos import ElapsedTime
|
43
|
-
from logger_36.task.measure.memory import CanCheckUsage as CanCheckMemoryUsage
|
44
51
|
from logger_36.task.measure.memory import CurrentUsage as CurrentMemoryUsage
|
45
52
|
from logger_36.type.handler import any_handler_t as base_handler_t
|
46
53
|
from logger_36.type.handler import extension_t as handler_extension_t
|
@@ -61,7 +68,6 @@ logger_handle_h = logger_handle_raw_h | logger_handle_with_self_h
|
|
61
68
|
|
62
69
|
_DATE_TIME_ORIGIN = date_time_t.fromtimestamp(1970, None)
|
63
70
|
_DATE_ORIGIN = _DATE_TIME_ORIGIN.date()
|
64
|
-
_MEMORY_MEASURE_ERROR = MEMORY_MEASURE_ERROR
|
65
71
|
|
66
72
|
|
67
73
|
@d.dataclass(slots=True, repr=False, eq=False)
|
@@ -70,20 +76,21 @@ class logger_t(base_t):
|
|
70
76
|
intercepted_wrn_handle: When warning interception is on, this stores the original
|
71
77
|
"handle" method of the Python warning logger.
|
72
78
|
|
73
|
-
_should_activate_log_interceptions: Loggers instantiated after a logger_t logger
|
74
|
-
be missed by an early call of ToggleLogInterceptions. Therefore, passing True
|
75
|
-
activate_log_interceptions only sets _should_activate_log_interceptions to True,
|
79
|
+
_should_activate_log_interceptions: Loggers instantiated after a logger_t logger
|
80
|
+
will be missed by an early call of ToggleLogInterceptions. Therefore, passing True
|
81
|
+
for activate_log_interceptions only sets _should_activate_log_interceptions to True,
|
76
82
|
which is later checked in AddHandler to effectively call ToggleLogInterceptions if
|
77
|
-
|
78
|
-
added is the last one).
|
83
|
+
_warming_up is False (which normally indicates that the handler about to
|
84
|
+
be added is the last one).
|
79
85
|
|
80
|
-
|
86
|
+
_warming_up: Must not be False until at least one handler has been added.
|
81
87
|
"""
|
82
88
|
|
83
89
|
should_record_messages: bool = False
|
84
|
-
|
90
|
+
should_monitor_memory_usage: bool = False
|
85
91
|
exit_on_error: bool = False # Implies exit_on_critical.
|
86
92
|
exit_on_critical: bool = False
|
93
|
+
verbose: bool = False
|
87
94
|
|
88
95
|
events: dict[int, int] = d.field(init=False, default_factory=dict)
|
89
96
|
recorded: list[tuple[int, str]] = d.field(init=False, default_factory=list)
|
@@ -98,11 +105,13 @@ class logger_t(base_t):
|
|
98
105
|
init=False, default_factory=dict
|
99
106
|
)
|
100
107
|
intercepts_exceptions: bool = d.field(init=False, default=False)
|
101
|
-
_should_hold_messages: bool = d.field(init=False, default=True)
|
102
|
-
_should_activate_log_interceptions: bool = d.field(init=False, default=False)
|
103
|
-
_on_hold: list[l.LogRecord] = d.field(init=False, default_factory=list)
|
104
108
|
_recording_handler: handler_extension_t | None = d.field(init=False, default=None)
|
105
109
|
|
110
|
+
# Used only until the last handler is added (see AddHandler).
|
111
|
+
_should_activate_log_interceptions: bool = d.field(init=False, default=False)
|
112
|
+
_warming_up: bool = d.field(init=False, default=True)
|
113
|
+
_on_hold: list[l.LogRecord] | None = d.field(init=False, default_factory=list)
|
114
|
+
|
106
115
|
name_: d.InitVar[str | None] = None
|
107
116
|
level_: d.InitVar[int] = l.NOTSET
|
108
117
|
activate_wrn_interceptions: d.InitVar[bool] = True
|
@@ -156,21 +165,28 @@ class logger_t(base_t):
|
|
156
165
|
activate_exc_interceptions: bool,
|
157
166
|
) -> None:
|
158
167
|
""""""
|
159
|
-
global _MEMORY_MEASURE_ERROR
|
160
|
-
|
161
168
|
if name_ is None:
|
162
169
|
name_ = f"{type(self).__name__}:{hex(id(self))[2:]}"
|
163
170
|
|
171
|
+
self.handle = self._HandleWarmUp
|
164
172
|
base_t.__init__(self, name_)
|
165
173
|
self.setLevel(level_)
|
166
174
|
self.propagate = False # Part of base_t.
|
167
175
|
|
168
|
-
if self.
|
169
|
-
self.
|
176
|
+
if self.exit_on_error:
|
177
|
+
self.exit_on_critical = True
|
170
178
|
|
171
179
|
for level_id in l.getLevelNamesMapping().values():
|
172
180
|
self.events[level_id] = 0
|
173
181
|
|
182
|
+
if self.should_record_messages:
|
183
|
+
self.ActivateMessageRecording()
|
184
|
+
|
185
|
+
self.info(
|
186
|
+
f'New logger "{self.name}" for "{PROJECT_FILE_RELATIVE}"',
|
187
|
+
extra={INTERNAL_INFO_ATTR: True},
|
188
|
+
)
|
189
|
+
|
174
190
|
if activate_wrn_interceptions:
|
175
191
|
self.ToggleWarningInterceptions(True)
|
176
192
|
if activate_log_interceptions:
|
@@ -178,23 +194,33 @@ class logger_t(base_t):
|
|
178
194
|
if activate_exc_interceptions:
|
179
195
|
self.ToggleExceptionInterceptions(True)
|
180
196
|
|
181
|
-
if self.
|
182
|
-
self.
|
197
|
+
if self.should_monitor_memory_usage:
|
198
|
+
self.ActivateMemoryUsageMonitoring()
|
183
199
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
200
|
+
def _HandleWarmUp(self, record: l.LogRecord, /) -> None:
|
201
|
+
""""""
|
202
|
+
now = ElapsedTime(should_return_now=True)[1]
|
203
|
+
if (date := now.date()) != self.last_message_date:
|
204
|
+
self._AcknowledgeDateChange(date)
|
205
|
+
|
206
|
+
# When.
|
207
|
+
record.when_or_elapsed = (TIME_LENGTH_m_1 + 1) * "."
|
208
|
+
# Where.
|
209
|
+
if record.levelno != l.INFO:
|
210
|
+
_ = _RecordLocation(record, True)
|
211
|
+
# What.
|
212
|
+
if not isinstance(record.msg, str):
|
213
|
+
record.msg = str(record.msg)
|
189
214
|
|
190
|
-
self.
|
215
|
+
self._on_hold.append(record)
|
191
216
|
|
192
|
-
def
|
217
|
+
def _HandleRoutine(self, record: l.LogRecord, /) -> None:
|
193
218
|
""""""
|
194
|
-
|
219
|
+
is_internal_info = getattr(record, INTERNAL_INFO_ATTR, False)
|
220
|
+
if is_internal_info and not self.verbose:
|
221
|
+
return
|
195
222
|
|
196
|
-
|
197
|
-
self._FlushRecordsOnHold()
|
223
|
+
elapsed_time, now = ElapsedTime(should_return_now=True)
|
198
224
|
|
199
225
|
if (date := now.date()) != self.last_message_date:
|
200
226
|
self._AcknowledgeDateChange(date)
|
@@ -209,19 +235,8 @@ class logger_t(base_t):
|
|
209
235
|
|
210
236
|
# Where.
|
211
237
|
should_show_where = getattr(record, SHOW_WHERE_ATTR, record.levelno != l.INFO)
|
212
|
-
if should_show_where or self.
|
213
|
-
|
214
|
-
for path in s.path:
|
215
|
-
if module.is_relative_to(path):
|
216
|
-
module = module.relative_to(path).with_suffix("")
|
217
|
-
module = str(module).replace(FOLDER_SEPARATOR, ".")
|
218
|
-
break
|
219
|
-
else:
|
220
|
-
if module.is_relative_to(USER_FOLDER):
|
221
|
-
module = module.relative_to(USER_FOLDER)
|
222
|
-
where = f"{module}:{record.funcName}:{record.lineno}"
|
223
|
-
if should_show_where:
|
224
|
-
record.where = where
|
238
|
+
if should_show_where or self.should_monitor_memory_usage:
|
239
|
+
where = _RecordLocation(record, should_show_where)
|
225
240
|
else:
|
226
241
|
where = None
|
227
242
|
|
@@ -229,13 +244,9 @@ class logger_t(base_t):
|
|
229
244
|
if not isinstance(record.msg, str):
|
230
245
|
record.msg = str(record.msg)
|
231
246
|
|
232
|
-
|
233
|
-
self._on_hold.append(record)
|
234
|
-
else:
|
235
|
-
self._HandleRecord(record)
|
236
|
-
self.events[record.levelno] += 1
|
247
|
+
self._HandleRaw(record)
|
237
248
|
|
238
|
-
if self.
|
249
|
+
if self.should_monitor_memory_usage:
|
239
250
|
self.memory_usages.append((where, CurrentMemoryUsage()))
|
240
251
|
|
241
252
|
if (self.exit_on_critical and (record.levelno is l.CRITICAL)) or (
|
@@ -245,12 +256,28 @@ class logger_t(base_t):
|
|
245
256
|
# __post_init__ set self.exit_on_critical if self.exit_on_error.
|
246
257
|
s.exit(1)
|
247
258
|
|
248
|
-
def
|
259
|
+
def _HandleRaw(self, record: l.LogRecord, /) -> None:
|
249
260
|
""""""
|
261
|
+
if self.should_record_messages:
|
262
|
+
message = self._recording_handler.MessageFromRecord(record)[0]
|
263
|
+
self.recorded.append((record.levelno, message))
|
264
|
+
|
265
|
+
base_t.handle(self, record)
|
266
|
+
self.events[record.levelno] += 1
|
267
|
+
|
268
|
+
def _FlushRecordsOnHold(self) -> None:
|
269
|
+
"""
|
270
|
+
should_record_messages and verbose must have been set by now.
|
271
|
+
"""
|
250
272
|
for held in self._on_hold:
|
251
|
-
self.
|
273
|
+
if self.verbose or not getattr(held, INTERNAL_INFO_ATTR, False):
|
274
|
+
self._HandleRaw(held)
|
252
275
|
|
253
276
|
self._on_hold.clear()
|
277
|
+
self._on_hold = None
|
278
|
+
self._warming_up = False
|
279
|
+
|
280
|
+
self.handle = self._HandleRoutine
|
254
281
|
|
255
282
|
def _AcknowledgeDateChange(self, date: date_t, /) -> None:
|
256
283
|
""""""
|
@@ -265,24 +292,32 @@ class logger_t(base_t):
|
|
265
292
|
}
|
266
293
|
)
|
267
294
|
|
268
|
-
if self.
|
295
|
+
if self._warming_up:
|
269
296
|
self._on_hold.append(record)
|
270
297
|
else:
|
271
|
-
self.
|
272
|
-
|
273
|
-
def _HandleRecord(self, record: l.LogRecord, /) -> None:
|
274
|
-
""""""
|
275
|
-
if self.should_record_messages:
|
276
|
-
message = self._recording_handler.MessageFromRecord(record)[0]
|
277
|
-
self.recorded.append((record.levelno, message))
|
278
|
-
|
279
|
-
base_t.handle(self, record)
|
298
|
+
self._HandleRaw(record)
|
280
299
|
|
281
300
|
def ActivateMessageRecording(self) -> None:
|
282
301
|
""""""
|
283
302
|
self._recording_handler = handler_extension_t("recording_handler", 0, None)
|
284
303
|
self.should_record_messages = True # Useless if called from __post_init__.
|
285
|
-
self.info(
|
304
|
+
self.info(
|
305
|
+
f'Message recording activated for logger "{self.name}"',
|
306
|
+
extra={INTERNAL_INFO_ATTR: True},
|
307
|
+
)
|
308
|
+
|
309
|
+
def ActivateMemoryUsageMonitoring(self) -> None:
|
310
|
+
""""""
|
311
|
+
if MEMORY_MEASURE_IS_AVAILABLE:
|
312
|
+
# Useless if called from __post_init__.
|
313
|
+
self.should_monitor_memory_usage = True
|
314
|
+
self.info(
|
315
|
+
f'Memory usage monitoring activated for logger "{self.name}"',
|
316
|
+
extra={INTERNAL_INFO_ATTR: True},
|
317
|
+
)
|
318
|
+
else:
|
319
|
+
self.should_monitor_memory_usage = False
|
320
|
+
self.error(MEMORY_MEASURE_ERROR)
|
286
321
|
|
287
322
|
def ResetEventCounts(self) -> None:
|
288
323
|
""""""
|
@@ -300,7 +335,7 @@ class logger_t(base_t):
|
|
300
335
|
logger.handle = t.MethodType(_HandleForWarnings(self), logger)
|
301
336
|
|
302
337
|
l.captureWarnings(True)
|
303
|
-
self.info("Warning Interception: ON")
|
338
|
+
self.info("Warning Interception: ON", extra={INTERNAL_INFO_ATTR: True})
|
304
339
|
else:
|
305
340
|
if not self.intercepts_warnings:
|
306
341
|
return
|
@@ -310,7 +345,7 @@ class logger_t(base_t):
|
|
310
345
|
self.intercepted_wrn_handle = None
|
311
346
|
|
312
347
|
l.captureWarnings(False)
|
313
|
-
self.info("Warning Interception: OFF")
|
348
|
+
self.info("Warning Interception: OFF", extra={INTERNAL_INFO_ATTR: True})
|
314
349
|
|
315
350
|
def ToggleLogInterceptions(self, state: bool, /) -> None:
|
316
351
|
""""""
|
@@ -334,7 +369,10 @@ class logger_t(base_t):
|
|
334
369
|
intercepted = sorted(self.intercepted_log_handles.keys())
|
335
370
|
if intercepted.__len__() > 0:
|
336
371
|
as_str = ", ".join(intercepted)
|
337
|
-
self.info(
|
372
|
+
self.info(
|
373
|
+
f"Now Intercepting LOGs from: {as_str}",
|
374
|
+
extra={INTERNAL_INFO_ATTR: True},
|
375
|
+
)
|
338
376
|
else:
|
339
377
|
if not self.intercepts_logs:
|
340
378
|
return
|
@@ -343,7 +381,7 @@ class logger_t(base_t):
|
|
343
381
|
logger = l.getLogger(name)
|
344
382
|
logger.handle = handle
|
345
383
|
self.intercepted_log_handles.clear()
|
346
|
-
self.info("Log Interception: OFF")
|
384
|
+
self.info("Log Interception: OFF", extra={INTERNAL_INFO_ATTR: True})
|
347
385
|
|
348
386
|
def ToggleExceptionInterceptions(self, state: bool, /) -> None:
|
349
387
|
""""""
|
@@ -354,7 +392,7 @@ class logger_t(base_t):
|
|
354
392
|
s.excepthook = self.DealWithException
|
355
393
|
thrd.excepthook = self.DealWithExceptionInThread
|
356
394
|
self.intercepts_exceptions = True
|
357
|
-
self.info("Exception Interception: ON")
|
395
|
+
self.info("Exception Interception: ON", extra={INTERNAL_INFO_ATTR: True})
|
358
396
|
else:
|
359
397
|
if not self.intercepts_exceptions:
|
360
398
|
return
|
@@ -362,7 +400,7 @@ class logger_t(base_t):
|
|
362
400
|
s.excepthook = s.__excepthook__
|
363
401
|
thrd.excepthook = thrd.__excepthook__
|
364
402
|
self.intercepts_exceptions = False
|
365
|
-
self.info("Exception Interception: OFF")
|
403
|
+
self.info("Exception Interception: OFF", extra={INTERNAL_INFO_ATTR: True})
|
366
404
|
|
367
405
|
def AddHandler(
|
368
406
|
self,
|
@@ -375,15 +413,21 @@ class logger_t(base_t):
|
|
375
413
|
name: str | None = None,
|
376
414
|
level: int = l.INFO,
|
377
415
|
message_width: int = -1,
|
378
|
-
|
416
|
+
this_is_last_handler: bool = True,
|
379
417
|
**kwargs,
|
380
418
|
) -> None:
|
381
|
-
"""
|
382
|
-
|
383
|
-
|
384
|
-
|
419
|
+
"""
|
420
|
+
Silently ignores re-holding request after un-holding.
|
421
|
+
"""
|
422
|
+
should_flush_on_hold = False
|
423
|
+
new_handler_warning = ""
|
424
|
+
if self._warming_up and this_is_last_handler:
|
425
|
+
if self._should_activate_log_interceptions:
|
426
|
+
self.ToggleLogInterceptions(True)
|
427
|
+
self._should_activate_log_interceptions = False
|
385
428
|
|
386
|
-
|
429
|
+
should_flush_on_hold = True
|
430
|
+
new_handler_warning = "\n(Handlers added from now on will miss above logs.)"
|
387
431
|
|
388
432
|
if isinstance(handler_t_or_handler, type):
|
389
433
|
handler = handler_t_or_handler.New(
|
@@ -393,13 +437,20 @@ class logger_t(base_t):
|
|
393
437
|
handler = handler_t_or_handler
|
394
438
|
base_t.addHandler(self, handler)
|
395
439
|
|
396
|
-
|
397
|
-
|
398
|
-
path
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
440
|
+
if self.verbose:
|
441
|
+
path = getattr(handler, "baseFilename", "")
|
442
|
+
if isinstance(path, path_t) or (path.__len__() > 0):
|
443
|
+
path = f"\nPath: {path}"
|
444
|
+
self.info(
|
445
|
+
f'New handler "{handler.name}" of type "{type(handler).__name__}" and '
|
446
|
+
f"level {handler.level}={l.getLevelName(handler.level)}{path}"
|
447
|
+
f"{new_handler_warning}",
|
448
|
+
extra={INTERNAL_INFO_ATTR: True},
|
449
|
+
)
|
450
|
+
|
451
|
+
# Wait until after the handler has been added to flush messages on hold.
|
452
|
+
if should_flush_on_hold:
|
453
|
+
self._FlushRecordsOnHold()
|
403
454
|
|
404
455
|
def MakeMonochrome(self) -> None:
|
405
456
|
""""""
|
@@ -407,13 +458,12 @@ class logger_t(base_t):
|
|
407
458
|
|
408
459
|
def MakeRich(self, *, alternating_logs: int = 0) -> None:
|
409
460
|
""""""
|
410
|
-
if
|
411
|
-
s.__stderr__.write(MISSING_RICH_MESSAGE + "\n")
|
412
|
-
|
413
|
-
if console_rich_handler_t is console_handler_t:
|
414
|
-
handler_kwargs = {}
|
415
|
-
else:
|
461
|
+
if RICH_IS_AVAILABLE:
|
416
462
|
handler_kwargs = {"alternating_logs": alternating_logs}
|
463
|
+
else:
|
464
|
+
handler_kwargs = {}
|
465
|
+
self.error(MISSING_RICH_MESSAGE)
|
466
|
+
|
417
467
|
self.AddHandler(console_rich_handler_t, **handler_kwargs)
|
418
468
|
|
419
469
|
def MakePermanent(self, path: str | path_t, /) -> None:
|
@@ -500,8 +550,11 @@ class logger_t(base_t):
|
|
500
550
|
message = text.indent(message, LINE_INDENT)
|
501
551
|
|
502
552
|
for handler in self.handlers:
|
503
|
-
|
504
|
-
|
553
|
+
EmitMessage = getattr(
|
554
|
+
handler, handler_extension_t.EmitMessage.__name__, None
|
555
|
+
)
|
556
|
+
if EmitMessage is not None:
|
557
|
+
EmitMessage(message)
|
505
558
|
|
506
559
|
info_raw = LogAsIs # To follow the convention of the logging methods info, error...
|
507
560
|
|
@@ -510,7 +563,8 @@ class logger_t(base_t):
|
|
510
563
|
) -> None:
|
511
564
|
""""""
|
512
565
|
for handler in self.handlers:
|
513
|
-
|
566
|
+
EmitRule = getattr(handler, handler_extension_t.EmitRule.__name__, None)
|
567
|
+
if EmitRule is not None:
|
514
568
|
EmitRule(text=message, color=color)
|
515
569
|
|
516
570
|
def AddContextLevel(self, new_level: str, /) -> None:
|
@@ -638,6 +692,26 @@ class logger_t(base_t):
|
|
638
692
|
return False
|
639
693
|
|
640
694
|
|
695
|
+
def _RecordLocation(record: l.LogRecord, should_also_store: bool, /) -> str:
|
696
|
+
""""""
|
697
|
+
module = path_t(record.pathname)
|
698
|
+
for path in s.path:
|
699
|
+
if module.is_relative_to(path):
|
700
|
+
module = module.relative_to(path).with_suffix("")
|
701
|
+
module = str(module).replace(FOLDER_SEPARATOR, ".")
|
702
|
+
break
|
703
|
+
else:
|
704
|
+
if module.is_relative_to(USER_FOLDER):
|
705
|
+
module = module.relative_to(USER_FOLDER)
|
706
|
+
|
707
|
+
output = f"{module}:{record.funcName}:{record.lineno}"
|
708
|
+
|
709
|
+
if should_also_store:
|
710
|
+
record.where = output
|
711
|
+
|
712
|
+
return output
|
713
|
+
|
714
|
+
|
641
715
|
def _HandleForWarnings(interceptor: base_t, /) -> logger_handle_h:
|
642
716
|
""""""
|
643
717
|
|
logger_36/version.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
logger_36/__init__.py,sha256=mK6AD0eWI2Sk42oxleTvsxzYJ28FbHK5WNkpLgAhnNE,2129
|
2
|
-
logger_36/version.py,sha256=
|
2
|
+
logger_36/version.py,sha256=WM8W-3pzA_JWd1DQWpdL-uJTAxV5u8_nbyWIlGaizjg,1680
|
3
3
|
logger_36/api/content.py,sha256=DuT4UX4r_1DTXzuuRD-tvsTZk5X-Nj11loBKhuWOMw0,1791
|
4
4
|
logger_36/api/gpu.py,sha256=NNs1IvQ7bh8Dppm8O8K2YLWbm4rogc3Ie_-D6xzkX3g,1726
|
5
5
|
logger_36/api/memory.py,sha256=vOY4cTTrC3u7L0OrKXdPNlsCahYjCrY4h7iqpGZv9kU,2217
|
@@ -8,11 +8,11 @@ logger_36/api/system.py,sha256=h-3GfhZPwawv0UKBWKkT1LzxSCZwpA2VIsy03lLYi6w,1725
|
|
8
8
|
logger_36/api/time.py,sha256=JG0vgzPSRZ7UWQyoihnVu4sjPC-okFIKA3ZyNh2GaZo,1798
|
9
9
|
logger_36/api/type.py,sha256=eLZ2yuH-sYeh4Z2KnAwTRJEbmkmgzBPMncdqXfFUTG8,1760
|
10
10
|
logger_36/catalog/config/console_rich.py,sha256=t9p9-AkSgPiLAsm1evAdbz77g7JcVLePhUJ1FzNi3cY,2330
|
11
|
-
logger_36/catalog/config/optional.py,sha256=
|
12
|
-
logger_36/catalog/handler/console.py,sha256=
|
13
|
-
logger_36/catalog/handler/console_rich.py,sha256=
|
14
|
-
logger_36/catalog/handler/file.py,sha256=
|
15
|
-
logger_36/catalog/handler/generic.py,sha256=
|
11
|
+
logger_36/catalog/config/optional.py,sha256=8d8HdpE07gHfsdoL8mVAlRlh9AgLcb4z7I7h6ob7CfU,2174
|
12
|
+
logger_36/catalog/handler/console.py,sha256=YEQN8fw7ra9w-5sJACNC4pktv9einm5ASP9TncU8TQo,2311
|
13
|
+
logger_36/catalog/handler/console_rich.py,sha256=gPpq8ij1ZFTXaLgISaCTXDDwv7uWPivLeq2ttpiuKlk,6190
|
14
|
+
logger_36/catalog/handler/file.py,sha256=yg8GnsV6AmDsx1R5iZlsK-5idqD733gc09Syl02TG7Y,2458
|
15
|
+
logger_36/catalog/handler/generic.py,sha256=L8mLc-iQlBWKBqEN3-wIKy2yk_TVgqIWYn_P1hXDsQA,6361
|
16
16
|
logger_36/catalog/logger/chronos.py,sha256=S4m9TMPQy_Ju500mpE1jNzu2gZG-QKdVuvX9RVRKHR8,1911
|
17
17
|
logger_36/catalog/logger/gpu.py,sha256=Py5YY0nD_pqJzJsEKQYoOGHcPqyNVJ3J2noOS3hDL6g,2890
|
18
18
|
logger_36/catalog/logger/memory.py,sha256=J0ZGKO7j1FZA_aDGxpABtvzDy1RjCDiDmWYh4U98fEI,4253
|
@@ -29,7 +29,7 @@ logger_36/constant/logger.py,sha256=ZQYX9JiPsoivwRgYNtdEqRKCagSKD88lRqvxP8MX1ZE,
|
|
29
29
|
logger_36/constant/memory.py,sha256=Q_E5tTWa-cGaNwrE_xmKa3BxQG6oJO6DHczrxc_M4sE,1817
|
30
30
|
logger_36/constant/message.py,sha256=YJOEzdI0ZjUOdHo3CsiS56FVPhrfNoQYvXuUkprH61g,2312
|
31
31
|
logger_36/constant/path.py,sha256=OfLh70Jyc8po9Ls34nQh_bRr3PXyQ3kF9ciR9QPhiqI,2213
|
32
|
-
logger_36/constant/record.py,sha256=
|
32
|
+
logger_36/constant/record.py,sha256=IGWnKA4TGv1oU6ezzNrGocZlB7Ie7nTr4l3IOtwdWOg,1833
|
33
33
|
logger_36/constant/rule.py,sha256=tBKQgPTt6G_p5eInDdWoEEAvQFz4WMSt5THsS5jvk14,1779
|
34
34
|
logger_36/constant/system.py,sha256=pLlLXG5sepQlSUOo3TphaGrHg8xzJBp-GxpL2NPP47k,1904
|
35
35
|
logger_36/extension/html_.py,sha256=W9SyiYsaaYHUrHLGAAN2wiJGXUlwOBJ5gzdjmEcnF18,3342
|
@@ -42,11 +42,11 @@ logger_36/task/format/memory.py,sha256=J1Oy3jw8wjSp2kuiRUm_VFpzXOHX2FOc7nuRrCyrs
|
|
42
42
|
logger_36/task/format/message.py,sha256=Rm6zymVEEGcgKfmxMPXP7q3PtwZJKlXGhqZ5tnvlwxA,3502
|
43
43
|
logger_36/task/measure/chronos.py,sha256=7ijMZgP4EP18HbLV2yCxpNpRS9724Wyk523f-nkbhUM,2529
|
44
44
|
logger_36/task/measure/memory.py,sha256=kkPHEIUTUhkCOLrAt01eLJLnsnkl0nFPNhFZdIB_JAw,1991
|
45
|
-
logger_36/type/handler.py,sha256=
|
45
|
+
logger_36/type/handler.py,sha256=4LCFZzI4OEH6lVBrBQ09ZIvF0nq-_j7OOVnujBDyDWA,6665
|
46
46
|
logger_36/type/issue.py,sha256=QHAYf7QgrjJUtF2D46z6X630qTgeP_0FE5hIwf54RsE,2688
|
47
|
-
logger_36/type/logger.py,sha256=
|
47
|
+
logger_36/type/logger.py,sha256=b2F21M5z1hwPdDsyHgBIlC06X9-_7zsjqyGEsVaIJgM,27536
|
48
48
|
logger_36/type/loggers.py,sha256=7EX7Sg_RlduBjdfFlNZmUfNeDloH1xU30Rdkg_-rXh8,3172
|
49
|
-
logger_36-2025.
|
50
|
-
logger_36-2025.
|
51
|
-
logger_36-2025.
|
52
|
-
logger_36-2025.
|
49
|
+
logger_36-2025.22.dist-info/METADATA,sha256=xcPkxJFWNYEIXgspK2VCcU4LbsME8hlmFQjASmR-3KM,6529
|
50
|
+
logger_36-2025.22.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
51
|
+
logger_36-2025.22.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
|
52
|
+
logger_36-2025.22.dist-info/RECORD,,
|
File without changes
|
File without changes
|