logger-36 2025.19__py3-none-any.whl → 2025.21__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/type/handler.py CHANGED
@@ -82,8 +82,6 @@ class extension_t:
82
82
  if when_or_elapsed is None:
83
83
  return message, True
84
84
 
85
- level_first_letter = getattr(record, "level_first_letter", "")
86
-
87
85
  if (where := getattr(record, "where", None)) is None:
88
86
  where = ""
89
87
  else:
@@ -91,7 +89,7 @@ class extension_t:
91
89
 
92
90
  return (
93
91
  f"{when_or_elapsed}"
94
- f"{LEVEL_OPENING}{level_first_letter}{LEVEL_CLOSING} "
92
+ f"{LEVEL_OPENING}{record.levelname[0]}{LEVEL_CLOSING} "
95
93
  f"{MESSAGE_MARKER} {message}{where}"
96
94
  ), True
97
95
 
logger_36/type/logger.py CHANGED
@@ -38,12 +38,6 @@ from logger_36.constant.memory import UNKNOWN_MEMORY_USAGE
38
38
  from logger_36.constant.message import LINE_INDENT, TIME_LENGTH_m_1, expected_op_h
39
39
  from logger_36.constant.path import PROJECT_FILE_RELATIVE, USER_FOLDER
40
40
  from logger_36.constant.record import SHOW_W_RULE_ATTR, SHOW_WHERE_ATTR
41
- from logger_36.constant.rule import (
42
- DEFAULT_RULE,
43
- DEFAULT_RULE_LENGTH,
44
- MIN_HALF_RULE_LENGTH,
45
- RULE_CHARACTER,
46
- )
47
41
  from logger_36.task.format.message import MessageWithActualExpected
48
42
  from logger_36.task.measure.chronos import ElapsedTime
49
43
  from logger_36.task.measure.memory import CanCheckUsage as CanCheckMemoryUsage
@@ -76,12 +70,12 @@ class logger_t(base_t):
76
70
  intercepted_wrn_handle: When warning interception is on, this stores the original
77
71
  "handle" method of the Python warning logger.
78
72
 
79
- _should_activate_log_interceptions: Loggers instantiated after a logger_t logger will
80
- be missed by an early call of ToggleLogInterceptions. Therefore, passing True for
81
- activate_log_interceptions only sets _should_activate_log_interceptions to True,
73
+ _should_activate_log_interceptions: Loggers instantiated after a logger_t logger
74
+ will be missed by an early call of ToggleLogInterceptions. Therefore, passing True
75
+ for activate_log_interceptions only sets _should_activate_log_interceptions to True,
82
76
  which is later checked in AddHandler to effectively call ToggleLogInterceptions if
83
- _should_hold_messages is False (which normally indicates that the handler about to be
84
- added is the last one).
77
+ _should_hold_messages is False (which normally indicates that the handler about to
78
+ be added is the last one).
85
79
 
86
80
  _should_hold_messages: Must not be False until at least one handler has been added.
87
81
  """
@@ -171,9 +165,17 @@ class logger_t(base_t):
171
165
  self.setLevel(level_)
172
166
  self.propagate = False # Part of base_t.
173
167
 
168
+ if self.exit_on_error:
169
+ self.exit_on_critical = True
170
+
174
171
  for level_id in l.getLevelNamesMapping().values():
175
172
  self.events[level_id] = 0
176
173
 
174
+ if self.should_record_messages:
175
+ self.ActivateMessageRecording()
176
+
177
+ self.info(f'New logger "{self.name}" for "{PROJECT_FILE_RELATIVE}"')
178
+
177
179
  if activate_wrn_interceptions:
178
180
  self.ToggleWarningInterceptions(True)
179
181
  if activate_log_interceptions:
@@ -181,57 +183,18 @@ class logger_t(base_t):
181
183
  if activate_exc_interceptions:
182
184
  self.ToggleExceptionInterceptions(True)
183
185
 
184
- if self.exit_on_error:
185
- self.exit_on_critical = True
186
-
187
- if self.should_record_messages:
188
- self.ActivateMessageRecording()
189
-
190
186
  if self.should_watch_memory_usage and not CanCheckMemoryUsage():
191
187
  self.should_watch_memory_usage = False
192
188
  if _MEMORY_MEASURE_ERROR is not None:
193
189
  s.__stderr__.write(_MEMORY_MEASURE_ERROR + "\n")
194
190
  _MEMORY_MEASURE_ERROR = None
195
191
 
196
- self.info(f'New logger "{self.name}" for "{PROJECT_FILE_RELATIVE}"')
197
-
198
192
  def handle(self, record: l.LogRecord, /) -> None:
199
193
  """"""
200
194
  elapsed_time, now = ElapsedTime(should_return_now=True)
201
195
 
202
- if (self._on_hold.__len__() > 0) and not self._should_hold_messages:
203
- for held in self._on_hold:
204
- if self.should_record_messages:
205
- self.recorded.append(
206
- (
207
- held.levelno,
208
- self._recording_handler.MessageFromRecord(held)[0],
209
- )
210
- )
211
- base_t.handle(self, held)
212
- self._on_hold.clear()
213
-
214
196
  if (date := now.date()) != self.last_message_date:
215
- self.last_message_date = date
216
- date_record = l.makeLogRecord(
217
- {
218
- "name": self.name,
219
- "levelno": l.INFO, # For management by logging.Logger.handle.
220
- "msg": f"DATE: {date.strftime(DATE_FORMAT)}",
221
- SHOW_W_RULE_ATTR: True,
222
- }
223
- )
224
- if self._should_hold_messages:
225
- self._on_hold.append(date_record)
226
- else:
227
- if self.should_record_messages:
228
- self.recorded.append(
229
- (
230
- date_record.levelno,
231
- self._recording_handler.MessageFromRecord(date_record)[0],
232
- )
233
- )
234
- base_t.handle(self, date_record)
197
+ self._AcknowledgeDateChange(date)
235
198
 
236
199
  # When.
237
200
  if now - self.last_message_now > LONG_ENOUGH:
@@ -259,9 +222,6 @@ class logger_t(base_t):
259
222
  else:
260
223
  where = None
261
224
 
262
- # How.
263
- record.level_first_letter = record.levelname[0]
264
-
265
225
  # What.
266
226
  if not isinstance(record.msg, str):
267
227
  record.msg = str(record.msg)
@@ -269,14 +229,11 @@ class logger_t(base_t):
269
229
  if self._should_hold_messages:
270
230
  self._on_hold.append(record)
271
231
  else:
272
- if self.should_record_messages:
273
- self.recorded.append(
274
- (
275
- record.levelno,
276
- self._recording_handler.MessageFromRecord(record)[0],
277
- )
278
- )
279
- base_t.handle(self, record)
232
+ self._HandleRecord(record)
233
+ self.events[record.levelno] += 1
234
+
235
+ if self.should_watch_memory_usage:
236
+ self.memory_usages.append((where, CurrentMemoryUsage()))
280
237
 
281
238
  if (self.exit_on_critical and (record.levelno is l.CRITICAL)) or (
282
239
  self.exit_on_error and (record.levelno is l.ERROR)
@@ -285,35 +242,44 @@ class logger_t(base_t):
285
242
  # __post_init__ set self.exit_on_critical if self.exit_on_error.
286
243
  s.exit(1)
287
244
 
288
- self.events[record.levelno] += 1
245
+ def _FlushRecordsOnHold(self) -> None:
246
+ """"""
247
+ for held in self._on_hold:
248
+ self._HandleRecord(held)
289
249
 
290
- if self.should_watch_memory_usage:
291
- self.memory_usages.append((where, CurrentMemoryUsage()))
250
+ self._on_hold.clear()
292
251
 
293
- def ActivateMessageRecording(self) -> None:
252
+ def _AcknowledgeDateChange(self, date: date_t, /) -> None:
294
253
  """"""
295
- if self._recording_handler is None:
296
- self._recording_handler = handler_extension_t("recording_handler", 0, None)
297
- self.should_record_messages = True # Useless if called from __post_init__.
254
+ self.last_message_date = date
255
+
256
+ record = l.makeLogRecord(
257
+ {
258
+ "name": self.name,
259
+ "levelno": l.INFO, # For management by logging.Logger.handle.
260
+ "msg": f"DATE: {date.strftime(DATE_FORMAT)}",
261
+ SHOW_W_RULE_ATTR: True,
262
+ }
263
+ )
298
264
 
299
- def MakeMonochrome(self) -> None:
300
- """"""
301
- self.AddHandler(console_handler_t)
265
+ if self._should_hold_messages:
266
+ self._on_hold.append(record)
267
+ else:
268
+ self._HandleRecord(record)
302
269
 
303
- def MakeRich(self, *, alternating_logs: int = 0) -> None:
270
+ def _HandleRecord(self, record: l.LogRecord, /) -> None:
304
271
  """"""
305
- if MISSING_RICH_MESSAGE is not None:
306
- s.__stderr__.write(MISSING_RICH_MESSAGE + "\n")
272
+ if self.should_record_messages:
273
+ message = self._recording_handler.MessageFromRecord(record)[0]
274
+ self.recorded.append((record.levelno, message))
307
275
 
308
- if console_rich_handler_t is console_handler_t:
309
- handler_kwargs = {}
310
- else:
311
- handler_kwargs = {"alternating_logs": alternating_logs}
312
- self.AddHandler(console_rich_handler_t, **handler_kwargs)
276
+ base_t.handle(self, record)
313
277
 
314
- def MakePermanent(self, path: str | path_t, /) -> None:
278
+ def ActivateMessageRecording(self) -> None:
315
279
  """"""
316
- self.AddHandler(file_handler_t, path=path)
280
+ self._recording_handler = handler_extension_t("recording_handler", 0, None)
281
+ self.should_record_messages = True # Useless if called from __post_init__.
282
+ self.info(f'Message recording activated for logger "{self.name}"')
317
283
 
318
284
  def ResetEventCounts(self) -> None:
319
285
  """"""
@@ -395,18 +361,6 @@ class logger_t(base_t):
395
361
  self.intercepts_exceptions = False
396
362
  self.info("Exception Interception: OFF")
397
363
 
398
- def DealWithException(self, _, exc_value, exc_traceback, /) -> None:
399
- """"""
400
- exception = exc_value.with_traceback(exc_traceback)
401
- self.LogException(exception, level=l.CRITICAL)
402
- s.exit(1)
403
-
404
- def DealWithExceptionInThread(
405
- self, exc_type, exc_value, exc_traceback, _, /
406
- ) -> None:
407
- """"""
408
- self.DealWithException(exc_type, exc_value, exc_traceback)
409
-
410
364
  def AddHandler(
411
365
  self,
412
366
  handler_t_or_handler: type[base_handler_t]
@@ -421,12 +375,19 @@ class logger_t(base_t):
421
375
  should_still_hold_messages: bool = False,
422
376
  **kwargs,
423
377
  ) -> None:
424
- """"""
425
- if (not should_still_hold_messages) and self._should_activate_log_interceptions:
426
- self.ToggleLogInterceptions(True)
427
- self._should_activate_log_interceptions = False
378
+ """
379
+ Silently ignores re-holding request after un-holding.
380
+ """
381
+ should_flush_on_hold = False
382
+ new_handler_warning = ""
383
+ if self._should_hold_messages and not should_still_hold_messages:
384
+ if self._should_activate_log_interceptions:
385
+ self.ToggleLogInterceptions(True)
386
+ self._should_activate_log_interceptions = False
428
387
 
429
- self._should_hold_messages = should_still_hold_messages
388
+ self._should_hold_messages = False
389
+ should_flush_on_hold = True
390
+ new_handler_warning = "\n(Handlers added from now on will miss above logs.)"
430
391
 
431
392
  if isinstance(handler_t_or_handler, type):
432
393
  handler = handler_t_or_handler.New(
@@ -436,14 +397,38 @@ class logger_t(base_t):
436
397
  handler = handler_t_or_handler
437
398
  base_t.addHandler(self, handler)
438
399
 
400
+ # Wait until after the handler has been added to flush messages on hold.
401
+ if should_flush_on_hold:
402
+ self._FlushRecordsOnHold()
403
+
439
404
  path = getattr(handler, "baseFilename", "")
440
405
  if isinstance(path, path_t) or (path.__len__() > 0):
441
406
  path = f"\nPath: {path}"
442
407
  self.info(
443
408
  f'New handler "{handler.name}" of type "{type(handler).__name__}" and '
444
409
  f"level {handler.level}={l.getLevelName(handler.level)}{path}"
410
+ f"{new_handler_warning}"
445
411
  )
446
412
 
413
+ def MakeMonochrome(self) -> None:
414
+ """"""
415
+ self.AddHandler(console_handler_t)
416
+
417
+ def MakeRich(self, *, alternating_logs: int = 0) -> None:
418
+ """"""
419
+ if MISSING_RICH_MESSAGE is not None:
420
+ s.__stderr__.write(MISSING_RICH_MESSAGE + "\n")
421
+
422
+ if console_rich_handler_t is console_handler_t:
423
+ handler_kwargs = {}
424
+ else:
425
+ handler_kwargs = {"alternating_logs": alternating_logs}
426
+ self.AddHandler(console_rich_handler_t, **handler_kwargs)
427
+
428
+ def MakePermanent(self, path: str | path_t, /) -> None:
429
+ """"""
430
+ self.AddHandler(file_handler_t, path=path)
431
+
447
432
  def __call__(self, *args, **kwargs) -> None:
448
433
  """
449
434
  For a print-like calling for print-based debugging.
@@ -506,6 +491,18 @@ class logger_t(base_t):
506
491
  message = f"Exception of type {type(exception).__name__}\n----\n{formatted}"
507
492
  self.log(level, message, extra={SHOW_WHERE_ATTR: False})
508
493
 
494
+ def DealWithException(self, _, exc_value, exc_traceback, /) -> None:
495
+ """"""
496
+ exception = exc_value.with_traceback(exc_traceback)
497
+ self.LogException(exception, level=l.CRITICAL)
498
+ s.exit(1)
499
+
500
+ def DealWithExceptionInThread(
501
+ self, exc_type, exc_value, exc_traceback, _, /
502
+ ) -> None:
503
+ """"""
504
+ self.DealWithException(exc_type, exc_value, exc_traceback)
505
+
509
506
  def LogAsIs(self, message: str, /, *, indented: bool = False) -> None:
510
507
  """"""
511
508
  if indented:
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.19"
7
+ __version__ = "2025.21"
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.19
3
+ Version: 2025.21
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=DefgP6TAlC9ZItUKr6xILYjfpSID0x0a7pe5gfQoQ1s,1680
2
+ logger_36/version.py,sha256=uq-1uJ3Ttvm7hNAwg0S3T103Mh6UIamgGGIWFao8YLI,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
@@ -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=LmdiBI1NLzpgI_Mzr6nVBsj9Nu_5iZFGKNKTqGAmdSM,6673
45
+ logger_36/type/handler.py,sha256=ChxP1j9PXLmoiNcsOdxI4bYVdr75v7HeCWp_iYJ2WNY,6602
46
46
  logger_36/type/issue.py,sha256=QHAYf7QgrjJUtF2D46z6X630qTgeP_0FE5hIwf54RsE,2688
47
- logger_36/type/logger.py,sha256=oQy5VrJor6aJYH3KMIRMpbWx9YoR9oWFeSZWYzle2n4,26041
47
+ logger_36/type/logger.py,sha256=-cEc56RRpYkXaoDjI7PF7q14Mamdc4zu3DmQ-lRjIn8,25823
48
48
  logger_36/type/loggers.py,sha256=7EX7Sg_RlduBjdfFlNZmUfNeDloH1xU30Rdkg_-rXh8,3172
49
- logger_36-2025.19.dist-info/METADATA,sha256=o3JDxhFujB13yngrFl9lTrpRoSvLYMev6u9pY06nB_E,6529
50
- logger_36-2025.19.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
- logger_36-2025.19.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
52
- logger_36-2025.19.dist-info/RECORD,,
49
+ logger_36-2025.21.dist-info/METADATA,sha256=bTX5e3Xn8lko_GnzpFd7XnE60aNUv6V_9JyoLwzE2G4,6529
50
+ logger_36-2025.21.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
+ logger_36-2025.21.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
52
+ logger_36-2025.21.dist-info/RECORD,,