logger-36 2025.22__py3-none-any.whl → 2025.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.
@@ -0,0 +1,98 @@
1
+ """
2
+ Copyright CNRS (https://www.cnrs.fr/index.php/en)
3
+ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
4
+ SEE COPYRIGHT NOTICE BELOW
5
+ """
6
+
7
+ import json
8
+ import logging as l
9
+ import typing as h
10
+
11
+ from logger_36.type.handler import handler_t as base_t
12
+
13
+ formats_h = h.Literal["json", "message", "raw"]
14
+
15
+
16
+ class memory_handler_t(base_t):
17
+ def __init__(
18
+ self, name: str | None, message_width: int, level: int, format_: formats_h
19
+ ) -> None:
20
+ """"""
21
+ assert format_ in h.get_args(formats_h)
22
+
23
+ base_t.__init__(self, name, message_width, None, level)
24
+
25
+ self.format_ = format_
26
+ self.records = []
27
+
28
+ @classmethod
29
+ def New(
30
+ cls,
31
+ /,
32
+ *,
33
+ name: str | None = None,
34
+ message_width: int = -1,
35
+ level: int = l.NOTSET,
36
+ format_: formats_h = "message",
37
+ **_,
38
+ ) -> h.Self:
39
+ """"""
40
+ return cls(name, message_width, level, format_)
41
+
42
+ def emit(self, record: l.LogRecord, /) -> None:
43
+ """"""
44
+ level = record.levelno
45
+
46
+ if self.format_ == "raw":
47
+ is_not_a_rule = True
48
+ elif self.format_ == "message":
49
+ record, is_not_a_rule = self.MessageFromRecord(record)
50
+ else:
51
+ record = json.dumps(record.__dict__)
52
+ is_not_a_rule = True
53
+
54
+ self.records.append((level, record, is_not_a_rule))
55
+
56
+ def EmitMessage(self, message: str, /) -> None:
57
+ """"""
58
+ if self.format_ == "message":
59
+ message_key = "msg"
60
+ else:
61
+ message_key = "message"
62
+ record = l.makeLogRecord(
63
+ {"name": "<UNKNOWN LOGGER>", "levelno": l.INFO, message_key: message}
64
+ )
65
+ self.emit(record)
66
+
67
+
68
+ """
69
+ COPYRIGHT NOTICE
70
+
71
+ This software is governed by the CeCILL license under French law and
72
+ abiding by the rules of distribution of free software. You can use,
73
+ modify and/ or redistribute the software under the terms of the CeCILL
74
+ license as circulated by CEA, CNRS and INRIA at the following URL
75
+ "http://www.cecill.info".
76
+
77
+ As a counterpart to the access to the source code and rights to copy,
78
+ modify and redistribute granted by the license, users are provided only
79
+ with a limited warranty and the software's author, the holder of the
80
+ economic rights, and the successive licensors have only limited
81
+ liability.
82
+
83
+ In this respect, the user's attention is drawn to the risks associated
84
+ with loading, using, modifying and/or developing or reproducing the
85
+ software by the user in light of its specific status of free software,
86
+ that may mean that it is complicated to manipulate, and that also
87
+ therefore means that it is reserved for developers and experienced
88
+ professionals having in-depth computer knowledge. Users are therefore
89
+ encouraged to load and test the software's suitability as regards their
90
+ requirements in conditions enabling the security of their systems and/or
91
+ data to be ensured and, more generally, to use and operate it in the
92
+ same conditions as regards security.
93
+
94
+ The fact that you are presently reading this means that you have had
95
+ knowledge of the CeCILL license and that you accept its terms.
96
+
97
+ SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
98
+ """
@@ -4,7 +4,6 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
- INTERNAL_INFO_ATTR = "internal_info"
8
7
  SHOW_WHERE_ATTR = "should_show_where"
9
8
  SHOW_W_RULE_ATTR = "should_show_w_rule"
10
9
  WHEN_OR_ELAPSED_ATTR = "when_or_elapsed"
logger_36/task/storage.py CHANGED
@@ -10,25 +10,28 @@ from pathlib import Path as path_t
10
10
 
11
11
  from logger_36.constant.html import BODY_PLACEHOLDER, MINIMAL_HTML, TITLE_PLACEHOLDER
12
12
  from logger_36.instance.logger import L
13
+ from logger_36.type.logger import logger_t
13
14
 
14
15
 
15
- def SaveLOGasHTML(path: str | path_t | io_base_t | None = None) -> None:
16
+ def SaveLOGasHTML(
17
+ path: str | path_t | io_base_t | None = None, /, *, logger: logger_t = L
18
+ ) -> None:
16
19
  """
17
20
  From first console handler found.
18
21
  """
19
22
  cannot_save = "Cannot save logging record as HTML"
20
23
 
21
24
  if path is None:
22
- for handler in L.handlers:
25
+ for handler in logger.handlers:
23
26
  if isinstance(handler, l.FileHandler):
24
27
  path = path_t(handler.baseFilename).with_suffix(".htm")
25
28
  break
26
29
  else:
27
- L.warning(f"{cannot_save}: No file handler to build a filename from.")
30
+ logger.warning(f"{cannot_save}: No file handler to build a filename from.")
28
31
  return
29
32
 
30
33
  if path.exists():
31
- L.warning(
34
+ logger.warning(
32
35
  f'{cannot_save}: Automatically generated path "{path}" already exists.'
33
36
  )
34
37
  return
@@ -38,13 +41,38 @@ def SaveLOGasHTML(path: str | path_t | io_base_t | None = None) -> None:
38
41
  actual_file = isinstance(path, path_t)
39
42
 
40
43
  if actual_file and path.exists():
41
- L.warning(f'{cannot_save}: File "{path}" already exists.')
44
+ logger.warning(f'{cannot_save}: File "{path}" already exists.')
42
45
  return
43
46
 
44
- body = "\n".join(map(_HighlightedEvent, L.recorded))
45
- html = MINIMAL_HTML.replace(TITLE_PLACEHOLDER, L.name).replace(
47
+ for handler in logger.handlers:
48
+ records = getattr(handler, "records", None)
49
+ if isinstance(records, list) and (
50
+ (records.__len__() == 0)
51
+ or all(
52
+ isinstance(_, tuple)
53
+ and isinstance(_[0], int)
54
+ and isinstance(_[1], dict | str | l.LogRecord)
55
+ and isinstance(_[2], bool)
56
+ for _ in records
57
+ )
58
+ ):
59
+ break
60
+ else:
61
+ logger.warning(f"{cannot_save}: No handlers with recording capability found.")
62
+ return
63
+
64
+ if records.__len__() == 0:
65
+ return
66
+
67
+ if isinstance(records[0][1], str):
68
+ records = map(_HighlightedEvent, records)
69
+ else:
70
+ records = map(lambda _: str(_[1]), records)
71
+ body = "\n".join(records)
72
+ html = MINIMAL_HTML.replace(TITLE_PLACEHOLDER, logger.name).replace(
46
73
  BODY_PLACEHOLDER, body
47
74
  )
75
+
48
76
  if actual_file:
49
77
  with open(path, "w") as accessor:
50
78
  accessor.write(html)
@@ -52,21 +80,25 @@ def SaveLOGasHTML(path: str | path_t | io_base_t | None = None) -> None:
52
80
  path.write(html)
53
81
 
54
82
 
55
- def _HighlightedEvent(event: tuple[int, str], /) -> str:
83
+ def _HighlightedEvent(event: tuple[int, str, bool], /) -> str:
56
84
  """"""
57
- level, message = event
58
- if level == l.DEBUG:
59
- color = "BlueViolet"
60
- elif level == l.INFO:
61
- color = "black"
62
- elif level == l.WARNING:
63
- color = "gold"
64
- elif level == l.ERROR:
65
- color = "orange"
66
- elif level == l.CRITICAL:
67
- color = "red"
85
+ level, message, is_not_a_rule = event
86
+
87
+ if is_not_a_rule:
88
+ if level == l.DEBUG:
89
+ color = "BlueViolet"
90
+ elif level == l.INFO:
91
+ color = "black"
92
+ elif level == l.WARNING:
93
+ color = "gold"
94
+ elif level == l.ERROR:
95
+ color = "orange"
96
+ elif level == l.CRITICAL:
97
+ color = "red"
98
+ else:
99
+ color = "black"
68
100
  else:
69
- color = "black"
101
+ color = "DarkTurquoise"
70
102
 
71
103
  return f'<span style="color:{color}">{message}</span>'
72
104
 
logger_36/type/logger.py CHANGED
@@ -41,11 +41,7 @@ from logger_36.constant.logger import WARNING_LOGGER_NAME, WARNING_TYPE_COMPILED
41
41
  from logger_36.constant.memory import UNKNOWN_MEMORY_USAGE
42
42
  from logger_36.constant.message import LINE_INDENT, TIME_LENGTH_m_1, expected_op_h
43
43
  from logger_36.constant.path import PROJECT_FILE_RELATIVE, USER_FOLDER
44
- from logger_36.constant.record import (
45
- INTERNAL_INFO_ATTR,
46
- SHOW_W_RULE_ATTR,
47
- SHOW_WHERE_ATTR,
48
- )
44
+ from logger_36.constant.record import SHOW_W_RULE_ATTR, SHOW_WHERE_ATTR
49
45
  from logger_36.task.format.message import MessageWithActualExpected
50
46
  from logger_36.task.measure.chronos import ElapsedTime
51
47
  from logger_36.task.measure.memory import CurrentUsage as CurrentMemoryUsage
@@ -79,21 +75,15 @@ class logger_t(base_t):
79
75
  _should_activate_log_interceptions: Loggers instantiated after a logger_t logger
80
76
  will be missed by an early call of ToggleLogInterceptions. Therefore, passing True
81
77
  for activate_log_interceptions only sets _should_activate_log_interceptions to True,
82
- which is later checked in AddHandler to effectively call ToggleLogInterceptions if
83
- _warming_up is False (which normally indicates that the handler about to
84
- be added is the last one).
85
-
86
- _warming_up: Must not be False until at least one handler has been added.
78
+ which is later checked in AddHandler to effectively call ToggleLogInterceptions.
87
79
  """
88
80
 
89
- should_record_messages: bool = False
90
- should_monitor_memory_usage: bool = False
91
81
  exit_on_error: bool = False # Implies exit_on_critical.
92
82
  exit_on_critical: bool = False
93
- verbose: bool = False
83
+ should_monitor_memory_usage: bool = False
94
84
 
95
- events: dict[int, int] = d.field(init=False, default_factory=dict)
96
- recorded: list[tuple[int, str]] = d.field(init=False, default_factory=list)
85
+ history: dict[date_time_t, str] = d.field(init=False, default_factory=dict)
86
+ n_events: dict[int, int] = d.field(init=False, default_factory=dict)
97
87
 
98
88
  last_message_now: date_time_t = d.field(init=False, default=_DATE_TIME_ORIGIN)
99
89
  last_message_date: date_t = d.field(init=False, default=_DATE_ORIGIN)
@@ -105,12 +95,9 @@ class logger_t(base_t):
105
95
  init=False, default_factory=dict
106
96
  )
107
97
  intercepts_exceptions: bool = d.field(init=False, default=False)
108
- _recording_handler: handler_extension_t | None = d.field(init=False, default=None)
109
98
 
110
99
  # Used only until the last handler is added (see AddHandler).
111
100
  _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
101
 
115
102
  name_: d.InitVar[str | None] = None
116
103
  level_: d.InitVar[int] = l.NOTSET
@@ -168,7 +155,6 @@ class logger_t(base_t):
168
155
  if name_ is None:
169
156
  name_ = f"{type(self).__name__}:{hex(id(self))[2:]}"
170
157
 
171
- self.handle = self._HandleWarmUp
172
158
  base_t.__init__(self, name_)
173
159
  self.setLevel(level_)
174
160
  self.propagate = False # Part of base_t.
@@ -177,15 +163,7 @@ class logger_t(base_t):
177
163
  self.exit_on_critical = True
178
164
 
179
165
  for level_id in l.getLevelNamesMapping().values():
180
- self.events[level_id] = 0
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
- )
166
+ self.n_events[level_id] = 0
189
167
 
190
168
  if activate_wrn_interceptions:
191
169
  self.ToggleWarningInterceptions(True)
@@ -197,29 +175,12 @@ class logger_t(base_t):
197
175
  if self.should_monitor_memory_usage:
198
176
  self.ActivateMemoryUsageMonitoring()
199
177
 
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)
214
-
215
- self._on_hold.append(record)
178
+ self.history[date_time_t.now()] = (
179
+ f'Logger "{self.name}" instantiation for "{PROJECT_FILE_RELATIVE}"'
180
+ )
216
181
 
217
- def _HandleRoutine(self, record: l.LogRecord, /) -> None:
182
+ def handle(self, record: l.LogRecord, /) -> None:
218
183
  """"""
219
- is_internal_info = getattr(record, INTERNAL_INFO_ATTR, False)
220
- if is_internal_info and not self.verbose:
221
- return
222
-
223
184
  elapsed_time, now = ElapsedTime(should_return_now=True)
224
185
 
225
186
  if (date := now.date()) != self.last_message_date:
@@ -244,7 +205,8 @@ class logger_t(base_t):
244
205
  if not isinstance(record.msg, str):
245
206
  record.msg = str(record.msg)
246
207
 
247
- self._HandleRaw(record)
208
+ base_t.handle(self, record)
209
+ self.n_events[record.levelno] += 1
248
210
 
249
211
  if self.should_monitor_memory_usage:
250
212
  self.memory_usages.append((where, CurrentMemoryUsage()))
@@ -256,29 +218,6 @@ class logger_t(base_t):
256
218
  # __post_init__ set self.exit_on_critical if self.exit_on_error.
257
219
  s.exit(1)
258
220
 
259
- def _HandleRaw(self, record: l.LogRecord, /) -> None:
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
- """
272
- for held in self._on_hold:
273
- if self.verbose or not getattr(held, INTERNAL_INFO_ATTR, False):
274
- self._HandleRaw(held)
275
-
276
- self._on_hold.clear()
277
- self._on_hold = None
278
- self._warming_up = False
279
-
280
- self.handle = self._HandleRoutine
281
-
282
221
  def _AcknowledgeDateChange(self, date: date_t, /) -> None:
283
222
  """"""
284
223
  self.last_message_date = date
@@ -291,38 +230,12 @@ class logger_t(base_t):
291
230
  SHOW_W_RULE_ATTR: True,
292
231
  }
293
232
  )
294
-
295
- if self._warming_up:
296
- self._on_hold.append(record)
297
- else:
298
- self._HandleRaw(record)
299
-
300
- def ActivateMessageRecording(self) -> None:
301
- """"""
302
- self._recording_handler = handler_extension_t("recording_handler", 0, None)
303
- self.should_record_messages = True # Useless if called from __post_init__.
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)
233
+ base_t.handle(self, record)
321
234
 
322
235
  def ResetEventCounts(self) -> None:
323
236
  """"""
324
- for level_id in self.events:
325
- self.events[level_id] = 0
237
+ for level_id in self.n_events:
238
+ self.n_events[level_id] = 0
326
239
 
327
240
  def ToggleWarningInterceptions(self, state: bool, /) -> None:
328
241
  """"""
@@ -335,7 +248,7 @@ class logger_t(base_t):
335
248
  logger.handle = t.MethodType(_HandleForWarnings(self), logger)
336
249
 
337
250
  l.captureWarnings(True)
338
- self.info("Warning Interception: ON", extra={INTERNAL_INFO_ATTR: True})
251
+ self.history[date_time_t.now()] = "Warning Interception: ON"
339
252
  else:
340
253
  if not self.intercepts_warnings:
341
254
  return
@@ -345,12 +258,12 @@ class logger_t(base_t):
345
258
  self.intercepted_wrn_handle = None
346
259
 
347
260
  l.captureWarnings(False)
348
- self.info("Warning Interception: OFF", extra={INTERNAL_INFO_ATTR: True})
261
+ self.history[date_time_t.now()] = "Warning Interception: OFF"
349
262
 
350
263
  def ToggleLogInterceptions(self, state: bool, /) -> None:
351
264
  """"""
352
265
  if state:
353
- if self.intercepts_logs:
266
+ if self._should_activate_log_interceptions or self.intercepts_logs:
354
267
  return
355
268
 
356
269
  # Note: Alternative to self.manager is logging.root.manager.
@@ -369,11 +282,14 @@ class logger_t(base_t):
369
282
  intercepted = sorted(self.intercepted_log_handles.keys())
370
283
  if intercepted.__len__() > 0:
371
284
  as_str = ", ".join(intercepted)
372
- self.info(
373
- f"Now Intercepting LOGs from: {as_str}",
374
- extra={INTERNAL_INFO_ATTR: True},
285
+ self.history[date_time_t.now()] = (
286
+ f"Now Intercepting LOGs from: {as_str}"
375
287
  )
376
288
  else:
289
+ if self._should_activate_log_interceptions:
290
+ self._should_activate_log_interceptions = False
291
+ return
292
+
377
293
  if not self.intercepts_logs:
378
294
  return
379
295
 
@@ -381,7 +297,7 @@ class logger_t(base_t):
381
297
  logger = l.getLogger(name)
382
298
  logger.handle = handle
383
299
  self.intercepted_log_handles.clear()
384
- self.info("Log Interception: OFF", extra={INTERNAL_INFO_ATTR: True})
300
+ self.history[date_time_t.now()] = "Log Interception: OFF"
385
301
 
386
302
  def ToggleExceptionInterceptions(self, state: bool, /) -> None:
387
303
  """"""
@@ -392,7 +308,7 @@ class logger_t(base_t):
392
308
  s.excepthook = self.DealWithException
393
309
  thrd.excepthook = self.DealWithExceptionInThread
394
310
  self.intercepts_exceptions = True
395
- self.info("Exception Interception: ON", extra={INTERNAL_INFO_ATTR: True})
311
+ self.history[date_time_t.now()] = "Exception Interception: ON"
396
312
  else:
397
313
  if not self.intercepts_exceptions:
398
314
  return
@@ -400,7 +316,19 @@ class logger_t(base_t):
400
316
  s.excepthook = s.__excepthook__
401
317
  thrd.excepthook = thrd.__excepthook__
402
318
  self.intercepts_exceptions = False
403
- self.info("Exception Interception: OFF", extra={INTERNAL_INFO_ATTR: True})
319
+ self.history[date_time_t.now()] = "Exception Interception: OFF"
320
+
321
+ def ActivateMemoryUsageMonitoring(self) -> None:
322
+ """"""
323
+ if MEMORY_MEASURE_IS_AVAILABLE:
324
+ # Useless if called from __post_init__.
325
+ self.should_monitor_memory_usage = True
326
+ self.history[date_time_t.now()] = (
327
+ f'Memory usage monitoring activated for logger "{self.name}"'
328
+ )
329
+ else:
330
+ self.should_monitor_memory_usage = False
331
+ self.error(MEMORY_MEASURE_ERROR)
404
332
 
405
333
  def AddHandler(
406
334
  self,
@@ -413,21 +341,16 @@ class logger_t(base_t):
413
341
  name: str | None = None,
414
342
  level: int = l.INFO,
415
343
  message_width: int = -1,
416
- this_is_last_handler: bool = True,
417
344
  **kwargs,
418
345
  ) -> None:
419
346
  """
420
347
  Silently ignores re-holding request after un-holding.
421
348
  """
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
428
-
429
- should_flush_on_hold = True
430
- new_handler_warning = "\n(Handlers added from now on will miss above logs.)"
349
+ if self._should_activate_log_interceptions:
350
+ # Turn _should_activate_log_interceptions off before calling
351
+ # ToggleLogInterceptions because it checks it.
352
+ self._should_activate_log_interceptions = False
353
+ self.ToggleLogInterceptions(True)
431
354
 
432
355
  if isinstance(handler_t_or_handler, type):
433
356
  handler = handler_t_or_handler.New(
@@ -437,20 +360,13 @@ class logger_t(base_t):
437
360
  handler = handler_t_or_handler
438
361
  base_t.addHandler(self, handler)
439
362
 
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()
363
+ path = getattr(handler, "baseFilename", "")
364
+ if isinstance(path, path_t) or (path.__len__() > 0):
365
+ path = f"\nPath: {path}"
366
+ self.history[date_time_t.now()] = (
367
+ f'New handler "{handler.name}" of type "{type(handler).__name__}" and '
368
+ f"level {handler.level}={l.getLevelName(handler.level)}{path}"
369
+ )
454
370
 
455
371
  def MakeMonochrome(self) -> None:
456
372
  """"""
logger_36/version.py CHANGED
@@ -4,7 +4,7 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
- __version__ = "2025.22"
7
+ __version__ = "2025.23"
8
8
 
9
9
  """
10
10
  COPYRIGHT NOTICE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: logger-36
3
- Version: 2025.22
3
+ Version: 2025.23
4
4
  Summary: Simple logger with a catalog of handlers
5
5
  Home-page: https://src.koda.cnrs.fr/eric.debreuve/logger-36/
6
6
  Author: Eric Debreuve
@@ -1,5 +1,5 @@
1
1
  logger_36/__init__.py,sha256=mK6AD0eWI2Sk42oxleTvsxzYJ28FbHK5WNkpLgAhnNE,2129
2
- logger_36/version.py,sha256=WM8W-3pzA_JWd1DQWpdL-uJTAxV5u8_nbyWIlGaizjg,1680
2
+ logger_36/version.py,sha256=3y8_8Te0bVUofCcWg9yoGDEx2HlTct92Ol2Pk3NTA8w,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
@@ -13,6 +13,7 @@ logger_36/catalog/handler/console.py,sha256=YEQN8fw7ra9w-5sJACNC4pktv9einm5ASP9T
13
13
  logger_36/catalog/handler/console_rich.py,sha256=gPpq8ij1ZFTXaLgISaCTXDDwv7uWPivLeq2ttpiuKlk,6190
14
14
  logger_36/catalog/handler/file.py,sha256=yg8GnsV6AmDsx1R5iZlsK-5idqD733gc09Syl02TG7Y,2458
15
15
  logger_36/catalog/handler/generic.py,sha256=L8mLc-iQlBWKBqEN3-wIKy2yk_TVgqIWYn_P1hXDsQA,6361
16
+ logger_36/catalog/handler/memory.py,sha256=-31hTXgGImC6if4wJF6eegvwYhsYAQsDTkdoXIUxZB8,3224
16
17
  logger_36/catalog/logger/chronos.py,sha256=S4m9TMPQy_Ju500mpE1jNzu2gZG-QKdVuvX9RVRKHR8,1911
17
18
  logger_36/catalog/logger/gpu.py,sha256=Py5YY0nD_pqJzJsEKQYoOGHcPqyNVJ3J2noOS3hDL6g,2890
18
19
  logger_36/catalog/logger/memory.py,sha256=J0ZGKO7j1FZA_aDGxpABtvzDy1RjCDiDmWYh4U98fEI,4253
@@ -29,7 +30,7 @@ logger_36/constant/logger.py,sha256=ZQYX9JiPsoivwRgYNtdEqRKCagSKD88lRqvxP8MX1ZE,
29
30
  logger_36/constant/memory.py,sha256=Q_E5tTWa-cGaNwrE_xmKa3BxQG6oJO6DHczrxc_M4sE,1817
30
31
  logger_36/constant/message.py,sha256=YJOEzdI0ZjUOdHo3CsiS56FVPhrfNoQYvXuUkprH61g,2312
31
32
  logger_36/constant/path.py,sha256=OfLh70Jyc8po9Ls34nQh_bRr3PXyQ3kF9ciR9QPhiqI,2213
32
- logger_36/constant/record.py,sha256=IGWnKA4TGv1oU6ezzNrGocZlB7Ie7nTr4l3IOtwdWOg,1833
33
+ logger_36/constant/record.py,sha256=VMqGxVTbtHpRiDOsYiXEoyYOocYFm8vtcRY-7zXzJrk,1796
33
34
  logger_36/constant/rule.py,sha256=tBKQgPTt6G_p5eInDdWoEEAvQFz4WMSt5THsS5jvk14,1779
34
35
  logger_36/constant/system.py,sha256=pLlLXG5sepQlSUOo3TphaGrHg8xzJBp-GxpL2NPP47k,1904
35
36
  logger_36/extension/html_.py,sha256=W9SyiYsaaYHUrHLGAAN2wiJGXUlwOBJ5gzdjmEcnF18,3342
@@ -37,16 +38,16 @@ logger_36/extension/line.py,sha256=joeojQX1bZJM53333mOEU3s-YC5ExGOrN9Cu9Lh5-FU,2
37
38
  logger_36/instance/logger.py,sha256=X_U10RYU1h2Aa70D8hBnmFyJZtRILK16KN-GB4xkHMU,1782
38
39
  logger_36/instance/loggers.py,sha256=inBk4KKrQ-z3szaopQ29-qQwh1iSc842sWo5J6zJoiM,1725
39
40
  logger_36/task/inspection.py,sha256=ZgPcrPo3h_kEnM-UpHDLg7PAFfB2fqsLFdfmi6hlPVA,4484
40
- logger_36/task/storage.py,sha256=KAILmJlF5IULxEX9QRCyXCwcalp5mpunWVh1oXuLvSs,3516
41
+ logger_36/task/storage.py,sha256=a50M628062iGEymuj5d9iKo7Ad01OXCZrEQnfNqy0gY,4486
41
42
  logger_36/task/format/memory.py,sha256=J1Oy3jw8wjSp2kuiRUm_VFpzXOHX2FOc7nuRrCyrskw,3723
42
43
  logger_36/task/format/message.py,sha256=Rm6zymVEEGcgKfmxMPXP7q3PtwZJKlXGhqZ5tnvlwxA,3502
43
44
  logger_36/task/measure/chronos.py,sha256=7ijMZgP4EP18HbLV2yCxpNpRS9724Wyk523f-nkbhUM,2529
44
45
  logger_36/task/measure/memory.py,sha256=kkPHEIUTUhkCOLrAt01eLJLnsnkl0nFPNhFZdIB_JAw,1991
45
46
  logger_36/type/handler.py,sha256=4LCFZzI4OEH6lVBrBQ09ZIvF0nq-_j7OOVnujBDyDWA,6665
46
47
  logger_36/type/issue.py,sha256=QHAYf7QgrjJUtF2D46z6X630qTgeP_0FE5hIwf54RsE,2688
47
- logger_36/type/logger.py,sha256=b2F21M5z1hwPdDsyHgBIlC06X9-_7zsjqyGEsVaIJgM,27536
48
+ logger_36/type/logger.py,sha256=nh7EuJvdkaDrtdHPWIjot2a2hGfAzwufMWm9_2KoDXM,24645
48
49
  logger_36/type/loggers.py,sha256=7EX7Sg_RlduBjdfFlNZmUfNeDloH1xU30Rdkg_-rXh8,3172
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,,
50
+ logger_36-2025.23.dist-info/METADATA,sha256=d94bUT9zjDr1Yjny2bsSobExZ1W0MXcIv2hX_DLLGC8,6529
51
+ logger_36-2025.23.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
52
+ logger_36-2025.23.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
53
+ logger_36-2025.23.dist-info/RECORD,,