logger-36 2025.23__py3-none-any.whl → 2025.25__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.
Files changed (40) hide show
  1. logger_36/api/{gpu.py → chronos.py} +1 -1
  2. logger_36/api/memory.py +0 -9
  3. logger_36/api/storage.py +0 -1
  4. logger_36/catalog/handler/console.py +1 -1
  5. logger_36/catalog/handler/console_rich.py +33 -22
  6. logger_36/catalog/handler/file.py +1 -2
  7. logger_36/catalog/handler/generic.py +24 -10
  8. logger_36/catalog/handler/memory.py +31 -6
  9. logger_36/catalog/logger/chronos.py +10 -2
  10. logger_36/catalog/logger/memory.py +1 -1
  11. logger_36/catalog/logger/system.py +6 -5
  12. logger_36/config/message.py +1 -4
  13. logger_36/{api/system.py → config/rule.py} +2 -1
  14. logger_36/constant/chronos.py +50 -0
  15. logger_36/constant/error.py +2 -0
  16. logger_36/constant/html.py +2 -0
  17. logger_36/constant/message.py +7 -7
  18. logger_36/constant/path.py +8 -7
  19. logger_36/constant/record.py +2 -0
  20. logger_36/constant/rule.py +2 -2
  21. logger_36/{api/time.py → extension/file.py} +18 -2
  22. logger_36/{task → extension}/inspection.py +15 -29
  23. logger_36/extension/line.py +1 -1
  24. logger_36/task/format/memory.py +1 -1
  25. logger_36/task/format/message.py +7 -5
  26. logger_36/task/measure/chronos.py +21 -13
  27. logger_36/task/storage.py +32 -48
  28. logger_36/type/handler.py +26 -32
  29. logger_36/type/issue.py +7 -4
  30. logger_36/type/logger.py +164 -88
  31. logger_36/version.py +1 -1
  32. {logger_36-2025.23.dist-info → logger_36-2025.25.dist-info}/METADATA +30 -44
  33. logger_36-2025.25.dist-info/RECORD +53 -0
  34. logger_36/extension/html_.py +0 -93
  35. logger_36-2025.23.dist-info/RECORD +0 -53
  36. /logger_36/api/{type.py → logger.py} +0 -0
  37. /logger_36/api/{content.py → message.py} +0 -0
  38. /logger_36/{constant/generic.py → extension/sentinel.py} +0 -0
  39. {logger_36-2025.23.dist-info → logger_36-2025.25.dist-info}/WHEEL +0 -0
  40. {logger_36-2025.23.dist-info → logger_36-2025.25.dist-info}/top_level.txt +0 -0
logger_36/type/logger.py CHANGED
@@ -7,6 +7,7 @@ SEE COPYRIGHT NOTICE BELOW
7
7
  import dataclasses as d
8
8
  import inspect as e
9
9
  import logging as l
10
+ import multiprocessing as prll
10
11
  import sys as s
11
12
  import textwrap as text
12
13
  import threading as thrd
@@ -15,7 +16,8 @@ import types as t
15
16
  import typing as h
16
17
  from datetime import date as date_t
17
18
  from datetime import datetime as date_time_t
18
- from os import sep as FOLDER_SEPARATOR
19
+ from logging.handlers import QueueHandler as queue_handler_t
20
+ from logging.handlers import QueueListener as log_server_t
19
21
  from pathlib import Path as path_t
20
22
  from traceback import TracebackException as traceback_t
21
23
 
@@ -27,26 +29,35 @@ from logger_36.catalog.config.optional import (
27
29
  )
28
30
  from logger_36.catalog.handler.console import console_handler_t
29
31
  from logger_36.catalog.handler.file import file_handler_t
32
+ from logger_36.catalog.handler.memory import memory_handler_t, records_h
30
33
  from logger_36.config.issue import ISSUE_CONTEXT_END, ISSUE_CONTEXT_SEPARATOR
31
34
  from logger_36.config.message import (
32
35
  DATE_FORMAT,
33
- ELAPSED_TIME_SEPARATOR,
34
36
  LONG_ENOUGH,
35
37
  TIME_FORMAT,
36
38
  WHERE_SEPARATOR,
37
39
  )
38
- from logger_36.constant.generic import NOT_PASSED
40
+ from logger_36.constant.chronos import DATE_ORIGIN, DATE_TIME_ORIGIN
39
41
  from logger_36.constant.issue import ISSUE_LEVEL_SEPARATOR, ORDER, order_h
40
42
  from logger_36.constant.logger import WARNING_LOGGER_NAME, WARNING_TYPE_COMPILED_PATTERN
41
43
  from logger_36.constant.memory import UNKNOWN_MEMORY_USAGE
42
- from logger_36.constant.message import LINE_INDENT, TIME_LENGTH_m_1, expected_op_h
43
- from logger_36.constant.path import PROJECT_FILE_RELATIVE, USER_FOLDER
44
- from logger_36.constant.record import SHOW_W_RULE_ATTR, SHOW_WHERE_ATTR
44
+ from logger_36.constant.message import LINE_INDENT, expected_op_h
45
+ from logger_36.constant.path import USER_FOLDER, LAUNCH_ROOT_FILE_relative
46
+ from logger_36.constant.record import (
47
+ HAS_ACTUAL_EXPECTED_ATTR,
48
+ SHOW_W_RULE_ATTR,
49
+ SHOW_WHEN_ATTR,
50
+ SHOW_WHERE_ATTR,
51
+ WHEN_OR_ELAPSED_ATTR,
52
+ WHERE_ATTR,
53
+ )
54
+ from logger_36.extension.file import NewTemporaryFile
55
+ from logger_36.extension.sentinel import NOT_PASSED
45
56
  from logger_36.task.format.message import MessageWithActualExpected
46
- from logger_36.task.measure.chronos import ElapsedTime
57
+ from logger_36.task.measure.chronos import FormattedElapsedTime
47
58
  from logger_36.task.measure.memory import CurrentUsage as CurrentMemoryUsage
48
- from logger_36.type.handler import any_handler_t as base_handler_t
49
59
  from logger_36.type.handler import extension_t as handler_extension_t
60
+ from logger_36.type.handler import handler_h as base_handler_h
50
61
  from logger_36.type.issue import NewIssue, issue_t
51
62
 
52
63
  if RICH_IS_AVAILABLE:
@@ -62,8 +73,7 @@ logger_handle_raw_h = h.Callable[[l.LogRecord], None]
62
73
  logger_handle_with_self_h = h.Callable[[l.Logger, l.LogRecord], None]
63
74
  logger_handle_h = logger_handle_raw_h | logger_handle_with_self_h
64
75
 
65
- _DATE_TIME_ORIGIN = date_time_t.fromtimestamp(1970, None)
66
- _DATE_ORIGIN = _DATE_TIME_ORIGIN.date()
76
+ MAIN_PROCESS_NAME = "MainProcess"
67
77
 
68
78
 
69
79
  @d.dataclass(slots=True, repr=False, eq=False)
@@ -85,26 +95,51 @@ class logger_t(base_t):
85
95
  history: dict[date_time_t, str] = d.field(init=False, default_factory=dict)
86
96
  n_events: dict[int, int] = d.field(init=False, default_factory=dict)
87
97
 
88
- last_message_now: date_time_t = d.field(init=False, default=_DATE_TIME_ORIGIN)
89
- last_message_date: date_t = d.field(init=False, default=_DATE_ORIGIN)
98
+ last_message_now: date_time_t = d.field(init=False, default=DATE_TIME_ORIGIN)
99
+ last_message_date: date_t = d.field(init=False, default=DATE_ORIGIN)
90
100
  memory_usages: list[tuple[str, int]] = d.field(init=False, default_factory=list)
91
101
  context_levels: list[str] = d.field(init=False, default_factory=list)
92
- staged_issues: list[issue_t] = d.field(init=False, default_factory=list)
102
+ staged_issues: list[tuple[issue_t, bool]] = d.field(
103
+ init=False, default_factory=list
104
+ )
93
105
  intercepted_wrn_handle: logger_handle_h | None = d.field(init=False, default=None)
94
106
  intercepted_log_handles: dict[str, logger_handle_h] = d.field(
95
107
  init=False, default_factory=dict
96
108
  )
97
109
  intercepts_exceptions: bool = d.field(init=False, default=False)
98
110
 
99
- # Used only until the last handler is added (see AddHandler).
111
+ # Used only until the first handler is added (see AddHandler).
100
112
  _should_activate_log_interceptions: bool = d.field(init=False, default=False)
101
113
 
114
+ log_server: log_server_t | None = d.field(init=False, default=None)
115
+
102
116
  name_: d.InitVar[str | None] = None
103
117
  level_: d.InitVar[int] = l.NOTSET
104
118
  activate_wrn_interceptions: d.InitVar[bool] = True
105
119
  activate_log_interceptions: d.InitVar[bool] = True
106
120
  activate_exc_interceptions: d.InitVar[bool] = True
107
121
 
122
+ @property
123
+ def formatted_history(self) -> str:
124
+ """"""
125
+ FormattedEntry = lambda _: f"{_[0]}: {_[1].replace('\n', '↲ ')}"
126
+ return "\n".join(map(FormattedEntry, self.history.items()))
127
+
128
+ @property
129
+ def records(self) -> records_h | None:
130
+ """"""
131
+ return logger_t.Records(self)
132
+
133
+ @staticmethod
134
+ def Records(logger: base_t | l.Logger, /) -> records_h | None:
135
+ """"""
136
+ for handler in logger.handlers:
137
+ output = getattr(handler, "records", None)
138
+ if memory_handler_t.AreRecords(output):
139
+ return output
140
+
141
+ return None
142
+
108
143
  @property
109
144
  def intercepts_warnings(self) -> bool:
110
145
  """"""
@@ -152,9 +187,15 @@ class logger_t(base_t):
152
187
  activate_exc_interceptions: bool,
153
188
  ) -> None:
154
189
  """"""
190
+ assert prll.current_process().name == MAIN_PROCESS_NAME
191
+
155
192
  if name_ is None:
156
193
  name_ = f"{type(self).__name__}:{hex(id(self))[2:]}"
157
194
 
195
+ self.history[date_time_t.now()] = (
196
+ f'Logger "{name_}" instantiation for "{LAUNCH_ROOT_FILE_relative}"'
197
+ )
198
+
158
199
  base_t.__init__(self, name_)
159
200
  self.setLevel(level_)
160
201
  self.propagate = False # Part of base_t.
@@ -175,44 +216,41 @@ class logger_t(base_t):
175
216
  if self.should_monitor_memory_usage:
176
217
  self.ActivateMemoryUsageMonitoring()
177
218
 
178
- self.history[date_time_t.now()] = (
179
- f'Logger "{self.name}" instantiation for "{PROJECT_FILE_RELATIVE}"'
180
- )
181
-
182
219
  def handle(self, record: l.LogRecord, /) -> None:
183
220
  """"""
184
- elapsed_time, now = ElapsedTime(should_return_now=True)
185
-
221
+ now = date_time_t.now()
186
222
  if (date := now.date()) != self.last_message_date:
187
223
  self._AcknowledgeDateChange(date)
188
224
 
225
+ level = record.levelno
226
+
189
227
  # When.
190
- if now - self.last_message_now > LONG_ENOUGH:
191
- w_or_e = now.strftime(TIME_FORMAT)
192
- else:
193
- w_or_e = f"{ELAPSED_TIME_SEPARATOR}{elapsed_time:.<{TIME_LENGTH_m_1}}"
194
- record.when_or_elapsed = w_or_e
228
+ if getattr(record, SHOW_WHEN_ATTR, True):
229
+ if now - self.last_message_now > LONG_ENOUGH:
230
+ w_or_e = f"{now:{TIME_FORMAT}}"
231
+ else:
232
+ w_or_e = FormattedElapsedTime(now) # or: f"{[...]:.<{TIME_LENGTH}}".
233
+ setattr(record, WHEN_OR_ELAPSED_ATTR, w_or_e)
195
234
  self.last_message_now = now
196
235
 
197
236
  # Where.
198
- should_show_where = getattr(record, SHOW_WHERE_ATTR, record.levelno != l.INFO)
237
+ should_show_where = getattr(record, SHOW_WHERE_ATTR, level != l.INFO)
199
238
  if should_show_where or self.should_monitor_memory_usage:
200
- where = _RecordLocation(record, should_show_where)
201
- else:
202
- where = None
239
+ where = f"{record.pathname}:{record.funcName}:{record.lineno}"
240
+ if should_show_where:
241
+ setattr(record, WHERE_ATTR, where)
242
+ if self.should_monitor_memory_usage:
243
+ self.memory_usages.append((where, CurrentMemoryUsage()))
203
244
 
204
245
  # What.
205
246
  if not isinstance(record.msg, str):
206
247
  record.msg = str(record.msg)
207
248
 
208
249
  base_t.handle(self, record)
209
- self.n_events[record.levelno] += 1
250
+ self.n_events[level] += 1
210
251
 
211
- if self.should_monitor_memory_usage:
212
- self.memory_usages.append((where, CurrentMemoryUsage()))
213
-
214
- if (self.exit_on_critical and (record.levelno is l.CRITICAL)) or (
215
- self.exit_on_error and (record.levelno is l.ERROR)
252
+ if (self.exit_on_critical and (level is l.CRITICAL)) or (
253
+ self.exit_on_error and (level is l.ERROR)
216
254
  ):
217
255
  # Also works if self.exit_on_error and record.levelno is l.CRITICAL since
218
256
  # __post_init__ set self.exit_on_critical if self.exit_on_error.
@@ -226,7 +264,7 @@ class logger_t(base_t):
226
264
  {
227
265
  "name": self.name,
228
266
  "levelno": l.INFO, # For management by logging.Logger.handle.
229
- "msg": f"DATE: {date.strftime(DATE_FORMAT)}",
267
+ "msg": f"DATE: {date:{DATE_FORMAT}}",
230
268
  SHOW_W_RULE_ATTR: True,
231
269
  }
232
270
  )
@@ -332,8 +370,8 @@ class logger_t(base_t):
332
370
 
333
371
  def AddHandler(
334
372
  self,
335
- handler_t_or_handler: type[base_handler_t]
336
- | base_handler_t
373
+ handler_t_or_handler: type[base_handler_h]
374
+ | base_handler_h
337
375
  | l.Handler
338
376
  | l.FileHandler,
339
377
  /,
@@ -386,6 +424,27 @@ class logger_t(base_t):
386
424
  """"""
387
425
  self.AddHandler(file_handler_t, path=path)
388
426
 
427
+ def MakeMultiSafe(self) -> None:
428
+ """
429
+ Should not be called until after all desired handlers have been added (as a
430
+ better-then-nothing check, it is checked that the logger has at least one
431
+ handler). If handlers are added passed this call, execution might freeze or
432
+ crash.
433
+ """
434
+ assert self.log_server is None
435
+ assert self.hasHandlers()
436
+
437
+ handlers = tuple(self.handlers) # Making a copy is necessary.
438
+ for handler in handlers:
439
+ self.removeHandler(handler)
440
+
441
+ queue = prll.Queue()
442
+
443
+ self.addHandler(queue_handler_t(queue))
444
+
445
+ self.log_server = log_server_t(queue, *handlers)
446
+ self.log_server.start()
447
+
389
448
  def __call__(self, *args, **kwargs) -> None:
390
449
  """
391
450
  For a print-like calling for print-based debugging.
@@ -397,7 +456,7 @@ class logger_t(base_t):
397
456
  path = path_t(details.filename)
398
457
  if path.is_relative_to(USER_FOLDER):
399
458
  path = path.relative_to(USER_FOLDER)
400
- where = f"{str(path.with_suffix(''))}.{details.function}.{details.lineno}"
459
+ where = f"{str(path.with_suffix(''))}:{details.function}:{details.lineno}"
401
460
 
402
461
  self.info(separator.join(map(str, args)) + f"\n{WHERE_SEPARATOR} " + where)
403
462
 
@@ -416,7 +475,7 @@ class logger_t(base_t):
416
475
  """"""
417
476
  if isinstance(level, str):
418
477
  level = l.getLevelNamesMapping()[level.upper()]
419
- message = MessageWithActualExpected(
478
+ message, has_actual_expected = MessageWithActualExpected(
420
479
  message,
421
480
  actual=actual,
422
481
  expected=expected,
@@ -424,7 +483,25 @@ class logger_t(base_t):
424
483
  expected_op=expected_op,
425
484
  with_final_dot=with_final_dot,
426
485
  )
427
- self.log(level, message)
486
+ if has_actual_expected:
487
+ extra = {HAS_ACTUAL_EXPECTED_ATTR: True}
488
+ else:
489
+ extra = {}
490
+ self.log(level, message, extra=extra)
491
+
492
+ def LogAsIs(self, message: str, /, *, indented: bool = False) -> None:
493
+ """"""
494
+ if indented:
495
+ message = text.indent(message, LINE_INDENT)
496
+
497
+ for handler in self.handlers:
498
+ EmitMessage = getattr(
499
+ handler, handler_extension_t.EmitMessage.__name__, None
500
+ )
501
+ if EmitMessage is not None:
502
+ EmitMessage(message)
503
+
504
+ info_raw = LogAsIs # To follow the convention of the logging methods info, error...
428
505
 
429
506
  def LogException(
430
507
  self,
@@ -454,25 +531,9 @@ class logger_t(base_t):
454
531
  self.LogException(exception, level=l.CRITICAL)
455
532
  s.exit(1)
456
533
 
457
- def DealWithExceptionInThread(
458
- self, exc_type, exc_value, exc_traceback, _, /
459
- ) -> None:
534
+ def DealWithExceptionInThread(self, args, /) -> None:
460
535
  """"""
461
- self.DealWithException(exc_type, exc_value, exc_traceback)
462
-
463
- def LogAsIs(self, message: str, /, *, indented: bool = False) -> None:
464
- """"""
465
- if indented:
466
- message = text.indent(message, LINE_INDENT)
467
-
468
- for handler in self.handlers:
469
- EmitMessage = getattr(
470
- handler, handler_extension_t.EmitMessage.__name__, None
471
- )
472
- if EmitMessage is not None:
473
- EmitMessage(message)
474
-
475
- info_raw = LogAsIs # To follow the convention of the logging methods info, error...
536
+ self.DealWithException(args.exc_type, args.exc_value, args.exc_traceback)
476
537
 
477
538
  def DisplayRule(
478
539
  self, /, *, message: str | None = None, color: str = "white"
@@ -523,7 +584,9 @@ class logger_t(base_t):
523
584
  )
524
585
  self.staged_issues.append(issue)
525
586
 
526
- def PopIssues(self, /, *, should_remove_context: bool = False) -> list[str]:
587
+ def PopIssues(
588
+ self, /, *, should_remove_context: bool = False
589
+ ) -> list[tuple[str, bool]]:
527
590
  """"""
528
591
  if not self.has_staged_issues:
529
592
  return []
@@ -535,10 +598,10 @@ class logger_t(base_t):
535
598
  else:
536
599
  separator = ISSUE_LEVEL_SEPARATOR
537
600
  separator_length = separator.__len__()
538
- for issue in self.staged_issues:
601
+ for issue, has_actual_expected in self.staged_issues:
539
602
  start_idx = issue.find(separator)
540
603
  issue = issue[(start_idx + separator_length) :]
541
- output.append(issue)
604
+ output.append((issue, has_actual_expected))
542
605
 
543
606
  self.staged_issues.clear()
544
607
 
@@ -560,13 +623,16 @@ class logger_t(base_t):
560
623
  "Invalid commit order",
561
624
  actual=order,
562
625
  expected=f"One of {str(ORDER)[1:-1]}",
563
- )
626
+ )[0]
564
627
  )
565
628
 
566
629
  if order == "when":
567
630
  issues = self.staged_issues
568
631
  else: # order == "context"
569
- issues = sorted(self.staged_issues, key=lambda _: _.context)
632
+ issues = sorted(
633
+ self.staged_issues,
634
+ key=lambda _: _[0].split(ISSUE_LEVEL_SEPARATOR, maxsplit=1)[1],
635
+ )
570
636
  """
571
637
  Format issues as an exception:
572
638
  try:
@@ -578,20 +644,43 @@ class logger_t(base_t):
578
644
  formatted = "\n".join(lines)
579
645
  """
580
646
 
581
- hide_where = {SHOW_WHERE_ATTR: False}
647
+ extra = {SHOW_WHERE_ATTR: False}
582
648
  if unified:
583
- level, _ = issues[0].split(ISSUE_LEVEL_SEPARATOR, maxsplit=1)
649
+ level, _ = issues[0][0].split(ISSUE_LEVEL_SEPARATOR, maxsplit=1)
584
650
  wo_level = []
585
- for issue in issues:
651
+ any_has_actual_expected = False
652
+ for issue, has_actual_expected in issues:
586
653
  _, issue = issue.split(ISSUE_LEVEL_SEPARATOR, maxsplit=1)
654
+ if has_actual_expected:
655
+ any_has_actual_expected = True
587
656
  wo_level.append(issue)
588
- self.log(int(level), "\n".join(wo_level), stacklevel=2, extra=hide_where)
657
+ if any_has_actual_expected:
658
+ extra[HAS_ACTUAL_EXPECTED_ATTR] = True
659
+ self.log(int(level), "\n".join(wo_level), stacklevel=2, extra=extra)
589
660
  else:
590
- for issue in issues:
661
+ for issue, has_actual_expected in issues:
591
662
  level, issue = issue.split(ISSUE_LEVEL_SEPARATOR, maxsplit=1)
592
- self.log(int(level), issue, stacklevel=2, extra=hide_where)
663
+ if has_actual_expected:
664
+ extra[HAS_ACTUAL_EXPECTED_ATTR] = True
665
+ self.log(int(level), issue, stacklevel=2, extra=extra)
666
+ if has_actual_expected:
667
+ del extra[HAS_ACTUAL_EXPECTED_ATTR]
593
668
  self.staged_issues.clear()
594
669
 
670
+ def StoragePath(self, suffix: str, /) -> path_t:
671
+ """
672
+ Use as staticmethod if needed.
673
+ """
674
+ for handler in self.handlers:
675
+ if (path := getattr(handler, "baseFilename", None)) is not None:
676
+ output = path_t(path).with_suffix(suffix)
677
+ if output.exists():
678
+ output = NewTemporaryFile(suffix)
679
+
680
+ return output
681
+
682
+ return NewTemporaryFile(suffix)
683
+
595
684
  def __enter__(self) -> None:
596
685
  """"""
597
686
  pass
@@ -607,25 +696,12 @@ class logger_t(base_t):
607
696
  _ = self.context_levels.pop()
608
697
  return False
609
698
 
699
+ def __del__(self) -> None:
700
+ """"""
701
+ assert prll.current_process().name == MAIN_PROCESS_NAME
610
702
 
611
- def _RecordLocation(record: l.LogRecord, should_also_store: bool, /) -> str:
612
- """"""
613
- module = path_t(record.pathname)
614
- for path in s.path:
615
- if module.is_relative_to(path):
616
- module = module.relative_to(path).with_suffix("")
617
- module = str(module).replace(FOLDER_SEPARATOR, ".")
618
- break
619
- else:
620
- if module.is_relative_to(USER_FOLDER):
621
- module = module.relative_to(USER_FOLDER)
622
-
623
- output = f"{module}:{record.funcName}:{record.lineno}"
624
-
625
- if should_also_store:
626
- record.where = output
627
-
628
- return output
703
+ if self.log_server is not None:
704
+ self.log_server.stop()
629
705
 
630
706
 
631
707
  def _HandleForWarnings(interceptor: base_t, /) -> logger_handle_h:
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.23"
7
+ __version__ = "2025.25"
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.23
3
+ Version: 2025.25
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
@@ -109,46 +109,32 @@ The code is formatted by `Black <https://github.com/psf/black/>`_, *The Uncompro
109
109
  The imports are ordered by `isort <https://github.com/timothycrosley/isort/>`_... *your imports, so you don't have to*.
110
110
 
111
111
  ..
112
- COPYRIGHT NOTICE
113
-
114
- This software is governed by the CeCILL license under French law and
115
- abiding by the rules of distribution of free software. You can use,
116
- modify and/ or redistribute the software under the terms of the CeCILL
117
- license as circulated by CEA, CNRS and INRIA at the following URL
118
- "http://www.cecill.info".
119
-
120
- As a counterpart to the access to the source code and rights to copy,
121
- modify and redistribute granted by the license, users are provided only
122
- with a limited warranty and the software's author, the holder of the
123
- economic rights, and the successive licensors have only limited
124
- liability.
125
-
126
- In this respect, the user's attention is drawn to the risks associated
127
- with loading, using, modifying and/or developing or reproducing the
128
- software by the user in light of its specific status of free software,
129
- that may mean that it is complicated to manipulate, and that also
130
- therefore means that it is reserved for developers and experienced
131
- professionals having in-depth computer knowledge. Users are therefore
132
- encouraged to load and test the software's suitability as regards their
133
- requirements in conditions enabling the security of their systems and/or
134
- data to be ensured and, more generally, to use and operate it in the
135
- same conditions as regards security.
136
-
137
- The fact that you are presently reading this means that you have had
138
- knowledge of the CeCILL license and that you accept its terms.
139
-
140
- SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
141
-
142
- This software is being developed by Eric Debreuve, a CNRS employee and
143
- member of team Morpheme.
144
- Team Morpheme is a joint team between Inria, CNRS, and UniCA.
145
- It is hosted by the Centre Inria d'Université Côte d'Azur, Laboratory
146
- I3S, and Laboratory iBV.
147
-
148
- CNRS: https://www.cnrs.fr/index.php/en
149
- Inria: https://www.inria.fr/en/
150
- UniCA: https://univ-cotedazur.eu/
151
- Centre Inria d'Université Côte d'Azur: https://www.inria.fr/en/centre/sophia/
152
- I3S: https://www.i3s.unice.fr/en/
153
- iBV: http://ibv.unice.fr/
154
- Team Morpheme: https://team.inria.fr/morpheme/
112
+ COPYRIGHT NOTICE
113
+
114
+ This software is governed by the CeCILL license under French law and
115
+ abiding by the rules of distribution of free software. You can use,
116
+ modify and/ or redistribute the software under the terms of the CeCILL
117
+ license as circulated by CEA, CNRS and INRIA at the following URL
118
+ "http://www.cecill.info".
119
+
120
+ As a counterpart to the access to the source code and rights to copy,
121
+ modify and redistribute granted by the license, users are provided only
122
+ with a limited warranty and the software's author, the holder of the
123
+ economic rights, and the successive licensors have only limited
124
+ liability.
125
+
126
+ In this respect, the user's attention is drawn to the risks associated
127
+ with loading, using, modifying and/or developing or reproducing the
128
+ software by the user in light of its specific status of free software,
129
+ that may mean that it is complicated to manipulate, and that also
130
+ therefore means that it is reserved for developers and experienced
131
+ professionals having in-depth computer knowledge. Users are therefore
132
+ encouraged to load and test the software's suitability as regards their
133
+ requirements in conditions enabling the security of their systems and/or
134
+ data to be ensured and, more generally, to use and operate it in the
135
+ same conditions as regards security.
136
+
137
+ The fact that you are presently reading this means that you have had
138
+ knowledge of the CeCILL license and that you accept its terms.
139
+
140
+ SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
@@ -0,0 +1,53 @@
1
+ logger_36/__init__.py,sha256=mK6AD0eWI2Sk42oxleTvsxzYJ28FbHK5WNkpLgAhnNE,2129
2
+ logger_36/version.py,sha256=gqr9_xGceDfeDrDRv0O1e-8Rn6mXcEV_iFdCtiuTyAk,1680
3
+ logger_36/api/chronos.py,sha256=o_UMZbeExjb01aNURmzIjOMAHhI9e90nyvJJYcJR6VQ,1739
4
+ logger_36/api/logger.py,sha256=eLZ2yuH-sYeh4Z2KnAwTRJEbmkmgzBPMncdqXfFUTG8,1760
5
+ logger_36/api/memory.py,sha256=U4mMEkx8WRHk9q2d3SCFGt2EJaBuflOXw2bGbAxOnSc,1828
6
+ logger_36/api/message.py,sha256=DuT4UX4r_1DTXzuuRD-tvsTZk5X-Nj11loBKhuWOMw0,1791
7
+ logger_36/api/storage.py,sha256=S1fVzrMp-_zlhg27fRPddWCFQRyvbpFwSreALOeoNFI,1713
8
+ logger_36/catalog/config/console_rich.py,sha256=t9p9-AkSgPiLAsm1evAdbz77g7JcVLePhUJ1FzNi3cY,2330
9
+ logger_36/catalog/config/optional.py,sha256=8d8HdpE07gHfsdoL8mVAlRlh9AgLcb4z7I7h6ob7CfU,2174
10
+ logger_36/catalog/handler/console.py,sha256=XIyO_8MrzaTlihDbFhIzRk47HjxMH4gV2Zqp0-1oMsU,2320
11
+ logger_36/catalog/handler/console_rich.py,sha256=RXLu8AQxAmyec1bXUc99Mabp7BjZc-lKEfwrCzMPkZA,6662
12
+ logger_36/catalog/handler/file.py,sha256=5GR_aACDEBXuZ-pUH9P0OCaXbCf-aLPmsz-XrGCAIgE,2434
13
+ logger_36/catalog/handler/generic.py,sha256=kwr7x7GWLmWvT7niHGW7OqlMotvTQNuNEwQGfKh_nhU,7040
14
+ logger_36/catalog/handler/memory.py,sha256=pJwKOlCm8Ej8ipDI00-FfX4qJjMPXJb-DucD1ukIQOU,4057
15
+ logger_36/catalog/logger/chronos.py,sha256=MDAx_NRRcRZcQYDDjVCRcu87SDP-rPYjX0-10KNcMnk,2216
16
+ logger_36/catalog/logger/gpu.py,sha256=Py5YY0nD_pqJzJsEKQYoOGHcPqyNVJ3J2noOS3hDL6g,2890
17
+ logger_36/catalog/logger/memory.py,sha256=pa-9pkvDGdf52giwL3Zi1mjWNFE_NVzBGdjwcfeIDNc,4256
18
+ logger_36/catalog/logger/system.py,sha256=zEbHirATqZAVYFmHLd0pppeuRhka1ucWwyHRq0afQNE,2593
19
+ logger_36/config/issue.py,sha256=QOkVRPSLZC_2mfcFpad-pcSXJXfLHdWUAXiMbTWlZTg,1741
20
+ logger_36/config/memory.py,sha256=bZmNYsD2goVdkraS1v_t2OqAJo86jKMtP311kIVURDk,1691
21
+ logger_36/config/message.py,sha256=bDAW4hZdsHBTYlCA7IZbL1FxGPwjX9Khmw0d21VHGs0,1968
22
+ logger_36/config/rule.py,sha256=BqOb4SWKgT0YQZ-DtOzkLNZNWZVZkl5GN3lMoWoPrKw,1702
23
+ logger_36/config/system.py,sha256=YRSa2eN_SoTnTXWUXAcpKt4JXifabzMR0eXwjUYlA_A,1951
24
+ logger_36/constant/chronos.py,sha256=JJvBN_skqRdUgnuWhMqG0gZ3_ZkXmAz1syEixfu4lCM,2131
25
+ logger_36/constant/error.py,sha256=FinnCcwGGH2oiXX3aw2uxKYvR3d5Tkb9rlNhNjyuoF8,2354
26
+ logger_36/constant/html.py,sha256=w8gttc1XBSMpdKRolnXAVJ5x_hOAIsVsUyELCXJYdWU,2011
27
+ logger_36/constant/issue.py,sha256=0EmcsRmSxktFUJR0qOU0PnKG-gfbLDOULH6sSRHFOcc,1789
28
+ logger_36/constant/logger.py,sha256=ZQYX9JiPsoivwRgYNtdEqRKCagSKD88lRqvxP8MX1ZE,1942
29
+ logger_36/constant/memory.py,sha256=Q_E5tTWa-cGaNwrE_xmKa3BxQG6oJO6DHczrxc_M4sE,1817
30
+ logger_36/constant/message.py,sha256=TdsZXWO2UmlG3a0ia3UsUCxtVUa8GNferi69pO4A9TM,2301
31
+ logger_36/constant/path.py,sha256=r-vx5ztGhcpYfg37kw0oaxBYdTSkWOJuToTmexaW8tE,2265
32
+ logger_36/constant/record.py,sha256=70JO2LYL-1Eg-vLD3N7nUoYALp6ji7-b3DLxCHTc7iQ,1881
33
+ logger_36/constant/rule.py,sha256=ul-MqOdHBGBC5Nwn05EUnz2T__7VEs82qiH7Fzs5qCk,1804
34
+ logger_36/constant/system.py,sha256=pLlLXG5sepQlSUOo3TphaGrHg8xzJBp-GxpL2NPP47k,1904
35
+ logger_36/extension/file.py,sha256=ClY8k805DnB6Vy0LEQIhlO0MavP91Y-CEjHjFepyROE,2034
36
+ logger_36/extension/inspection.py,sha256=LoHXi4wsIgHKrq_7GYkVcfJ9rnBG16pLKMpAoHNwJiY,3922
37
+ logger_36/extension/line.py,sha256=9BgxnY6wiyc44Ari5rkvqbvz9ao4sNs39u8k7sY6vFc,2611
38
+ logger_36/extension/sentinel.py,sha256=SQgkQiRcTIjCRvbxiOb6TEm59BC0FNMcjYoIShpcwLo,1718
39
+ logger_36/instance/logger.py,sha256=X_U10RYU1h2Aa70D8hBnmFyJZtRILK16KN-GB4xkHMU,1782
40
+ logger_36/instance/loggers.py,sha256=inBk4KKrQ-z3szaopQ29-qQwh1iSc842sWo5J6zJoiM,1725
41
+ logger_36/task/storage.py,sha256=L93v5w9p_7MoiagEr3d6QSYEQxX42DxmZ-BJTCuLpgQ,3915
42
+ logger_36/task/format/memory.py,sha256=xcWwbUnl1BxH7RVBHyhp1RlbT2n370PzoFLLLd3dtlU,3726
43
+ logger_36/task/format/message.py,sha256=Q9QkyUAU47Nj606zsvq0gNyso8Vk9G9OaqG9Em5FjKg,3575
44
+ logger_36/task/measure/chronos.py,sha256=fZKK16LwlLzRRAP-gfF1uy6gFCL33gR7LZ4Xs_nXdVY,2612
45
+ logger_36/task/measure/memory.py,sha256=kkPHEIUTUhkCOLrAt01eLJLnsnkl0nFPNhFZdIB_JAw,1991
46
+ logger_36/type/handler.py,sha256=bDsCFYpevCJBV7Vc9jovttapjU-7GXI1_TDbmOf2kN4,6660
47
+ logger_36/type/issue.py,sha256=M2KeQwzDG9yqgdtbyWk5Y-ier7c71TuAKlNCf5QCGzY,2770
48
+ logger_36/type/logger.py,sha256=0OjqyMcBAyS0qUUeEzweALrs0m5rVqZF3e6R1b8B4RA,27358
49
+ logger_36/type/loggers.py,sha256=7EX7Sg_RlduBjdfFlNZmUfNeDloH1xU30Rdkg_-rXh8,3172
50
+ logger_36-2025.25.dist-info/METADATA,sha256=Uchfn7mGuqLow-qAR-TejGvwkXNns2N7XnpLbgHeGFE,5980
51
+ logger_36-2025.25.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
52
+ logger_36-2025.25.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
53
+ logger_36-2025.25.dist-info/RECORD,,