logger-36 2025.23__tar.gz → 2025.24__tar.gz

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 (65) hide show
  1. {logger_36-2025.23 → logger_36-2025.24}/PKG-INFO +1 -1
  2. logger_36-2025.24/package/logger_36/api/memory.py +40 -0
  3. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/api/storage.py +0 -1
  4. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/api/time.py +0 -1
  5. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/handler/console.py +1 -1
  6. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/handler/console_rich.py +1 -1
  7. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/handler/generic.py +1 -1
  8. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/handler/memory.py +8 -5
  9. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/logger/system.py +6 -5
  10. logger_36-2025.23/package/logger_36/api/system.py → logger_36-2025.24/package/logger_36/config/rule.py +2 -1
  11. logger_36-2025.24/package/logger_36/constant/date_time.py +46 -0
  12. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/path.py +8 -7
  13. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/rule.py +2 -2
  14. {logger_36-2025.23/package/logger_36/task → logger_36-2025.24/package/logger_36/extension}/inspection.py +15 -29
  15. logger_36-2025.24/package/logger_36/extension/record.py +66 -0
  16. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/task/measure/chronos.py +2 -4
  17. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/task/storage.py +11 -2
  18. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/type/handler.py +6 -10
  19. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/type/logger.py +34 -50
  20. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/version.py +1 -1
  21. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36.egg-info/PKG-INFO +1 -1
  22. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36.egg-info/SOURCES.txt +6 -6
  23. logger_36-2025.23/package/logger_36/api/gpu.py +0 -39
  24. logger_36-2025.23/package/logger_36/api/memory.py +0 -49
  25. logger_36-2025.23/package/logger_36/extension/html_.py +0 -93
  26. {logger_36-2025.23 → logger_36-2025.24}/MANIFEST.in +0 -0
  27. {logger_36-2025.23 → logger_36-2025.24}/README-COPYRIGHT-utf8.txt +0 -0
  28. {logger_36-2025.23 → logger_36-2025.24}/README-LICENCE-utf8.txt +0 -0
  29. {logger_36-2025.23 → logger_36-2025.24}/README.rst +0 -0
  30. {logger_36-2025.23 → logger_36-2025.24}/documentation/wiki/description.asciidoc +0 -0
  31. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/__init__.py +0 -0
  32. /logger_36-2025.23/package/logger_36/api/type.py → /logger_36-2025.24/package/logger_36/api/logger.py +0 -0
  33. /logger_36-2025.23/package/logger_36/api/content.py → /logger_36-2025.24/package/logger_36/api/message.py +0 -0
  34. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/config/console_rich.py +0 -0
  35. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/config/optional.py +0 -0
  36. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/handler/file.py +0 -0
  37. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/logger/chronos.py +0 -0
  38. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/logger/gpu.py +0 -0
  39. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/catalog/logger/memory.py +0 -0
  40. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/config/issue.py +0 -0
  41. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/config/memory.py +0 -0
  42. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/config/message.py +0 -0
  43. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/config/system.py +0 -0
  44. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/error.py +0 -0
  45. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/generic.py +0 -0
  46. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/html.py +0 -0
  47. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/issue.py +0 -0
  48. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/logger.py +0 -0
  49. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/memory.py +0 -0
  50. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/message.py +0 -0
  51. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/record.py +0 -0
  52. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/constant/system.py +0 -0
  53. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/extension/line.py +0 -0
  54. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/instance/logger.py +0 -0
  55. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/instance/loggers.py +0 -0
  56. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/task/format/memory.py +0 -0
  57. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/task/format/message.py +0 -0
  58. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/task/measure/memory.py +0 -0
  59. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/type/issue.py +0 -0
  60. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36/type/loggers.py +0 -0
  61. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36.egg-info/dependency_links.txt +0 -0
  62. {logger_36-2025.23 → logger_36-2025.24}/package/logger_36.egg-info/top_level.txt +0 -0
  63. {logger_36-2025.23 → logger_36-2025.24}/pyproject.toml +0 -0
  64. {logger_36-2025.23 → logger_36-2025.24}/setup.cfg +0 -0
  65. {logger_36-2025.23 → logger_36-2025.24}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: logger-36
3
- Version: 2025.23
3
+ Version: 2025.24
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
@@ -0,0 +1,40 @@
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
+ from logger_36.task.measure.memory import CanCheckUsage as CanCheckMemoryUsage # noqa
8
+ from logger_36.task.measure.memory import CurrentUsage as CurrentMemoryUsage # noqa
9
+
10
+ """
11
+ COPYRIGHT NOTICE
12
+
13
+ This software is governed by the CeCILL license under French law and
14
+ abiding by the rules of distribution of free software. You can use,
15
+ modify and/ or redistribute the software under the terms of the CeCILL
16
+ license as circulated by CEA, CNRS and INRIA at the following URL
17
+ "http://www.cecill.info".
18
+
19
+ As a counterpart to the access to the source code and rights to copy,
20
+ modify and redistribute granted by the license, users are provided only
21
+ with a limited warranty and the software's author, the holder of the
22
+ economic rights, and the successive licensors have only limited
23
+ liability.
24
+
25
+ In this respect, the user's attention is drawn to the risks associated
26
+ with loading, using, modifying and/or developing or reproducing the
27
+ software by the user in light of its specific status of free software,
28
+ that may mean that it is complicated to manipulate, and that also
29
+ therefore means that it is reserved for developers and experienced
30
+ professionals having in-depth computer knowledge. Users are therefore
31
+ encouraged to load and test the software's suitability as regards their
32
+ requirements in conditions enabling the security of their systems and/or
33
+ data to be ensured and, more generally, to use and operate it in the
34
+ same conditions as regards security.
35
+
36
+ The fact that you are presently reading this means that you have had
37
+ knowledge of the CeCILL license and that you accept its terms.
38
+
39
+ SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
40
+ """
@@ -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
- from logger_36.extension.html_ import html_content_t # noqa
8
7
  from logger_36.task.storage import SaveLOGasHTML # noqa
9
8
 
10
9
  """
@@ -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
- from logger_36.catalog.logger.chronos import LogElapsedTime # noqa
8
7
  from logger_36.task.measure.chronos import ElapsedTime, TimeStamp # noqa
9
8
 
10
9
  """
@@ -8,7 +8,7 @@ import logging as l
8
8
  import sys as s
9
9
  import typing as h
10
10
 
11
- from logger_36.type.handler import handler_t as base_t
11
+ from logger_36.type.handler import non_file_handler_t as base_t
12
12
 
13
13
 
14
14
  class console_handler_t(base_t):
@@ -26,7 +26,7 @@ from logger_36.catalog.config.console_rich import (
26
26
  )
27
27
  from logger_36.config.message import ACTUAL_PATTERNS, EXPECTED_PATTERNS, WHERE_SEPARATOR
28
28
  from logger_36.constant.message import CONTEXT_LENGTH
29
- from logger_36.type.handler import handler_t as base_t
29
+ from logger_36.type.handler import non_file_handler_t as base_t
30
30
 
31
31
  _COMMON_TRACEBACK_ARGUMENTS = ("theme", "width")
32
32
  _EXCLUSIVE_TRACEBACK_ARGUMENTS = (
@@ -23,7 +23,7 @@ else:
23
23
  RULE_COLOR
24
24
  ) = HighlightedVersion = None
25
25
 
26
- from logger_36.type.handler import handler_t as base_t
26
+ from logger_36.type.handler import non_file_handler_t as base_t
27
27
 
28
28
 
29
29
  class generic_handler_t(base_t):
@@ -8,9 +8,9 @@ import json
8
8
  import logging as l
9
9
  import typing as h
10
10
 
11
- from logger_36.type.handler import handler_t as base_t
11
+ from logger_36.type.handler import non_file_handler_t as base_t
12
12
 
13
- formats_h = h.Literal["json", "message", "raw"]
13
+ formats_h = h.Literal["dict", "json", "message", "raw"]
14
14
 
15
15
 
16
16
  class memory_handler_t(base_t):
@@ -45,11 +45,14 @@ class memory_handler_t(base_t):
45
45
 
46
46
  if self.format_ == "raw":
47
47
  is_not_a_rule = True
48
- elif self.format_ == "message":
49
- record, is_not_a_rule = self.MessageFromRecord(record)
50
- else:
48
+ elif self.format_ == "dict":
49
+ record = dict(record.__dict__)
50
+ is_not_a_rule = True
51
+ elif self.format_ == "json":
51
52
  record = json.dumps(record.__dict__)
52
53
  is_not_a_rule = True
54
+ else:
55
+ record, is_not_a_rule = self.MessageFromRecord(record)
53
56
 
54
57
  self.records.append((level, record, is_not_a_rule))
55
58
 
@@ -5,16 +5,17 @@ SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
7
  from logger_36.constant.system import MAX_DETAIL_NAME_LENGTH, SYSTEM_DETAILS_AS_DICT
8
+ from logger_36.extension.inspection import Modules
8
9
  from logger_36.instance.logger import L
9
- from logger_36.task.inspection import Modules
10
10
  from logger_36.type.logger import logger_t
11
11
 
12
12
 
13
13
  def LogSystemDetails(
14
14
  *,
15
+ should_restrict_modules_to_loaded: bool = True,
15
16
  modules_with_version: bool = True,
16
17
  modules_formatted: bool = True,
17
- should_restrict_modules_to_loaded: bool = True,
18
+ indent: int = 4,
18
19
  logger: logger_t = L,
19
20
  ) -> None:
20
21
  """"""
@@ -23,10 +24,10 @@ def LogSystemDetails(
23
24
  for _key, _vle in SYSTEM_DETAILS_AS_DICT.items()
24
25
  )
25
26
  modules = Modules(
26
- modules_with_version,
27
- modules_formatted,
28
27
  only_loaded=should_restrict_modules_to_loaded,
29
- indent=4,
28
+ with_version=modules_with_version,
29
+ formatted=modules_formatted,
30
+ indent=indent,
30
31
  )
31
32
 
32
33
  logger.info(
@@ -4,7 +4,8 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
- from logger_36.catalog.logger.system import LogSystemDetails # noqa
7
+ RULE_CHARACTER = "-"
8
+ DEFAULT_RULE_LENGTH = 50
8
9
 
9
10
  """
10
11
  COPYRIGHT NOTICE
@@ -0,0 +1,46 @@
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
+ from datetime import datetime as date_time_t
8
+
9
+ # This module is imported early. Therefore, the current date and time should be close
10
+ # enough to the real start date and time of the main script.
11
+ START_DATE_TIME = date_time_t.now()
12
+
13
+ DATE_TIME_ORIGIN = date_time_t.fromtimestamp(1970, None)
14
+ DATE_ORIGIN = DATE_TIME_ORIGIN.date()
15
+
16
+ """
17
+ COPYRIGHT NOTICE
18
+
19
+ This software is governed by the CeCILL license under French law and
20
+ abiding by the rules of distribution of free software. You can use,
21
+ modify and/ or redistribute the software under the terms of the CeCILL
22
+ license as circulated by CEA, CNRS and INRIA at the following URL
23
+ "http://www.cecill.info".
24
+
25
+ As a counterpart to the access to the source code and rights to copy,
26
+ modify and redistribute granted by the license, users are provided only
27
+ with a limited warranty and the software's author, the holder of the
28
+ economic rights, and the successive licensors have only limited
29
+ liability.
30
+
31
+ In this respect, the user's attention is drawn to the risks associated
32
+ with loading, using, modifying and/or developing or reproducing the
33
+ software by the user in light of its specific status of free software,
34
+ that may mean that it is complicated to manipulate, and that also
35
+ therefore means that it is reserved for developers and experienced
36
+ professionals having in-depth computer knowledge. Users are therefore
37
+ encouraged to load and test the software's suitability as regards their
38
+ requirements in conditions enabling the security of their systems and/or
39
+ data to be ensured and, more generally, to use and operate it in the
40
+ same conditions as regards security.
41
+
42
+ The fact that you are presently reading this means that you have had
43
+ knowledge of the CeCILL license and that you accept its terms.
44
+
45
+ SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
46
+ """
@@ -12,15 +12,16 @@ USER_FOLDER = path_t.home()
12
12
 
13
13
  frame = e.stack(context=0)[-1] # -1=root caller.
14
14
  if path_t(frame.filename).exists():
15
- PROJECT_FILE = path_t(frame.filename)
16
- if PROJECT_FILE.is_relative_to(USER_FOLDER):
17
- PROJECT_FILE_RELATIVE = PROJECT_FILE.relative_to(USER_FOLDER)
15
+ LAUNCH_ROOT_FILE = path_t(frame.filename)
16
+ LAUNCH_FOLDER = LAUNCH_ROOT_FILE.parent
17
+
18
+ if LAUNCH_ROOT_FILE.is_relative_to(USER_FOLDER):
19
+ LAUNCH_ROOT_FILE_relative = LAUNCH_ROOT_FILE.relative_to(USER_FOLDER)
18
20
  else:
19
- PROJECT_FILE_RELATIVE = PROJECT_FILE
20
- PROJECT_FOLDER = PROJECT_FILE.parent
21
+ LAUNCH_ROOT_FILE_relative = LAUNCH_ROOT_FILE
21
22
  else:
22
- PROJECT_FILE = PROJECT_FILE_RELATIVE = "<unknown>"
23
- PROJECT_FOLDER = path_t(tmps.mkdtemp())
23
+ LAUNCH_ROOT_FILE = LAUNCH_ROOT_FILE_relative = "<unknown launch root file>"
24
+ LAUNCH_FOLDER = path_t(tmps.mkdtemp())
24
25
 
25
26
  """
26
27
  COPYRIGHT NOTICE
@@ -4,9 +4,9 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
- RULE_CHARACTER = "-"
7
+ from logger_36.config.rule import DEFAULT_RULE_LENGTH, RULE_CHARACTER
8
+
8
9
  MIN_HALF_RULE_LENGTH = 4
9
- DEFAULT_RULE_LENGTH = 50
10
10
  DEFAULT_RULE = DEFAULT_RULE_LENGTH * RULE_CHARACTER
11
11
 
12
12
  """
@@ -4,14 +4,16 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
- import importlib.metadata as mprt
8
7
  import pkgutil as pkgs
9
8
  import sys as s
10
- from types import FunctionType, MethodType
11
9
 
12
10
 
13
11
  def Modules(
14
- with_version: bool, formatted: bool, /, *, only_loaded: bool = True, indent: int = 0
12
+ *,
13
+ only_loaded: bool = True,
14
+ with_version: bool = True,
15
+ formatted: bool = False,
16
+ indent: int = 0,
15
17
  ) -> tuple[str, ...] | str:
16
18
  """"""
17
19
  output = []
@@ -61,23 +63,6 @@ def Modules(
61
63
  return tuple(output)
62
64
 
63
65
 
64
- def WhereFunction(function: FunctionType, /) -> str:
65
- """"""
66
- return f"{function.__module__}:{function.__name__}"
67
-
68
-
69
- def WhereMethod(instance: object, method: MethodType, /) -> str:
70
- """
71
- method: Could be a str instead, which would require changing method.__name__ into
72
- getattr(cls, method). But if the method name changes while forgetting to change the
73
- string in the call to WhereMethod accordingly, then an exception would be raised
74
- here.
75
- """
76
- cls = instance.__class__
77
-
78
- return f"{cls.__module__}:{cls.__name__}:{method.__name__}"
79
-
80
-
81
66
  def _ModulesUsingPkgUtil() -> tuple[str, ...]:
82
67
  """
83
68
  Returns more results than using importlib.
@@ -91,15 +76,16 @@ def _ModulesUsingPkgUtil() -> tuple[str, ...]:
91
76
  )
92
77
 
93
78
 
94
- def _ModulesUsingImportlib() -> tuple[str, ...]:
95
- """"""
96
- return tuple(
97
- sorted(
98
- _elm
99
- for _elm in mprt.packages_distributions()
100
- if (_elm[0] != "_") and ("__" not in _elm) and ("/" not in _elm)
101
- )
102
- )
79
+ # import importlib.metadata as mprt
80
+ # def _ModulesUsingImportlib() -> tuple[str, ...]:
81
+ # """"""
82
+ # return tuple(
83
+ # sorted(
84
+ # _elm
85
+ # for _elm in mprt.packages_distributions()
86
+ # if (_elm[0] != "_") and ("__" not in _elm) and ("/" not in _elm)
87
+ # )
88
+ # )
103
89
 
104
90
 
105
91
  """
@@ -0,0 +1,66 @@
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 logging as l
8
+ import sys as s
9
+ from os import sep as FOLDER_SEPARATOR
10
+ from pathlib import Path as path_t
11
+
12
+ from logger_36.constant.path import USER_FOLDER
13
+ from logger_36.constant.record import WHERE_ATTR
14
+
15
+
16
+ def RecordLocation(record: l.LogRecord, should_also_store: bool, /) -> str:
17
+ """"""
18
+ module = path_t(record.pathname)
19
+ for path in s.path:
20
+ if module.is_relative_to(path):
21
+ module = module.relative_to(path).with_suffix("")
22
+ module = str(module).replace(FOLDER_SEPARATOR, ".")
23
+ break
24
+ else:
25
+ if module.is_relative_to(USER_FOLDER):
26
+ module = module.relative_to(USER_FOLDER)
27
+
28
+ output = f"{module}:{record.funcName}:{record.lineno}"
29
+
30
+ if should_also_store:
31
+ setattr(record, WHERE_ATTR, output)
32
+
33
+ return output
34
+
35
+
36
+ """
37
+ COPYRIGHT NOTICE
38
+
39
+ This software is governed by the CeCILL license under French law and
40
+ abiding by the rules of distribution of free software. You can use,
41
+ modify and/ or redistribute the software under the terms of the CeCILL
42
+ license as circulated by CEA, CNRS and INRIA at the following URL
43
+ "http://www.cecill.info".
44
+
45
+ As a counterpart to the access to the source code and rights to copy,
46
+ modify and redistribute granted by the license, users are provided only
47
+ with a limited warranty and the software's author, the holder of the
48
+ economic rights, and the successive licensors have only limited
49
+ liability.
50
+
51
+ In this respect, the user's attention is drawn to the risks associated
52
+ with loading, using, modifying and/or developing or reproducing the
53
+ software by the user in light of its specific status of free software,
54
+ that may mean that it is complicated to manipulate, and that also
55
+ therefore means that it is reserved for developers and experienced
56
+ professionals having in-depth computer knowledge. Users are therefore
57
+ encouraged to load and test the software's suitability as regards their
58
+ requirements in conditions enabling the security of their systems and/or
59
+ data to be ensured and, more generally, to use and operate it in the
60
+ same conditions as regards security.
61
+
62
+ The fact that you are presently reading this means that you have had
63
+ knowledge of the CeCILL license and that you accept its terms.
64
+
65
+ SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
66
+ """
@@ -7,9 +7,7 @@ SEE COPYRIGHT NOTICE BELOW
7
7
  import time
8
8
  from datetime import datetime as date_time_t
9
9
 
10
- # This module is imported early. Therefore, the current date and time should be close
11
- # enough to the real start time of the main script.
12
- _START_DATE_AND_TIME = date_time_t.now()
10
+ from logger_36.constant.date_time import START_DATE_TIME
13
11
 
14
12
 
15
13
  def TimeStamp(*, precision: str = "microseconds") -> str:
@@ -25,7 +23,7 @@ def TimeStamp(*, precision: str = "microseconds") -> str:
25
23
  def ElapsedTime(*, should_return_now: bool = False) -> str | tuple[str, date_time_t]:
26
24
  """"""
27
25
  now = date_time_t.now()
28
- elapsed_seconds = (now - _START_DATE_AND_TIME).total_seconds()
26
+ elapsed_seconds = (now - START_DATE_TIME).total_seconds()
29
27
  output = time.strftime("%H:%M:%S", time.gmtime(elapsed_seconds))
30
28
  while output.startswith("00:"):
31
29
  output = output.split(sep=":", maxsplit=1)[-1]
@@ -5,6 +5,8 @@ SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
7
  import logging as l
8
+ import os as o
9
+ import tempfile as tmps
8
10
  from io import IOBase as io_base_t
9
11
  from pathlib import Path as path_t
10
12
 
@@ -41,8 +43,15 @@ def SaveLOGasHTML(
41
43
  actual_file = isinstance(path, path_t)
42
44
 
43
45
  if actual_file and path.exists():
44
- logger.warning(f'{cannot_save}: File "{path}" already exists.')
45
- return
46
+ existing = path
47
+
48
+ accessor, path = tmps.mkstemp(suffix=".htm")
49
+ o.close(accessor)
50
+ path = path_t(path)
51
+
52
+ logger.warning(
53
+ f'File "{existing}" already exists: Saving LOG as HTML in {path} instead.'
54
+ )
46
55
 
47
56
  for handler in logger.handlers:
48
57
  records = getattr(handler, "records", None)
@@ -15,14 +15,10 @@ from logger_36.config.message import (
15
15
  MESSAGE_MARKER,
16
16
  WHERE_SEPARATOR,
17
17
  )
18
+ from logger_36.config.rule import DEFAULT_RULE_LENGTH, RULE_CHARACTER
18
19
  from logger_36.constant.message import NEXT_LINE_PROLOGUE
19
20
  from logger_36.constant.record import SHOW_W_RULE_ATTR, WHEN_OR_ELAPSED_ATTR, WHERE_ATTR
20
- from logger_36.constant.rule import (
21
- DEFAULT_RULE,
22
- DEFAULT_RULE_LENGTH,
23
- MIN_HALF_RULE_LENGTH,
24
- RULE_CHARACTER,
25
- )
21
+ from logger_36.constant.rule import DEFAULT_RULE, MIN_HALF_RULE_LENGTH
26
22
  from logger_36.extension.line import WrappedLines
27
23
 
28
24
 
@@ -56,7 +52,7 @@ class extension_t:
56
52
  raise NotImplementedError
57
53
 
58
54
  def MessageFromRecord(
59
- self, record: l.LogRecord, /, *, rule_color: str | None = None
55
+ self, record: l.LogRecord, /, *, rule_color: str = "black"
60
56
  ) -> tuple[str, bool]:
61
57
  """
62
58
  The second returned value is is_not_a_rule.
@@ -122,7 +118,7 @@ class extension_t:
122
118
  self.EmitMessage(self.Rule(text=text, color=color))
123
119
 
124
120
 
125
- class handler_t(l.Handler, extension_t):
121
+ class non_file_handler_t(l.Handler, extension_t):
126
122
  def __init__(
127
123
  self,
128
124
  name: str | None,
@@ -160,10 +156,10 @@ class file_handler_t(l.FileHandler, extension_t):
160
156
  __post_init__(self, level)
161
157
 
162
158
 
163
- any_handler_t = handler_t | file_handler_t
159
+ handler_h = non_file_handler_t | file_handler_t
164
160
 
165
161
 
166
- def __post_init__(handler: any_handler_t, level: int) -> None:
162
+ def __post_init__(handler: handler_h, level: int) -> None:
167
163
  """"""
168
164
  handler.setLevel(level)
169
165
 
@@ -15,7 +15,6 @@ import types as t
15
15
  import typing as h
16
16
  from datetime import date as date_t
17
17
  from datetime import datetime as date_time_t
18
- from os import sep as FOLDER_SEPARATOR
19
18
  from pathlib import Path as path_t
20
19
  from traceback import TracebackException as traceback_t
21
20
 
@@ -35,18 +34,20 @@ from logger_36.config.message import (
35
34
  TIME_FORMAT,
36
35
  WHERE_SEPARATOR,
37
36
  )
37
+ from logger_36.constant.date_time import DATE_ORIGIN, DATE_TIME_ORIGIN
38
38
  from logger_36.constant.generic import NOT_PASSED
39
39
  from logger_36.constant.issue import ISSUE_LEVEL_SEPARATOR, ORDER, order_h
40
40
  from logger_36.constant.logger import WARNING_LOGGER_NAME, WARNING_TYPE_COMPILED_PATTERN
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
- from logger_36.constant.path import PROJECT_FILE_RELATIVE, USER_FOLDER
43
+ from logger_36.constant.path import USER_FOLDER, LAUNCH_ROOT_FILE_relative
44
44
  from logger_36.constant.record import SHOW_W_RULE_ATTR, SHOW_WHERE_ATTR
45
+ from logger_36.extension.record import RecordLocation
45
46
  from logger_36.task.format.message import MessageWithActualExpected
46
47
  from logger_36.task.measure.chronos import ElapsedTime
47
48
  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
49
  from logger_36.type.handler import extension_t as handler_extension_t
50
+ from logger_36.type.handler import handler_h as base_handler_h
50
51
  from logger_36.type.issue import NewIssue, issue_t
51
52
 
52
53
  if RICH_IS_AVAILABLE:
@@ -62,9 +63,6 @@ logger_handle_raw_h = h.Callable[[l.LogRecord], None]
62
63
  logger_handle_with_self_h = h.Callable[[l.Logger, l.LogRecord], None]
63
64
  logger_handle_h = logger_handle_raw_h | logger_handle_with_self_h
64
65
 
65
- _DATE_TIME_ORIGIN = date_time_t.fromtimestamp(1970, None)
66
- _DATE_ORIGIN = _DATE_TIME_ORIGIN.date()
67
-
68
66
 
69
67
  @d.dataclass(slots=True, repr=False, eq=False)
70
68
  class logger_t(base_t):
@@ -85,8 +83,8 @@ class logger_t(base_t):
85
83
  history: dict[date_time_t, str] = d.field(init=False, default_factory=dict)
86
84
  n_events: dict[int, int] = d.field(init=False, default_factory=dict)
87
85
 
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)
86
+ last_message_now: date_time_t = d.field(init=False, default=DATE_TIME_ORIGIN)
87
+ last_message_date: date_t = d.field(init=False, default=DATE_ORIGIN)
90
88
  memory_usages: list[tuple[str, int]] = d.field(init=False, default_factory=list)
91
89
  context_levels: list[str] = d.field(init=False, default_factory=list)
92
90
  staged_issues: list[issue_t] = d.field(init=False, default_factory=list)
@@ -96,7 +94,7 @@ class logger_t(base_t):
96
94
  )
97
95
  intercepts_exceptions: bool = d.field(init=False, default=False)
98
96
 
99
- # Used only until the last handler is added (see AddHandler).
97
+ # Used only until the first handler is added (see AddHandler).
100
98
  _should_activate_log_interceptions: bool = d.field(init=False, default=False)
101
99
 
102
100
  name_: d.InitVar[str | None] = None
@@ -105,6 +103,12 @@ class logger_t(base_t):
105
103
  activate_log_interceptions: d.InitVar[bool] = True
106
104
  activate_exc_interceptions: d.InitVar[bool] = True
107
105
 
106
+ @property
107
+ def formatted_history(self) -> str:
108
+ """"""
109
+ FormattedEntry = lambda _: f"{_[0]}: {_[1].replace('\n', '↲ ')}"
110
+ return "\n".join(map(FormattedEntry, self.history.items()))
111
+
108
112
  @property
109
113
  def intercepts_warnings(self) -> bool:
110
114
  """"""
@@ -155,6 +159,10 @@ class logger_t(base_t):
155
159
  if name_ is None:
156
160
  name_ = f"{type(self).__name__}:{hex(id(self))[2:]}"
157
161
 
162
+ self.history[date_time_t.now()] = (
163
+ f'Logger "{name_}" instantiation for "{LAUNCH_ROOT_FILE_relative}"'
164
+ )
165
+
158
166
  base_t.__init__(self, name_)
159
167
  self.setLevel(level_)
160
168
  self.propagate = False # Part of base_t.
@@ -175,10 +183,6 @@ class logger_t(base_t):
175
183
  if self.should_monitor_memory_usage:
176
184
  self.ActivateMemoryUsageMonitoring()
177
185
 
178
- self.history[date_time_t.now()] = (
179
- f'Logger "{self.name}" instantiation for "{PROJECT_FILE_RELATIVE}"'
180
- )
181
-
182
186
  def handle(self, record: l.LogRecord, /) -> None:
183
187
  """"""
184
188
  elapsed_time, now = ElapsedTime(should_return_now=True)
@@ -197,7 +201,7 @@ class logger_t(base_t):
197
201
  # Where.
198
202
  should_show_where = getattr(record, SHOW_WHERE_ATTR, record.levelno != l.INFO)
199
203
  if should_show_where or self.should_monitor_memory_usage:
200
- where = _RecordLocation(record, should_show_where)
204
+ where = RecordLocation(record, should_show_where)
201
205
  else:
202
206
  where = None
203
207
 
@@ -332,8 +336,8 @@ class logger_t(base_t):
332
336
 
333
337
  def AddHandler(
334
338
  self,
335
- handler_t_or_handler: type[base_handler_t]
336
- | base_handler_t
339
+ handler_t_or_handler: type[base_handler_h]
340
+ | base_handler_h
337
341
  | l.Handler
338
342
  | l.FileHandler,
339
343
  /,
@@ -426,6 +430,20 @@ class logger_t(base_t):
426
430
  )
427
431
  self.log(level, message)
428
432
 
433
+ def LogAsIs(self, message: str, /, *, indented: bool = False) -> None:
434
+ """"""
435
+ if indented:
436
+ message = text.indent(message, LINE_INDENT)
437
+
438
+ for handler in self.handlers:
439
+ EmitMessage = getattr(
440
+ handler, handler_extension_t.EmitMessage.__name__, None
441
+ )
442
+ if EmitMessage is not None:
443
+ EmitMessage(message)
444
+
445
+ info_raw = LogAsIs # To follow the convention of the logging methods info, error...
446
+
429
447
  def LogException(
430
448
  self,
431
449
  exception: Exception,
@@ -460,20 +478,6 @@ class logger_t(base_t):
460
478
  """"""
461
479
  self.DealWithException(exc_type, exc_value, exc_traceback)
462
480
 
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...
476
-
477
481
  def DisplayRule(
478
482
  self, /, *, message: str | None = None, color: str = "white"
479
483
  ) -> None:
@@ -608,26 +612,6 @@ class logger_t(base_t):
608
612
  return False
609
613
 
610
614
 
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
629
-
630
-
631
615
  def _HandleForWarnings(interceptor: base_t, /) -> logger_handle_h:
632
616
  """"""
633
617
 
@@ -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.24"
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.24
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
@@ -11,13 +11,11 @@ package/logger_36.egg-info/PKG-INFO
11
11
  package/logger_36.egg-info/SOURCES.txt
12
12
  package/logger_36.egg-info/dependency_links.txt
13
13
  package/logger_36.egg-info/top_level.txt
14
- package/logger_36/api/content.py
15
- package/logger_36/api/gpu.py
14
+ package/logger_36/api/logger.py
16
15
  package/logger_36/api/memory.py
16
+ package/logger_36/api/message.py
17
17
  package/logger_36/api/storage.py
18
- package/logger_36/api/system.py
19
18
  package/logger_36/api/time.py
20
- package/logger_36/api/type.py
21
19
  package/logger_36/catalog/config/console_rich.py
22
20
  package/logger_36/catalog/config/optional.py
23
21
  package/logger_36/catalog/handler/console.py
@@ -32,7 +30,9 @@ package/logger_36/catalog/logger/system.py
32
30
  package/logger_36/config/issue.py
33
31
  package/logger_36/config/memory.py
34
32
  package/logger_36/config/message.py
33
+ package/logger_36/config/rule.py
35
34
  package/logger_36/config/system.py
35
+ package/logger_36/constant/date_time.py
36
36
  package/logger_36/constant/error.py
37
37
  package/logger_36/constant/generic.py
38
38
  package/logger_36/constant/html.py
@@ -44,11 +44,11 @@ package/logger_36/constant/path.py
44
44
  package/logger_36/constant/record.py
45
45
  package/logger_36/constant/rule.py
46
46
  package/logger_36/constant/system.py
47
- package/logger_36/extension/html_.py
47
+ package/logger_36/extension/inspection.py
48
48
  package/logger_36/extension/line.py
49
+ package/logger_36/extension/record.py
49
50
  package/logger_36/instance/logger.py
50
51
  package/logger_36/instance/loggers.py
51
- package/logger_36/task/inspection.py
52
52
  package/logger_36/task/storage.py
53
53
  package/logger_36/task/format/memory.py
54
54
  package/logger_36/task/format/message.py
@@ -1,39 +0,0 @@
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
- from logger_36.catalog.logger.gpu import LogGPURelatedDetails # noqa
8
-
9
- """
10
- COPYRIGHT NOTICE
11
-
12
- This software is governed by the CeCILL license under French law and
13
- abiding by the rules of distribution of free software. You can use,
14
- modify and/ or redistribute the software under the terms of the CeCILL
15
- license as circulated by CEA, CNRS and INRIA at the following URL
16
- "http://www.cecill.info".
17
-
18
- As a counterpart to the access to the source code and rights to copy,
19
- modify and redistribute granted by the license, users are provided only
20
- with a limited warranty and the software's author, the holder of the
21
- economic rights, and the successive licensors have only limited
22
- liability.
23
-
24
- In this respect, the user's attention is drawn to the risks associated
25
- with loading, using, modifying and/or developing or reproducing the
26
- software by the user in light of its specific status of free software,
27
- that may mean that it is complicated to manipulate, and that also
28
- therefore means that it is reserved for developers and experienced
29
- professionals having in-depth computer knowledge. Users are therefore
30
- encouraged to load and test the software's suitability as regards their
31
- requirements in conditions enabling the security of their systems and/or
32
- data to be ensured and, more generally, to use and operate it in the
33
- same conditions as regards security.
34
-
35
- The fact that you are presently reading this means that you have had
36
- knowledge of the CeCILL license and that you accept its terms.
37
-
38
- SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
39
- """
@@ -1,49 +0,0 @@
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
- from logger_36.catalog.logger.memory import ( # noqa
8
- LogMaximumMemoryUsage,
9
- LogMemoryUsages,
10
- )
11
- from logger_36.task.format.memory import FormattedUsage as FormattedMemoryUsage # noqa
12
- from logger_36.task.format.memory import ( # noqa
13
- FormattedUsageWithAutoUnit as FormattedMemoryUsageWithAutoUnit,
14
- )
15
- from logger_36.task.format.memory import UsageBar as MemoryUsageBar # noqa
16
- from logger_36.task.measure.memory import CanCheckUsage as CanCheckMemoryUsage # noqa
17
- from logger_36.task.measure.memory import CurrentUsage as CurrentMemoryUsage # noqa
18
-
19
- """
20
- COPYRIGHT NOTICE
21
-
22
- This software is governed by the CeCILL license under French law and
23
- abiding by the rules of distribution of free software. You can use,
24
- modify and/ or redistribute the software under the terms of the CeCILL
25
- license as circulated by CEA, CNRS and INRIA at the following URL
26
- "http://www.cecill.info".
27
-
28
- As a counterpart to the access to the source code and rights to copy,
29
- modify and redistribute granted by the license, users are provided only
30
- with a limited warranty and the software's author, the holder of the
31
- economic rights, and the successive licensors have only limited
32
- liability.
33
-
34
- In this respect, the user's attention is drawn to the risks associated
35
- with loading, using, modifying and/or developing or reproducing the
36
- software by the user in light of its specific status of free software,
37
- that may mean that it is complicated to manipulate, and that also
38
- therefore means that it is reserved for developers and experienced
39
- professionals having in-depth computer knowledge. Users are therefore
40
- encouraged to load and test the software's suitability as regards their
41
- requirements in conditions enabling the security of their systems and/or
42
- data to be ensured and, more generally, to use and operate it in the
43
- same conditions as regards security.
44
-
45
- The fact that you are presently reading this means that you have had
46
- knowledge of the CeCILL license and that you accept its terms.
47
-
48
- SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
49
- """
@@ -1,93 +0,0 @@
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 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
- """
File without changes
File without changes
File without changes
File without changes
File without changes