logger-36 2025.7__py3-none-any.whl → 2025.9__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/api/storage.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
- from logger_36.task.storage import html_reader_t # noqa
7
+ from logger_36.extension.html_ import html_content_t # noqa
8
8
 
9
9
  """
10
10
  COPYRIGHT NOTICE
@@ -6,6 +6,7 @@ SEE COPYRIGHT NOTICE BELOW
6
6
 
7
7
  import dataclasses as d
8
8
  import logging as l
9
+ import sys as s
9
10
  import typing as h
10
11
 
11
12
  from logger_36.constant.record import SHOW_W_RULE_ATTR
@@ -58,14 +59,14 @@ class console_handler_t(l.Handler):
58
59
  message = RuleAsText(record.msg)
59
60
  else:
60
61
  message = self.MessageFromRecord(record)
61
- print(message)
62
+ s.__stdout__.write(message + "\n")
62
63
 
63
64
  def LogAsIs(self, message: str, /) -> None:
64
65
  """
65
66
  See documentation of
66
67
  logger_36.catalog.handler.generic.generic_handler_t.LogAsIs.
67
68
  """
68
- print(message)
69
+ s.__stdout__.write(message + "\n")
69
70
 
70
71
  def DisplayRule(self, /, *, text: str | None = None, color: str = "white") -> None:
71
72
  """"""
@@ -69,11 +69,20 @@ class console_rich_handler_t(l.Handler):
69
69
  should_store_memory_usage: d.InitVar[bool] = False
70
70
  message_width: d.InitVar[int] = -1
71
71
  formatter: d.InitVar[l.Formatter | None] = None
72
+ #
72
73
  should_install_traceback: d.InitVar[bool] = False
73
74
  should_record: d.InitVar[bool] = False
74
-
75
75
  rich_kwargs: d.InitVar[dict[str, h.Any] | None] = None
76
76
 
77
+ @property
78
+ def past_logs_as_HTML(self) -> str | None:
79
+ """"""
80
+ console = self.console
81
+ if console.record:
82
+ return console.export_html()
83
+
84
+ return None
85
+
77
86
  def __post_init__(
78
87
  self,
79
88
  name: str | None,
@@ -30,7 +30,7 @@ class file_handler_t(l.FileHandler):
30
30
  should_store_memory_usage: d.InitVar[bool] = False
31
31
  message_width: d.InitVar[int] = -1
32
32
  formatter: d.InitVar[l.Formatter | None] = None
33
-
33
+ #
34
34
  path: d.InitVar[path_t | None] = None
35
35
  handler_args: d.InitVar[tuple[h.Any, ...] | None] = None
36
36
  handler_kwargs: d.InitVar[dict[str, h.Any] | None] = None
@@ -66,7 +66,7 @@ class file_handler_t(l.FileHandler):
66
66
  message = RuleAsText(record.msg)
67
67
  else:
68
68
  message = self.MessageFromRecord(record)
69
- print(message, file=self.stream)
69
+ self.stream.write(message + "\n")
70
70
  self.stream.flush()
71
71
 
72
72
  def LogAsIs(self, message: str, /) -> None:
@@ -74,7 +74,7 @@ class file_handler_t(l.FileHandler):
74
74
  See documentation of
75
75
  logger_36.catalog.handler.generic.generic_handler_t.LogAsIs.
76
76
  """
77
- print(message, file=self.stream)
77
+ self.stream.write(message + "\n")
78
78
  self.stream.flush()
79
79
 
80
80
  def DisplayRule(self, /, *, text: str | None = None, color: str = "white") -> None:
@@ -75,7 +75,7 @@ class generic_handler_t(l.Handler):
75
75
  should_store_memory_usage: d.InitVar[bool] = False
76
76
  message_width: d.InitVar[int] = -1
77
77
  formatter: d.InitVar[l.Formatter | None] = None
78
-
78
+ #
79
79
  supports_html: d.InitVar[bool] = False
80
80
  should_record: d.InitVar[bool] = False
81
81
  rich_kwargs: d.InitVar[dict[str, h.Any] | None] = None
@@ -26,7 +26,7 @@ def LogGPURelatedDetails(*, logger: logger_t = L) -> None:
26
26
 
27
27
  if None in (tsfl, tsrt):
28
28
  if _GPU_LOGGING_ERROR is not None:
29
- print(_GPU_LOGGING_ERROR, file=s.stderr)
29
+ s.__stderr__.write(_GPU_LOGGING_ERROR + "\n")
30
30
  _GPU_LOGGING_ERROR = None
31
31
  return
32
32
 
logger_36/exception.py CHANGED
@@ -76,14 +76,13 @@ def _HandleException(
76
76
 
77
77
  document = tmpf.NamedTemporaryFile(delete=False)
78
78
 
79
- print(
79
+ s.__stderr__.write(
80
80
  f"{stripe.__name__}\n"
81
81
  f" {module}:{function}@{line_number}\n"
82
82
  f"{line_content}"
83
83
  f"{variables}"
84
84
  f"{message}"
85
- f" Full report at: {document.name}",
86
- file=s.stderr,
85
+ f" Full report at: {document.name}\n",
87
86
  )
88
87
 
89
88
  lines = tcbk.format_exception(exception)
@@ -0,0 +1,107 @@
1
+ """
2
+ Copyright CNRS/Inria/UniCA
3
+ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
4
+ SEE COPYRIGHT NOTICE BELOW
5
+ """
6
+
7
+ import dataclasses as d
8
+ import re as r
9
+ from html.parser import HTMLParser as base_t
10
+
11
+ _BODY_END_PATTERN = r"</[bB][oO][dD][yY]>(.|\n)*$"
12
+
13
+
14
+ @d.dataclass(slots=True, repr=False, eq=False)
15
+ class html_content_t(base_t):
16
+ source: str = ""
17
+ inside_body: bool = d.field(init=False, default=False)
18
+ body_position_start: tuple[int, int] = d.field(init=False, default=(-1, -1))
19
+ body_position_end: tuple[int, int] = d.field(init=False, default=(-1, -1))
20
+ pieces: list[str] = d.field(init=False, default_factory=list)
21
+
22
+ @property
23
+ def body(self) -> str:
24
+ """"""
25
+ output = self.source.splitlines()
26
+ output = "\n".join(
27
+ output[self.body_position_start[0] : (self.body_position_end[0] + 1)]
28
+ )
29
+ output = output[self.body_position_start[1] :]
30
+ output = r.sub(_BODY_END_PATTERN, "", output, count=1)
31
+
32
+ return output.strip()
33
+
34
+ @property
35
+ def body_as_text(self) -> str:
36
+ """"""
37
+ return "".join(self.pieces).strip()
38
+
39
+ def __post_init__(self) -> None:
40
+ """"""
41
+ base_t.__init__(self)
42
+ self.source = self.source.strip()
43
+ self.feed(self.source)
44
+
45
+ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]], /) -> None:
46
+ """"""
47
+ if tag == "body":
48
+ self.body_position_start = self.getpos()
49
+ self.inside_body = True
50
+
51
+ def handle_endtag(self, tag: str, /) -> None:
52
+ """"""
53
+ if tag == "body":
54
+ self.body_position_end = self.getpos()
55
+ self.inside_body = False
56
+
57
+ def handle_data(self, data: str, /) -> None:
58
+ """"""
59
+ if self.inside_body:
60
+ self.pieces.append(data)
61
+
62
+
63
+ """
64
+ COPYRIGHT NOTICE
65
+
66
+ This software is governed by the CeCILL license under French law and
67
+ abiding by the rules of distribution of free software. You can use,
68
+ modify and/ or redistribute the software under the terms of the CeCILL
69
+ license as circulated by CEA, CNRS and INRIA at the following URL
70
+ "http://www.cecill.info".
71
+
72
+ As a counterpart to the access to the source code and rights to copy,
73
+ modify and redistribute granted by the license, users are provided only
74
+ with a limited warranty and the software's author, the holder of the
75
+ economic rights, and the successive licensors have only limited
76
+ liability.
77
+
78
+ In this respect, the user's attention is drawn to the risks associated
79
+ with loading, using, modifying and/or developing or reproducing the
80
+ software by the user in light of its specific status of free software,
81
+ that may mean that it is complicated to manipulate, and that also
82
+ therefore means that it is reserved for developers and experienced
83
+ professionals having in-depth computer knowledge. Users are therefore
84
+ encouraged to load and test the software's suitability as regards their
85
+ requirements in conditions enabling the security of their systems and/or
86
+ data to be ensured and, more generally, to use and operate it in the
87
+ same conditions as regards security.
88
+
89
+ The fact that you are presently reading this means that you have had
90
+ knowledge of the CeCILL license and that you accept its terms.
91
+
92
+ SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
93
+
94
+ This software is being developed by Eric Debreuve, a CNRS employee and
95
+ member of team Morpheme.
96
+ Team Morpheme is a joint team between Inria, CNRS, and UniCA.
97
+ It is hosted by the Centre Inria d'Université Côte d'Azur, Laboratory
98
+ I3S, and Laboratory iBV.
99
+
100
+ CNRS: https://www.cnrs.fr/index.php/en
101
+ Inria: https://www.inria.fr/en/
102
+ UniCA: https://univ-cotedazur.eu/
103
+ Centre Inria d'Université Côte d'Azur: https://www.inria.fr/en/centre/sophia/
104
+ I3S: https://www.i3s.unice.fr/en/
105
+ iBV: http://ibv.unice.fr/
106
+ Team Morpheme: https://team.inria.fr/morpheme/
107
+ """
logger_36/handler.py CHANGED
@@ -94,7 +94,7 @@ def AddRichConsoleHandler(
94
94
  """"""
95
95
  global _MISSING_RICH_MESSAGE
96
96
  if _MISSING_RICH_MESSAGE is not None:
97
- print(_MISSING_RICH_MESSAGE, file=s.stderr)
97
+ s.__stderr__.write(_MISSING_RICH_MESSAGE + "\n")
98
98
  _MISSING_RICH_MESSAGE = None
99
99
 
100
100
  if console_rich_handler_t is console_handler_t:
logger_36/task/storage.py CHANGED
@@ -4,73 +4,12 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
- import dataclasses as d
8
7
  import logging as l
9
- import re as r
10
- from html.parser import HTMLParser as html_parser_t
11
8
  from io import IOBase as io_base_t
12
9
  from pathlib import Path as path_t
13
10
 
14
- from logger_36.catalog.config.optional import RICH_IS_AVAILABLE
15
11
  from logger_36.instance.logger import L
16
12
 
17
- if RICH_IS_AVAILABLE:
18
- from rich.console import Console as console_t # noqa
19
- else:
20
- console_t = None
21
-
22
-
23
- _BODY_END_PATTERN = r"</[bB][oO][dD][yY]>(.|\n)*$"
24
-
25
-
26
- @d.dataclass(slots=True, repr=False, eq=False)
27
- class html_reader_t(html_parser_t):
28
- source: str = ""
29
- inside_body: bool = d.field(init=False, default=False)
30
- body_position_start: tuple[int, int] = d.field(init=False, default=(-1, -1))
31
- body_position_end: tuple[int, int] = d.field(init=False, default=(-1, -1))
32
- pieces: list[str] = d.field(init=False, default_factory=list)
33
-
34
- def __post_init__(self) -> None:
35
- """"""
36
- html_parser_t.__init__(self)
37
- self.source = self.source.strip()
38
- self.feed(self.source)
39
-
40
- def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]], /) -> None:
41
- """"""
42
- if tag == "body":
43
- self.body_position_start = self.getpos()
44
- self.inside_body = True
45
-
46
- def handle_endtag(self, tag: str, /) -> None:
47
- """"""
48
- if tag == "body":
49
- self.body_position_end = self.getpos()
50
- self.inside_body = False
51
-
52
- def handle_data(self, data: str, /) -> None:
53
- """"""
54
- if self.inside_body:
55
- self.pieces.append(data)
56
-
57
- @property
58
- def body(self) -> str:
59
- """"""
60
- output = self.source.splitlines()
61
- output = "\n".join(
62
- output[self.body_position_start[0] : (self.body_position_end[0] + 1)]
63
- )
64
- output = output[self.body_position_start[1] :]
65
- output = r.sub(_BODY_END_PATTERN, "", output, count=1)
66
-
67
- return output.strip()
68
-
69
- @property
70
- def body_as_text(self) -> str:
71
- """"""
72
- return "".join(self.pieces).strip()
73
-
74
13
 
75
14
  def SaveLOGasHTML(path: str | path_t | io_base_t | None = None) -> None:
76
15
  """
@@ -78,18 +17,15 @@ def SaveLOGasHTML(path: str | path_t | io_base_t | None = None) -> None:
78
17
  """
79
18
  cannot_save = "Cannot save logging record as HTML"
80
19
 
81
- if console_t is None:
82
- L.warning(f"{cannot_save}: The Rich console cannot be imported.")
83
- return
84
-
85
20
  if path is None:
86
21
  for handler in L.handlers:
87
22
  if isinstance(handler, l.FileHandler):
88
23
  path = path_t(handler.baseFilename).with_suffix(".htm")
89
24
  break
90
- if path is None:
25
+ else:
91
26
  L.warning(f"{cannot_save}: No file handler to build a filename from.")
92
27
  return
28
+
93
29
  if path.exists():
94
30
  L.warning(
95
31
  f'{cannot_save}: Automatically generated path "{path}" already exists.'
@@ -103,18 +39,15 @@ def SaveLOGasHTML(path: str | path_t | io_base_t | None = None) -> None:
103
39
  L.warning(f'{cannot_save}: File "{path}" already exists.')
104
40
  return
105
41
 
106
- for handler in L.handlers:
107
- console = getattr(handler, "console", None)
108
- if isinstance(console, console_t) and console.record:
109
- html = console.export_html()
110
- if actual_file:
111
- with open(path, "w") as accessor:
112
- accessor.write(html)
113
- else:
114
- path.write(html)
115
- break
42
+ html = L.past_logs_as_HTML
43
+ if html is None:
44
+ L.warning(f"{cannot_save}: No handler could provide an HTML output.")
116
45
  else:
117
- L.warning(f"{cannot_save}: No handler has a RICH console with recording ON.")
46
+ if actual_file:
47
+ with open(path, "w") as accessor:
48
+ accessor.write(html)
49
+ else:
50
+ path.write(html)
118
51
 
119
52
 
120
53
  """
logger_36/type/handler.py CHANGED
@@ -73,7 +73,7 @@ class handler_extension_t:
73
73
  if self.should_store_memory_usage and not CanCheckMemoryUsage():
74
74
  self.should_store_memory_usage = False
75
75
  if _MEMORY_MEASURE_ERROR is not None:
76
- print(_MEMORY_MEASURE_ERROR, file=s.stderr)
76
+ s.__stderr__.write(_MEMORY_MEASURE_ERROR + "\n")
77
77
  _MEMORY_MEASURE_ERROR = None
78
78
 
79
79
  handler.setLevel(level)
logger_36/type/logger.py CHANGED
@@ -63,11 +63,14 @@ class logger_t(base_t):
63
63
  """
64
64
  intercepted_wrn_handle: When warning interception is on, this stores the original
65
65
  "handle" method of the Python warning logger.
66
- """
67
66
 
68
- name_: d.InitVar[str] = LOGGER_NAME
69
- level_: d.InitVar[int] = l.NOTSET
70
- activate_wrn_interceptions: d.InitVar[bool] = True
67
+ should_activate_log_interceptions: Loggers instantiated after a logger_t logger will
68
+ be missed by an early call of ToggleLogInterceptions. Therefore, passing True for
69
+ activate_log_interceptions only sets should_activate_log_interceptions to True,
70
+ which is later checked in AddHandler to effectively call ToggleLogInterceptions if
71
+ should_hold_messages is False (which normally indicates that the handler about to be
72
+ added is the last one).
73
+ """
71
74
 
72
75
  # Must not be False until at least one handler has been added.
73
76
  should_hold_messages: bool = True
@@ -86,6 +89,12 @@ class logger_t(base_t):
86
89
  intercepted_log_handles: dict[str, logger_handle_h] = d.field(
87
90
  init=False, default_factory=dict
88
91
  )
92
+ should_activate_log_interceptions: bool = False
93
+
94
+ name_: d.InitVar[str] = LOGGER_NAME
95
+ level_: d.InitVar[int] = l.NOTSET
96
+ activate_wrn_interceptions: d.InitVar[bool] = True
97
+ activate_log_interceptions: d.InitVar[bool] = True
89
98
 
90
99
  @property
91
100
  def intercepts_warnings(self) -> bool:
@@ -102,6 +111,18 @@ class logger_t(base_t):
102
111
  """"""
103
112
  return self.staged_issues.__len__() > 0
104
113
 
114
+ @property
115
+ def past_logs_as_HTML(self) -> str | None:
116
+ """
117
+ From the first handler found with the given functionality, if any.
118
+ """
119
+ for handler in self.handlers:
120
+ past_logs_as_HTML = getattr(handler, "past_logs_as_HTML", None)
121
+ if past_logs_as_HTML is not None:
122
+ return past_logs_as_HTML
123
+
124
+ return None
125
+
105
126
  @property
106
127
  def max_memory_usage(self) -> int:
107
128
  """"""
@@ -121,7 +142,11 @@ class logger_t(base_t):
121
142
  return "?", UNKNOWN_MEMORY_USAGE
122
143
 
123
144
  def __post_init__(
124
- self, name_: str, level_: int, activate_wrn_interceptions: bool
145
+ self,
146
+ name_: str,
147
+ level_: int,
148
+ activate_wrn_interceptions: bool,
149
+ activate_log_interceptions: bool,
125
150
  ) -> None:
126
151
  """"""
127
152
  base_t.__init__(self, name_)
@@ -135,6 +160,9 @@ class logger_t(base_t):
135
160
 
136
161
  if activate_wrn_interceptions:
137
162
  self.ToggleWarningInterceptions(True)
163
+ if activate_log_interceptions:
164
+ self.should_activate_log_interceptions = True
165
+
138
166
  if self.exit_on_error:
139
167
  self.exit_on_critical = True
140
168
 
@@ -250,72 +278,31 @@ class logger_t(base_t):
250
278
  )
251
279
  )
252
280
 
253
- def MakeMonochrome(
254
- self,
255
- *,
256
- should_intercept_logs: bool = True,
257
- should_override_exceptions: bool = True,
258
- ) -> None:
281
+ def MakeMonochrome(self) -> None:
259
282
  """"""
260
- self._MakePreamble(
261
- should_intercept_logs=should_intercept_logs,
262
- should_override_exceptions=should_override_exceptions,
263
- )
283
+ OverrideExceptionFormat()
264
284
  AddConsoleHandler(self)
265
285
 
266
- def MakeRich(
267
- self,
268
- *,
269
- alternating_lines: int = 2,
270
- should_intercept_logs: bool = True,
271
- should_override_exceptions: bool = True,
272
- ) -> None:
286
+ def MakeRich(self, *, alternating_lines: int = 2) -> None:
273
287
  """"""
274
- self._MakePreamble(
275
- should_intercept_logs=should_intercept_logs,
276
- should_override_exceptions=should_override_exceptions,
277
- )
288
+ OverrideExceptionFormat()
278
289
  AddRichConsoleHandler(self, alternating_lines=alternating_lines)
279
290
 
280
- def MakePermanent(
281
- self,
282
- path: str | path_t,
283
- /,
284
- *,
285
- should_intercept_logs: bool = True,
286
- should_override_exceptions: bool = True,
287
- ) -> None:
291
+ def MakePermanent(self, path: str | path_t, /) -> None:
288
292
  """"""
289
- self._MakePreamble(
290
- should_intercept_logs=should_intercept_logs,
291
- should_override_exceptions=should_override_exceptions,
292
- )
293
+ OverrideExceptionFormat()
293
294
  AddFileHandler(self, path)
294
295
 
295
- def _MakePreamble(
296
- self,
297
- *,
298
- should_intercept_logs: bool = True,
299
- should_override_exceptions: bool = True,
300
- ) -> None:
301
- """"""
302
- if should_override_exceptions:
303
- OverrideExceptionFormat()
304
- if should_intercept_logs:
305
- self.ToggleLogInterceptions(True)
306
-
307
296
  def ResetEventCounts(self) -> None:
308
297
  """"""
309
298
  for level in self.events:
310
299
  self.events[level] = 0
311
300
 
312
301
  def ToggleWarningInterceptions(self, state: bool, /) -> None:
313
- """
314
- The log message will not appear if called from __post_init__ since there are no
315
- handlers yet.
316
- """
302
+ """"""
317
303
  if state:
318
- assert not self.intercepts_warnings
304
+ if self.intercepts_warnings:
305
+ return
319
306
 
320
307
  logger = l.getLogger(WARNING_LOGGER_NAME)
321
308
  self.intercepted_wrn_handle = logger.handle
@@ -324,7 +311,8 @@ class logger_t(base_t):
324
311
  l.captureWarnings(True)
325
312
  self.info("Warning Interception: ON")
326
313
  else:
327
- assert self.intercepts_warnings
314
+ if not self.intercepts_warnings:
315
+ return
328
316
 
329
317
  logger = l.getLogger(WARNING_LOGGER_NAME)
330
318
  logger.handle = self.intercepted_wrn_handle
@@ -336,11 +324,14 @@ class logger_t(base_t):
336
324
  def ToggleLogInterceptions(self, state: bool, /) -> None:
337
325
  """"""
338
326
  if state:
339
- assert not self.intercepts_logs
327
+ if self.intercepts_logs:
328
+ return
340
329
 
330
+ # Note: Alternative to self.manager is logging.root.manager.
331
+ all_loggers_names_but_root = self.manager.loggerDict.keys()
341
332
  all_loggers = [l.getLogger()] + [
342
333
  l.getLogger(_nme)
343
- for _nme in self.manager.loggerDict
334
+ for _nme in all_loggers_names_but_root
344
335
  if _nme not in (self.name, WARNING_LOGGER_NAME)
345
336
  ]
346
337
  for logger in all_loggers:
@@ -354,7 +345,8 @@ class logger_t(base_t):
354
345
  as_str = ", ".join(intercepted)
355
346
  self.info(f"Now Intercepting LOGs from: {as_str}")
356
347
  else:
357
- assert self.intercepts_logs
348
+ if not self.intercepts_logs:
349
+ return
358
350
 
359
351
  for name, handle in self.intercepted_log_handles.items():
360
352
  logger = l.getLogger(name)
@@ -366,6 +358,10 @@ class logger_t(base_t):
366
358
  self, handler: l.Handler, /, *, should_hold_messages: bool = False
367
359
  ) -> None:
368
360
  """"""
361
+ if (not should_hold_messages) and self.should_activate_log_interceptions:
362
+ self.ToggleLogInterceptions(True)
363
+ self.should_activate_log_interceptions = False
364
+
369
365
  self.should_hold_messages = should_hold_messages
370
366
  base_t.addHandler(self, handler)
371
367
 
@@ -583,13 +579,18 @@ def _HandleForWarnings(interceptor: base_t, /) -> logger_handle_h:
583
579
  path = GetPiece(1)
584
580
  line = GetPiece(2)
585
581
  kind = GetPiece(3)
586
- message = GetPiece(4).strip()
582
+ message = GetPiece(4)
583
+
584
+ path_as_t = path_t(path)
585
+ line = int(line)
586
+ line_content = path_as_t.read_text().splitlines()[line - 1]
587
+ message = message.replace(line_content.strip(), "").strip()
587
588
 
588
589
  duplicate = l.makeLogRecord(record.__dict__)
589
590
  duplicate.msg = f"{kind}: {message}"
590
591
  duplicate.pathname = path
591
- duplicate.module = path_t(path).stem
592
- duplicate.funcName = "?"
592
+ duplicate.module = path_as_t.stem
593
+ duplicate.funcName = "<function>"
593
594
  duplicate.lineno = line
594
595
 
595
596
  interceptor.handle(duplicate)
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.7"
7
+ __version__ = "2025.9"
8
8
 
9
9
  """
10
10
  COPYRIGHT NOTICE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: logger-36
3
- Version: 2025.7
3
+ Version: 2025.9
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,23 +1,23 @@
1
1
  logger_36/__init__.py,sha256=3BtAgxFb14e9zzC5fXwqSQxstsd3BO0b_KVu3_wbLwg,2592
2
2
  logger_36/content.py,sha256=clHYYUKa8n4qef6PVlUV4mFHRRf6fnm9wEd2fu9oagA,2381
3
- logger_36/exception.py,sha256=BQm9maX9CMjpqN26cEsArPCcX37LqYtQSrUZ3fN8tbU,4613
3
+ logger_36/exception.py,sha256=9YWnS2LN_Mc0qYkohtbgEkzKe9ja2h_dBEd39ytGbRU,4605
4
4
  logger_36/gpu.py,sha256=BOumedCAPWvCo7J-KJ3XE-jr5S0KSmgcFv_S4QKRPO8,2252
5
- logger_36/handler.py,sha256=pIwunW-_aSB-SrdlvVmq61nOTH03deKIVcJa4Sz_hkc,6304
5
+ logger_36/handler.py,sha256=YOSkwLOO02Y69z-Hd7gtjng7s3VtgvlqnLMgv8jovI4,6309
6
6
  logger_36/memory.py,sha256=szJVk4UTXsbYv3B-W9LFttf1F3j86GXHsKgEUOsXKl4,2743
7
7
  logger_36/storage.py,sha256=sCxkHQH4xMaseweK1p2M1j0j2PxNPpy9MytPdg1sKiQ,2239
8
8
  logger_36/system.py,sha256=cgOMF_OneYeIJDMbIbIDx96EZss2uAdkk8QofOC7O1U,2251
9
9
  logger_36/time.py,sha256=Uw1jQtY1njsRuIPRAXX44v4nPOo84MSBu_WK_YCRzQs,2324
10
- logger_36/version.py,sha256=QWIy4Jr-I6cIfY2uS0OZkwf54A1Oh3Rxgb14HI6W6bE,2205
10
+ logger_36/version.py,sha256=GMhKYpDckX_jLa0A1mt1reiX5XWPRZxrdkZSXbm_Km4,2205
11
11
  logger_36/api/logger.py,sha256=TE3ATbymeWX-wBKBFkVz2FxUyJnaqY7vzFwAONVsp2o,2233
12
- logger_36/api/storage.py,sha256=KT52AGR37nsMrhKTVfG8R-Dc7lmCXjWML18cOqqCXZY,2239
12
+ logger_36/api/storage.py,sha256=v1iywLEItJCz18F_nJ20OnlpCpLdA-7EhlvqdLu42js,2243
13
13
  logger_36/catalog/config/console_rich.py,sha256=lAa5Ev5BhXvmQzfIt1FNihMNUQJFlXaIzNanAMdgtd0,2861
14
14
  logger_36/catalog/config/optional.py,sha256=HaN6mbx7gHBBppNvUw1ckhYTOrlYqb-b_r0mzPcHPjM,2398
15
- logger_36/catalog/handler/console.py,sha256=s2DBcDK9To-wVS228RsDDPmOPxlIbVnQbZINfIK2TP0,4150
16
- logger_36/catalog/handler/console_rich.py,sha256=pI0OE0c5I19-ycvOJjdG5vdtDXTZadNNRbKCJD-2oL4,8347
17
- logger_36/catalog/handler/file.py,sha256=2qbsI3UHxqEm9WiCMkAm20hA2qXth2wKnakazVbwrBs,4613
18
- logger_36/catalog/handler/generic.py,sha256=y-f6HY5xppoHYYnej0qOQT3BI0Gam_0W1_bIHCk5nn0,9212
15
+ logger_36/catalog/handler/console.py,sha256=13ygxLmsywdGlr9hV9guw7FuRD-dxlZX20d1Mn-pWKs,4206
16
+ logger_36/catalog/handler/console_rich.py,sha256=E9ysE_aREozf9qz-ooxzVMwT3aj13U6Mb8qtmomYwSI,8549
17
+ logger_36/catalog/handler/file.py,sha256=ZbYLic0XcX3vw-col8hiuO-SQOSZh06tPYu5z3FdGDo,4620
18
+ logger_36/catalog/handler/generic.py,sha256=sJwqUFKEcziVAtHrPLDemEdeB1VU-F2gXkbbLtsYJ-g,9217
19
19
  logger_36/catalog/logger/chronos.py,sha256=ocY13f98EfknU7wZCv0FS9Xb7pTNaWCPSusXFIEvEd4,2437
20
- logger_36/catalog/logger/gpu.py,sha256=lzrkqrMnXsszRB_TiHFqnNNI7JhNat8qL2OSlnHDe5c,3412
20
+ logger_36/catalog/logger/gpu.py,sha256=n_kbAQdRNk3Jdket6031_r2unOcz3dWplhCR-WFPjE0,3417
21
21
  logger_36/catalog/logger/memory.py,sha256=CWhr2J4BqArJxzH6tS-ZThr-rYPAQGtuLn0pP7Iryfg,4685
22
22
  logger_36/catalog/logger/system.py,sha256=KXP2jdPd-ACFNdA0wWdmOLwuxt4baUvXkuChyOHyfy0,3066
23
23
  logger_36/config/issue.py,sha256=G-i5p6lhZCLAOa-VTMyL9ZonvGCvhdoQ5KZdSWgP-FU,2267
@@ -34,20 +34,21 @@ logger_36/constant/message.py,sha256=Ys_CAyhENlT8Z3rr-AxO4hjdl1jLsKzVSPQ8wqLOCPQ
34
34
  logger_36/constant/path.py,sha256=fKJn2vGj012BU5DFRetDFus_tKMty2q_WL0J2KrXdCo,2731
35
35
  logger_36/constant/record.py,sha256=9Q28lVH_s0og4v74delgwIPAJ9G28I5rBM-brXcoY80,2308
36
36
  logger_36/constant/system.py,sha256=G2mzBTxRXoJMxb53TnmBaceMJC_q3WonoCG7y6nC_R8,2430
37
+ logger_36/extension/html_.py,sha256=J9EX8-Rotq9i8bZ9U-dIpXv5gKLLnLmWqdDy4XayT1Q,3868
37
38
  logger_36/instance/logger.py,sha256=oTw5svRzKRJKvGrrZUtutJIOjp5UISft3fl0Ze7DOBE,2241
38
39
  logger_36/instance/loggers.py,sha256=RCWpC1NPAf6vXnFc9NqsSALv-x-FEzcH6k_OlxTxeQk,2251
39
40
  logger_36/task/inspection.py,sha256=KZzmQyREQ6VmBWCLyNIYIOOISW9C_fC9TWTSX90zGDk,5019
40
- logger_36/task/storage.py,sha256=2B4OU7RqpUe98-pY9fadfnW8aFwxtsLSRGKkBtGWn-k,5686
41
+ logger_36/task/storage.py,sha256=T96JZT5Tmrt_-Kqf_WKweTvJYPX6lmPZZkJzCqyVPcI,3502
41
42
  logger_36/task/format/memory.py,sha256=jpQS8tAdxy7GM_FzqEIJUU3m-6O9iX-jiyO7gx5YwR8,4266
42
43
  logger_36/task/format/message.py,sha256=T2V2gUlUQqSojyRrz4I4uAHwNe6eBEsuAe6V-LTyx0k,3867
43
44
  logger_36/task/format/rule.py,sha256=vkf-HivFb4VqV2GeOPVqMAp99krtziI-kXhox3UVnzw,2873
44
45
  logger_36/task/measure/chronos.py,sha256=1kVhu6jZlNAtNWQQh8ZVuRwZIAC9gGz3_ul1tn0t4Yw,3055
45
46
  logger_36/task/measure/memory.py,sha256=OjU5EYFH8SnzlCQKAoiXvauUlwQYOrH34jFXTVYF0jE,2517
46
- logger_36/type/handler.py,sha256=-myl7uBMOzkwCs1u4ehuYlQa9F6909jmnL2v_eQN5ag,6819
47
+ logger_36/type/handler.py,sha256=5g5KdmKk6cdsUSV0JoFfjpAXdQIzSRcW81STyLqqWq8,6824
47
48
  logger_36/type/issue.py,sha256=2rGsFqaQJCbeml9xN08mN_nK79L8qscaS_0ws36Y0bI,3214
48
- logger_36/type/logger.py,sha256=nGNWJ5xcyA79E45qcZ-gZ3ZuY7j1aDg5NXk7VwbQVFU,22287
49
+ logger_36/type/logger.py,sha256=4KkM_bIVRsjGO0ORloSibEb0MPtg88wSj5_wweRKjJU,22805
49
50
  logger_36/type/loggers.py,sha256=znqxWBnfQxvkg3VUfbTUvt3S6Kq0DAzWWepxQDt9suI,2871
50
- logger_36-2025.7.dist-info/METADATA,sha256=E708bS17nu3wkJZ7YTNfvezYSBUbfwXgUCwiiXwOkf0,6505
51
- logger_36-2025.7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
52
- logger_36-2025.7.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
53
- logger_36-2025.7.dist-info/RECORD,,
51
+ logger_36-2025.9.dist-info/METADATA,sha256=AMDXKjSSMDRqWDLT0FeNYlV9bWGc2s1LXSDTD_h93sg,6505
52
+ logger_36-2025.9.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
53
+ logger_36-2025.9.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
54
+ logger_36-2025.9.dist-info/RECORD,,