logger-36 2025.5__py3-none-any.whl → 2025.7__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/logger.py +1 -1
- logger_36/api/storage.py +1 -1
- logger_36/catalog/config/console_rich.py +2 -2
- logger_36/catalog/config/optional.py +60 -0
- logger_36/catalog/handler/console.py +11 -9
- logger_36/catalog/handler/console_rich.py +16 -15
- logger_36/catalog/handler/file.py +10 -9
- logger_36/catalog/handler/generic.py +21 -16
- logger_36/catalog/logger/gpu.py +2 -2
- logger_36/constant/error.py +1 -1
- logger_36/constant/handler.py +2 -2
- logger_36/constant/logger.py +2 -9
- logger_36/{config/logger.py → constant/path.py} +15 -46
- logger_36/content.py +3 -3
- logger_36/exception.py +47 -12
- logger_36/gpu.py +1 -1
- logger_36/handler.py +15 -18
- logger_36/memory.py +9 -6
- logger_36/storage.py +1 -1
- logger_36/system.py +1 -1
- logger_36/task/format/rule.py +4 -2
- logger_36/task/measure/memory.py +2 -2
- logger_36/task/storage.py +7 -5
- logger_36/time.py +2 -2
- logger_36/type/handler.py +20 -4
- logger_36/type/logger.py +230 -123
- logger_36/version.py +1 -1
- {logger_36-2025.5.dist-info → logger_36-2025.7.dist-info}/METADATA +1 -1
- logger_36-2025.7.dist-info/RECORD +53 -0
- logger_36-2025.5.dist-info/RECORD +0 -52
- {logger_36-2025.5.dist-info → logger_36-2025.7.dist-info}/WHEEL +0 -0
- {logger_36-2025.5.dist-info → logger_36-2025.7.dist-info}/top_level.txt +0 -0
logger_36/api/logger.py
CHANGED
logger_36/api/storage.py
CHANGED
@@ -6,8 +6,8 @@ SEE COPYRIGHT NOTICE BELOW
|
|
6
6
|
|
7
7
|
import logging as l
|
8
8
|
|
9
|
-
from rich.color import Color as color_t
|
10
|
-
from rich.style import Style as style_t
|
9
|
+
from rich.color import Color as color_t # noqa
|
10
|
+
from rich.style import Style as style_t # noqa
|
11
11
|
|
12
12
|
"""
|
13
13
|
Colors: See https://rich.readthedocs.io/en/stable/appendix/colors.html.
|
@@ -0,0 +1,60 @@
|
|
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
|
+
try:
|
8
|
+
import rich # noqa
|
9
|
+
except ModuleNotFoundError:
|
10
|
+
RICH_IS_AVAILABLE = False
|
11
|
+
from logger_36.constant.error import MISSING_RICH_MESSAGE
|
12
|
+
else:
|
13
|
+
RICH_IS_AVAILABLE = True
|
14
|
+
MISSING_RICH_MESSAGE = None
|
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
|
+
|
47
|
+
This software is being developed by Eric Debreuve, a CNRS employee and
|
48
|
+
member of team Morpheme.
|
49
|
+
Team Morpheme is a joint team between Inria, CNRS, and UniCA.
|
50
|
+
It is hosted by the Centre Inria d'Université Côte d'Azur, Laboratory
|
51
|
+
I3S, and Laboratory iBV.
|
52
|
+
|
53
|
+
CNRS: https://www.cnrs.fr/index.php/en
|
54
|
+
Inria: https://www.inria.fr/en/
|
55
|
+
UniCA: https://univ-cotedazur.eu/
|
56
|
+
Centre Inria d'Université Côte d'Azur: https://www.inria.fr/en/centre/sophia/
|
57
|
+
I3S: https://www.i3s.unice.fr/en/
|
58
|
+
iBV: http://ibv.unice.fr/
|
59
|
+
Team Morpheme: https://team.inria.fr/morpheme/
|
60
|
+
"""
|
@@ -6,19 +6,23 @@ SEE COPYRIGHT NOTICE BELOW
|
|
6
6
|
|
7
7
|
import dataclasses as d
|
8
8
|
import logging as l
|
9
|
-
import textwrap as txt_
|
10
9
|
import typing as h
|
11
10
|
|
12
|
-
from logger_36.constant.message import LINE_INDENT
|
13
11
|
from logger_36.constant.record import SHOW_W_RULE_ATTR
|
14
12
|
from logger_36.task.format.rule import RuleAsText
|
15
|
-
from logger_36.type.handler import handler_extension_t
|
13
|
+
from logger_36.type.handler import MessageFromRecordRaw_h, handler_extension_t
|
16
14
|
|
17
15
|
|
18
16
|
@d.dataclass(slots=True, repr=False, eq=False)
|
19
17
|
class console_handler_t(l.Handler):
|
18
|
+
"""
|
19
|
+
kind: See logger_36.constant.handler.handler_codes_h.
|
20
|
+
"""
|
21
|
+
|
22
|
+
kind: h.ClassVar[str] = "c"
|
23
|
+
|
20
24
|
extension: handler_extension_t = d.field(init=False)
|
21
|
-
MessageFromRecord:
|
25
|
+
MessageFromRecord: MessageFromRecordRaw_h = d.field(init=False)
|
22
26
|
|
23
27
|
name: d.InitVar[str | None] = None
|
24
28
|
level: d.InitVar[int] = l.NOTSET
|
@@ -56,18 +60,16 @@ class console_handler_t(l.Handler):
|
|
56
60
|
message = self.MessageFromRecord(record)
|
57
61
|
print(message)
|
58
62
|
|
59
|
-
def
|
63
|
+
def LogAsIs(self, message: str, /) -> None:
|
60
64
|
"""
|
61
65
|
See documentation of
|
62
|
-
logger_36.catalog.handler.generic.generic_handler_t.
|
66
|
+
logger_36.catalog.handler.generic.generic_handler_t.LogAsIs.
|
63
67
|
"""
|
64
|
-
if indented:
|
65
|
-
message = txt_.indent(message, LINE_INDENT)
|
66
68
|
print(message)
|
67
69
|
|
68
70
|
def DisplayRule(self, /, *, text: str | None = None, color: str = "white") -> None:
|
69
71
|
""""""
|
70
|
-
self.
|
72
|
+
self.LogAsIs(RuleAsText(text))
|
71
73
|
|
72
74
|
|
73
75
|
"""
|
@@ -6,7 +6,6 @@ SEE COPYRIGHT NOTICE BELOW
|
|
6
6
|
|
7
7
|
import dataclasses as d
|
8
8
|
import logging as l
|
9
|
-
import textwrap as txt_
|
10
9
|
import typing as h
|
11
10
|
|
12
11
|
from logger_36.catalog.config.console_rich import (
|
@@ -20,15 +19,15 @@ from logger_36.catalog.config.console_rich import (
|
|
20
19
|
WHITE_COLOR,
|
21
20
|
)
|
22
21
|
from logger_36.config.message import ACTUAL_PATTERNS, EXPECTED_PATTERNS, WHERE_SEPARATOR
|
23
|
-
from logger_36.constant.message import CONTEXT_LENGTH
|
22
|
+
from logger_36.constant.message import CONTEXT_LENGTH
|
24
23
|
from logger_36.constant.record import SHOW_W_RULE_ATTR
|
25
|
-
from logger_36.task.format.rule import Rule
|
26
|
-
from logger_36.type.handler import handler_extension_t
|
27
|
-
from rich.console import Console as console_t
|
28
|
-
from rich.console import RenderableType as renderable_t
|
29
|
-
from rich.markup import escape as EscapedVersion
|
30
|
-
from rich.text import Text as text_t
|
31
|
-
from rich.traceback import install as InstallTracebackHandler
|
24
|
+
from logger_36.task.format.rule import Rule
|
25
|
+
from logger_36.type.handler import MessageFromRecordPreprocessed_p, handler_extension_t
|
26
|
+
from rich.console import Console as console_t # noqa
|
27
|
+
from rich.console import RenderableType as renderable_t # noqa
|
28
|
+
from rich.markup import escape as EscapedVersion # noqa
|
29
|
+
from rich.text import Text as text_t # noqa
|
30
|
+
from rich.traceback import install as InstallTracebackHandler # noqa
|
32
31
|
|
33
32
|
_COMMON_TRACEBACK_ARGUMENTS = ("theme", "width")
|
34
33
|
_EXCLUSIVE_TRACEBACK_ARGUMENTS = (
|
@@ -47,6 +46,8 @@ _EXCLUSIVE_TRACEBACK_ARGUMENTS = (
|
|
47
46
|
@d.dataclass(slots=True, repr=False, eq=False)
|
48
47
|
class console_rich_handler_t(l.Handler):
|
49
48
|
"""
|
49
|
+
kind: See logger_36.constant.handler.handler_codes_h.
|
50
|
+
|
50
51
|
alternating_lines:
|
51
52
|
- Initial value:
|
52
53
|
- 1: enabled for dark background
|
@@ -55,9 +56,11 @@ class console_rich_handler_t(l.Handler):
|
|
55
56
|
- Runtime value: 0/1=do not/do highlight next time.
|
56
57
|
"""
|
57
58
|
|
59
|
+
kind: h.ClassVar[str] = "c"
|
60
|
+
|
58
61
|
extension: handler_extension_t = d.field(init=False)
|
59
62
|
console: console_t = d.field(init=False)
|
60
|
-
MessageFromRecord:
|
63
|
+
MessageFromRecord: MessageFromRecordPreprocessed_p = d.field(init=False)
|
61
64
|
alternating_lines: int = 0
|
62
65
|
background_is_light: bool = True
|
63
66
|
|
@@ -145,18 +148,16 @@ class console_rich_handler_t(l.Handler):
|
|
145
148
|
)
|
146
149
|
self.console.print(richer, crop=False, overflow="ignore")
|
147
150
|
|
148
|
-
def
|
151
|
+
def LogAsIs(self, message: str | renderable_t, /) -> None:
|
149
152
|
"""
|
150
153
|
See documentation of
|
151
|
-
logger_36.catalog.handler.generic.generic_handler_t.
|
154
|
+
logger_36.catalog.handler.generic.generic_handler_t.LogAsIs.
|
152
155
|
"""
|
153
|
-
if isinstance(message, str) and indented:
|
154
|
-
message = txt_.indent(message, LINE_INDENT)
|
155
156
|
self.console.print(message, crop=False, overflow="ignore")
|
156
157
|
|
157
158
|
def DisplayRule(self, /, *, text: str | None = None, color: str = "white") -> None:
|
158
159
|
""""""
|
159
|
-
self.
|
160
|
+
self.LogAsIs(Rule(text, color))
|
160
161
|
|
161
162
|
|
162
163
|
def HighlightedVersion(
|
@@ -6,21 +6,24 @@ SEE COPYRIGHT NOTICE BELOW
|
|
6
6
|
|
7
7
|
import dataclasses as d
|
8
8
|
import logging as l
|
9
|
-
import textwrap as txt_
|
10
9
|
import typing as h
|
11
10
|
from pathlib import Path as path_t
|
12
11
|
|
13
|
-
from logger_36.constant.message import LINE_INDENT
|
14
12
|
from logger_36.constant.record import SHOW_W_RULE_ATTR
|
15
13
|
from logger_36.task.format.rule import RuleAsText
|
16
|
-
from logger_36.type.handler import handler_extension_t
|
14
|
+
from logger_36.type.handler import MessageFromRecordRaw_h, handler_extension_t
|
17
15
|
|
18
16
|
|
19
17
|
@d.dataclass(slots=True, repr=False, eq=False)
|
20
18
|
class file_handler_t(l.FileHandler):
|
19
|
+
"""
|
20
|
+
kind: See logger_36.constant.handler.handler_codes_h.
|
21
|
+
"""
|
22
|
+
|
23
|
+
kind: h.ClassVar[str] = "f"
|
21
24
|
|
22
25
|
extension: handler_extension_t = d.field(init=False)
|
23
|
-
MessageFromRecord:
|
26
|
+
MessageFromRecord: MessageFromRecordRaw_h = d.field(init=False)
|
24
27
|
|
25
28
|
name: d.InitVar[str | None] = None
|
26
29
|
level: d.InitVar[int] = l.NOTSET
|
@@ -66,19 +69,17 @@ class file_handler_t(l.FileHandler):
|
|
66
69
|
print(message, file=self.stream)
|
67
70
|
self.stream.flush()
|
68
71
|
|
69
|
-
def
|
72
|
+
def LogAsIs(self, message: str, /) -> None:
|
70
73
|
"""
|
71
74
|
See documentation of
|
72
|
-
logger_36.catalog.handler.generic.generic_handler_t.
|
75
|
+
logger_36.catalog.handler.generic.generic_handler_t.LogAsIs.
|
73
76
|
"""
|
74
|
-
if indented:
|
75
|
-
message = txt_.indent(message, LINE_INDENT)
|
76
77
|
print(message, file=self.stream)
|
77
78
|
self.stream.flush()
|
78
79
|
|
79
80
|
def DisplayRule(self, /, *, text: str | None = None, color: str = "white") -> None:
|
80
81
|
""""""
|
81
|
-
self.
|
82
|
+
self.LogAsIs(RuleAsText(text))
|
82
83
|
|
83
84
|
|
84
85
|
"""
|
@@ -8,34 +8,37 @@ import dataclasses as d
|
|
8
8
|
import logging as l
|
9
9
|
import typing as h
|
10
10
|
|
11
|
-
|
11
|
+
from logger_36.catalog.config.optional import RICH_IS_AVAILABLE
|
12
|
+
|
13
|
+
if RICH_IS_AVAILABLE:
|
12
14
|
from logger_36.catalog.config.console_rich import DATE_TIME_COLOR
|
13
15
|
from logger_36.catalog.handler.console_rich import HighlightedVersion
|
14
16
|
from rich.console import Console as console_t # noqa
|
15
17
|
from rich.console import ConsoleOptions as console_options_t # noqa
|
16
18
|
from rich.markup import escape as EscapedForRich # noqa
|
17
19
|
from rich.terminal_theme import DEFAULT_TERMINAL_THEME # noqa
|
18
|
-
|
19
|
-
|
20
|
+
else:
|
21
|
+
DATE_TIME_COLOR = HighlightedVersion = console_t = console_options_t = (
|
22
|
+
EscapedForRich
|
23
|
+
) = DEFAULT_TERMINAL_THEME = None
|
20
24
|
|
21
25
|
from logger_36.constant.record import SHOW_W_RULE_ATTR
|
22
26
|
from logger_36.task.format.rule import Rule, RuleAsText
|
23
|
-
from logger_36.type.handler import handler_extension_t
|
24
|
-
|
27
|
+
from logger_36.type.handler import MessageFromRecord_h, handler_extension_t
|
25
28
|
|
26
|
-
|
27
|
-
class show_message_p(h.Protocol):
|
28
|
-
def __call__(self, message: str, /, *, indented: bool = False) -> None: ...
|
29
|
+
LogAsIs_h = h.Callable[[str | h.Any], None]
|
29
30
|
|
30
31
|
|
31
32
|
@h.runtime_checkable
|
32
|
-
class
|
33
|
+
class DisplayRule_p(h.Protocol):
|
33
34
|
def __call__(self, /, *, text: str | None = None, color: str = "white") -> None: ...
|
34
35
|
|
35
36
|
|
36
37
|
@d.dataclass(slots=True, repr=False, eq=False)
|
37
38
|
class generic_handler_t(l.Handler):
|
38
39
|
"""
|
40
|
+
kind: See logger_36.constant.handler.handler_codes_h.
|
41
|
+
|
39
42
|
alternating_lines:
|
40
43
|
- Initial value:
|
41
44
|
- 1: enabled for dark background
|
@@ -43,7 +46,7 @@ class generic_handler_t(l.Handler):
|
|
43
46
|
- anything else: disabled
|
44
47
|
- Runtime value: 0/1=do not/do highlight next time.
|
45
48
|
|
46
|
-
|
49
|
+
LogAsIs:
|
47
50
|
Log a message as is, i.e. without formatting. If this is a method, it should
|
48
51
|
contain the same call(s) as the final ones in the emit methods that are used to
|
49
52
|
output the formatted log messages. This means that there is some code
|
@@ -54,16 +57,18 @@ class generic_handler_t(l.Handler):
|
|
54
57
|
it is indeed called at the end of the emit method.
|
55
58
|
"""
|
56
59
|
|
57
|
-
|
60
|
+
kind: h.ClassVar[str] = "g"
|
61
|
+
|
62
|
+
LogAsIs: LogAsIs_h
|
58
63
|
# "None -> h.Any" (twice below) since None | None is invalid.
|
59
64
|
console: console_t | h.Any = None
|
60
65
|
console_options: console_options_t | h.Any = None
|
61
66
|
alternating_lines: int = 0
|
62
67
|
background_is_light: bool = True
|
63
68
|
|
64
|
-
DisplayRule:
|
69
|
+
DisplayRule: DisplayRule_p = d.field(init=False)
|
65
70
|
extension: handler_extension_t = d.field(init=False)
|
66
|
-
MessageFromRecord:
|
71
|
+
MessageFromRecord: MessageFromRecord_h = d.field(init=False)
|
67
72
|
|
68
73
|
name: d.InitVar[str | None] = None
|
69
74
|
level: d.InitVar[int] = l.NOTSET
|
@@ -170,17 +175,17 @@ class generic_handler_t(l.Handler):
|
|
170
175
|
"<pre style='margin-bottom:0px'>" + "".join(html_segments) + "</pre>"
|
171
176
|
)
|
172
177
|
|
173
|
-
self.
|
178
|
+
self.LogAsIs(message)
|
174
179
|
|
175
180
|
def _DisplayRuleAsText(
|
176
181
|
self, /, *, text: str | None = None, color: str = "white"
|
177
182
|
) -> None:
|
178
183
|
""""""
|
179
|
-
self.
|
184
|
+
self.LogAsIs(RuleAsText(text))
|
180
185
|
|
181
186
|
def _DisplayRule(self, /, *, text: str | None = None, color: str = "white") -> None:
|
182
187
|
""""""
|
183
|
-
self.
|
188
|
+
self.LogAsIs(Rule(text, color))
|
184
189
|
|
185
190
|
|
186
191
|
"""
|
logger_36/catalog/logger/gpu.py
CHANGED
@@ -13,11 +13,11 @@ from logger_36.type.logger import logger_t
|
|
13
13
|
try:
|
14
14
|
import tensorflow as tsfl # noqa
|
15
15
|
import tensorrt as tsrt # noqa
|
16
|
-
|
17
|
-
_GPU_LOGGING_ERROR = None
|
18
16
|
except ModuleNotFoundError:
|
19
17
|
tsfl = tsrt = None
|
20
18
|
_GPU_LOGGING_ERROR = GPU_LOGGING_ERROR
|
19
|
+
else:
|
20
|
+
_GPU_LOGGING_ERROR = None
|
21
21
|
|
22
22
|
|
23
23
|
def LogGPURelatedDetails(*, logger: logger_t = L) -> None:
|
logger_36/constant/error.py
CHANGED
@@ -16,7 +16,7 @@ MEMORY_MEASURE_ERROR = (
|
|
16
16
|
"is not installed or not importable."
|
17
17
|
)
|
18
18
|
|
19
|
-
|
19
|
+
MISSING_RICH_MESSAGE = (
|
20
20
|
"The Rich console handler is not available because the Rich package "
|
21
21
|
"(https://rich.readthedocs.io/en/stable/) "
|
22
22
|
"is not installed or not importable. "
|
logger_36/constant/handler.py
CHANGED
@@ -6,8 +6,8 @@ SEE COPYRIGHT NOTICE BELOW
|
|
6
6
|
|
7
7
|
import typing as h
|
8
8
|
|
9
|
-
handler_codes_h = h.Literal["g", "c", "f", "a"]
|
10
|
-
|
9
|
+
handler_codes_h = h.Literal["g", "c", "f", "a"] # g=generic, c=console, f=file, a=all.
|
10
|
+
HANDLER_KINDS: tuple[str, ...] = h.get_args(handler_codes_h)
|
11
11
|
|
12
12
|
ANONYMOUS = "<Anonymous>"
|
13
13
|
|
logger_36/constant/logger.py
CHANGED
@@ -4,21 +4,14 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
|
|
4
4
|
SEE COPYRIGHT NOTICE BELOW
|
5
5
|
"""
|
6
6
|
|
7
|
-
import
|
8
|
-
import re as regx
|
9
|
-
import typing as h
|
7
|
+
import re as r
|
10
8
|
|
11
9
|
LOGGER_NAME = "logger-36"
|
12
10
|
|
13
11
|
# https://docs.python.org/3/library/logging.html#logging.captureWarnings
|
14
12
|
WARNING_LOGGER_NAME = "py.warnings"
|
15
13
|
WARNING_TYPE_PATTERN = r"\s*([^:]+):([0-9]+):\s*([^:]+)\s*:((.|\n)*)"
|
16
|
-
WARNING_TYPE_COMPILED_PATTERN =
|
17
|
-
|
18
|
-
# Second version: with self as first parameter.
|
19
|
-
logger_handle_h = (
|
20
|
-
h.Callable[[l.LogRecord], None] | h.Callable[[l.Logger, l.LogRecord], None]
|
21
|
-
)
|
14
|
+
WARNING_TYPE_COMPILED_PATTERN = r.compile(WARNING_TYPE_PATTERN)
|
22
15
|
|
23
16
|
"""
|
24
17
|
COPYRIGHT NOTICE
|
@@ -4,54 +4,23 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
|
|
4
4
|
SEE COPYRIGHT NOTICE BELOW
|
5
5
|
"""
|
6
6
|
|
7
|
-
import
|
7
|
+
import inspect as nspt
|
8
|
+
import tempfile as tmps
|
9
|
+
from pathlib import Path as path_t
|
8
10
|
|
9
|
-
|
10
|
-
from logger_36.catalog.handler.console_rich import console_rich_handler_t
|
11
|
-
from logger_36.catalog.handler.file import file_handler_t
|
12
|
-
from logger_36.catalog.handler.generic import generic_handler_t
|
13
|
-
from logger_36.constant.handler import HANDLER_CODES, handler_codes_h
|
14
|
-
from logger_36.instance.logger import L
|
15
|
-
from logger_36.task.format.message import MessageWithActualExpected
|
16
|
-
|
17
|
-
|
18
|
-
def SetLOGLevel(
|
19
|
-
level: int,
|
20
|
-
/,
|
21
|
-
*,
|
22
|
-
logger: l.Logger = L,
|
23
|
-
which: handler_codes_h | str = "a",
|
24
|
-
) -> None:
|
25
|
-
"""
|
26
|
-
which: g=generic, c=console, f=file, a=all, str=name.
|
27
|
-
"""
|
28
|
-
which_is_name = which not in HANDLER_CODES
|
29
|
-
found = False
|
30
|
-
for handler in logger.handlers:
|
31
|
-
if (
|
32
|
-
(which == "a")
|
33
|
-
or ((which == "g") and isinstance(handler, generic_handler_t))
|
34
|
-
or (
|
35
|
-
(which == "c")
|
36
|
-
and isinstance(handler, (console_handler_t, console_rich_handler_t))
|
37
|
-
)
|
38
|
-
or ((which == "f") and isinstance(handler, file_handler_t))
|
39
|
-
or (which == handler.name)
|
40
|
-
):
|
41
|
-
handler.setLevel(level)
|
42
|
-
if which_is_name:
|
43
|
-
return
|
44
|
-
found = True
|
45
|
-
|
46
|
-
if not found:
|
47
|
-
raise ValueError(
|
48
|
-
MessageWithActualExpected(
|
49
|
-
"Handler not found",
|
50
|
-
actual=which,
|
51
|
-
expected=f"{str(HANDLER_CODES)[1:-1]}, or a handler name",
|
52
|
-
)
|
53
|
-
)
|
11
|
+
USER_FOLDER = path_t.home()
|
54
12
|
|
13
|
+
frame = nspt.stack()[-1]
|
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 = path_t("~") / PROJECT_FILE.relative_to(USER_FOLDER)
|
18
|
+
else:
|
19
|
+
PROJECT_FILE_RELATIVE = PROJECT_FILE
|
20
|
+
PROJECT_FOLDER = PROJECT_FILE.parent
|
21
|
+
else:
|
22
|
+
PROJECT_FILE = PROJECT_FILE_RELATIVE = "<unknown>"
|
23
|
+
PROJECT_FOLDER = path_t(tmps.mkdtemp())
|
55
24
|
|
56
25
|
"""
|
57
26
|
COPYRIGHT NOTICE
|
logger_36/content.py
CHANGED
@@ -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
|
-
from logger_36.constant.message import LINE_INDENT
|
8
|
-
from logger_36.task.format.message import MessageWithActualExpected
|
9
|
-
from logger_36.task.format.rule import Rule, RuleAsText
|
7
|
+
from logger_36.constant.message import LINE_INDENT # noqa
|
8
|
+
from logger_36.task.format.message import MessageWithActualExpected # noqa
|
9
|
+
from logger_36.task.format.rule import Rule, RuleAsText # noqa
|
10
10
|
|
11
11
|
"""
|
12
12
|
COPYRIGHT NOTICE
|
logger_36/exception.py
CHANGED
@@ -4,12 +4,15 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
|
|
4
4
|
SEE COPYRIGHT NOTICE BELOW
|
5
5
|
"""
|
6
6
|
|
7
|
+
import re as r
|
7
8
|
import sys as s
|
8
9
|
import tempfile as tmpf
|
9
10
|
import traceback as tcbk
|
10
11
|
import types as t
|
11
12
|
from pathlib import Path as path_t
|
12
13
|
|
14
|
+
from logger_36.constant.path import USER_FOLDER
|
15
|
+
|
13
16
|
_ORIGINAL_EXCEPTION_HANDLER = s.excepthook
|
14
17
|
|
15
18
|
|
@@ -30,24 +33,56 @@ def _HandleException(
|
|
30
33
|
while trace.tb_next is not None:
|
31
34
|
trace = trace.tb_next
|
32
35
|
frame = trace.tb_frame
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
code = frame.f_code
|
37
|
+
module = path_t(code.co_filename)
|
38
|
+
function = code.co_name
|
39
|
+
line_number = frame.f_lineno
|
40
|
+
line_content = module.read_text().splitlines()[line_number - 1].strip()
|
41
|
+
|
42
|
+
# Format module.
|
43
|
+
if module.is_relative_to(USER_FOLDER):
|
44
|
+
module = path_t("~") / module.relative_to(USER_FOLDER)
|
45
|
+
|
46
|
+
# Format line content.
|
47
|
+
if line_content.startswith("raise "):
|
48
|
+
# Do not display code of explicit exception raising.
|
49
|
+
line_content = None
|
50
|
+
|
51
|
+
# Find variables appearing in the line.
|
52
|
+
if line_content is None:
|
53
|
+
line_content = variables = ""
|
54
|
+
else:
|
55
|
+
all_variables = frame.f_locals
|
56
|
+
found_names = []
|
57
|
+
for match in r.finditer(r"[^\d\W]\w*", line_content):
|
58
|
+
name = match.group()
|
59
|
+
if name in all_variables:
|
60
|
+
found_names.append(name)
|
61
|
+
if found_names.__len__() > 0:
|
62
|
+
longest = max(map(len, found_names))
|
63
|
+
variables = map(
|
64
|
+
lambda _: f"{_:{longest}} = {all_variables[_]}", sorted(found_names)
|
65
|
+
)
|
66
|
+
variables = " " + "\n ".join(variables) + "\n"
|
67
|
+
else:
|
68
|
+
variables = ""
|
69
|
+
|
70
|
+
line_content = f" {line_content}\n"
|
71
|
+
|
72
|
+
# Format message.
|
73
|
+
message = str(exception).strip()
|
42
74
|
if message.__len__() > 0:
|
43
|
-
message = f" {message}\n"
|
75
|
+
message = f" {message[0].title()}{message[1:]}\n"
|
44
76
|
|
45
77
|
document = tmpf.NamedTemporaryFile(delete=False)
|
46
78
|
|
47
79
|
print(
|
48
80
|
f"{stripe.__name__}\n"
|
49
|
-
f" {module}
|
50
|
-
f"{
|
81
|
+
f" {module}:{function}@{line_number}\n"
|
82
|
+
f"{line_content}"
|
83
|
+
f"{variables}"
|
84
|
+
f"{message}"
|
85
|
+
f" Full report at: {document.name}",
|
51
86
|
file=s.stderr,
|
52
87
|
)
|
53
88
|
|
logger_36/gpu.py
CHANGED