logger-36 2024.22__py3-none-any.whl → 2024.24__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/catalog/handler/console_rich.py +5 -4
- logger_36/constant/message.py +1 -1
- logger_36/task/format/message.py +25 -24
- logger_36/task/format/rule.py +10 -4
- logger_36/type/issue.py +2 -0
- logger_36/type/logger.py +55 -14
- logger_36/version.py +1 -1
- {logger_36-2024.22.dist-info → logger_36-2024.24.dist-info}/METADATA +1 -1
- {logger_36-2024.22.dist-info → logger_36-2024.24.dist-info}/RECORD +11 -11
- {logger_36-2024.22.dist-info → logger_36-2024.24.dist-info}/WHEEL +1 -1
- {logger_36-2024.22.dist-info → logger_36-2024.24.dist-info}/top_level.txt +0 -0
@@ -31,7 +31,6 @@ from logger_36.task.format.rule import Rule
|
|
31
31
|
from logger_36.type.handler import handler_extension_t
|
32
32
|
from rich.console import Console as console_t
|
33
33
|
from rich.console import RenderableType as renderable_t
|
34
|
-
from rich.markup import escape as EscapedForRich
|
35
34
|
from rich.text import Text as text_t
|
36
35
|
from rich.traceback import install as InstallTracebackHandler
|
37
36
|
|
@@ -140,7 +139,7 @@ class console_rich_handler_t(lggg.Handler):
|
|
140
139
|
if hasattr(record, SHOW_W_RULE_ATTR):
|
141
140
|
richer = Rule(record.msg, DATE_TIME_COLOR)
|
142
141
|
else:
|
143
|
-
first, next_s = self.FormattedLines(record
|
142
|
+
first, next_s = self.FormattedLines(record)
|
144
143
|
should_highlight_back = self.alternating_lines == 1
|
145
144
|
if self.alternating_lines >= 0:
|
146
145
|
self.alternating_lines = (self.alternating_lines + 1) % 2
|
@@ -173,7 +172,9 @@ def HighlightedVersion(
|
|
173
172
|
background_is_light: bool = True,
|
174
173
|
) -> renderable_t:
|
175
174
|
""""""
|
176
|
-
|
175
|
+
# TODO: Is there a way to use html or something to enable message styling,
|
176
|
+
# regardless of the handler (would require styling conversion; html->rich here).
|
177
|
+
output = text_t.from_markup(first_line)
|
177
178
|
|
178
179
|
# Used instead of _CONTEXT_LENGTH which might include \t, thus creating a
|
179
180
|
# mismatch between character length and length when displayed in console.
|
@@ -193,7 +194,7 @@ def HighlightedVersion(
|
|
193
194
|
output.stylize(ELAPSED_TIME_COLOR, start=elapsed_time_separator)
|
194
195
|
|
195
196
|
if next_lines is not None:
|
196
|
-
output.append(next_lines)
|
197
|
+
output.append(text_t.from_markup(next_lines))
|
197
198
|
|
198
199
|
_ = output.highlight_regex(ACTUAL_PATTERNS, style=ACTUAL_COLOR)
|
199
200
|
_ = output.highlight_regex(EXPECTED_PATTERNS, style=EXPECTED_COLOR)
|
logger_36/constant/message.py
CHANGED
@@ -19,7 +19,7 @@ LOG_LEVEL_LENGTH = 1 + LEVEL_OPENING.__len__() + LEVEL_CLOSING.__len__()
|
|
19
19
|
CONTEXT_LENGTH = TIME_LENGTH + LOG_LEVEL_LENGTH
|
20
20
|
NEXT_LINE_PROLOGUE = "\n" + (CONTEXT_LENGTH + MESSAGE_MARKER.__len__() + 1) * " "
|
21
21
|
|
22
|
-
expected_op_h = h.Literal[": ", "=", "!=", ">=", "<="]
|
22
|
+
expected_op_h = h.Literal[":", ": ", "=", "!=", ">=", "<="]
|
23
23
|
EXPECTED_OP: tuple[str, ...] = h.get_args(expected_op_h)
|
24
24
|
|
25
25
|
"""
|
logger_36/task/format/message.py
CHANGED
@@ -4,6 +4,7 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
|
|
4
4
|
SEE COPYRIGHT NOTICE BELOW
|
5
5
|
"""
|
6
6
|
|
7
|
+
import difflib as diff
|
7
8
|
import typing as h
|
8
9
|
|
9
10
|
from logger_36.config.message import (
|
@@ -14,7 +15,7 @@ from logger_36.config.message import (
|
|
14
15
|
MESSAGE_MARKER,
|
15
16
|
)
|
16
17
|
from logger_36.constant.generic import NOT_PASSED
|
17
|
-
from logger_36.constant.message import
|
18
|
+
from logger_36.constant.message import expected_op_h
|
18
19
|
|
19
20
|
|
20
21
|
def MessageFormat(with_where: bool, with_memory_usage: bool, /) -> str:
|
@@ -40,19 +41,11 @@ def FormattedMessage(
|
|
40
41
|
*,
|
41
42
|
actual: h.Any = NOT_PASSED,
|
42
43
|
expected: h.Any | None = None,
|
44
|
+
expected_is_choices: bool = False,
|
43
45
|
expected_op: expected_op_h = "=",
|
44
46
|
with_final_dot: bool = True,
|
45
47
|
) -> str:
|
46
48
|
""""""
|
47
|
-
if expected_op not in EXPECTED_OP:
|
48
|
-
raise ValueError(
|
49
|
-
FormattedMessage(
|
50
|
-
'Invalid "expected" section operator',
|
51
|
-
actual=expected_op,
|
52
|
-
expected=f"One of {str(EXPECTED_OP)[1:-1]}",
|
53
|
-
)
|
54
|
-
)
|
55
|
-
|
56
49
|
if actual is NOT_PASSED:
|
57
50
|
if with_final_dot:
|
58
51
|
if message[-1] != ".":
|
@@ -64,27 +57,35 @@ def FormattedMessage(
|
|
64
57
|
|
65
58
|
if message[-1] == ".":
|
66
59
|
message = message[:-1]
|
67
|
-
|
68
|
-
expected = _FormattedValue(expected)
|
69
|
-
|
60
|
+
expected = _FormattedExpected(expected_op, expected, expected_is_choices, actual)
|
70
61
|
if with_final_dot:
|
71
62
|
dot = "."
|
72
63
|
else:
|
73
64
|
dot = ""
|
74
|
-
return f"{message}: Actual={actual}; Expected{expected_op}{expected}{dot}"
|
75
65
|
|
66
|
+
return f"{message}: Actual={actual}:{type(actual).__name__}; {expected}{dot}"
|
76
67
|
|
77
|
-
def _FormattedValue(value: h.Any, /, *, should_format_str: bool = True) -> str:
|
78
|
-
""""""
|
79
|
-
if value is None:
|
80
|
-
return "None"
|
81
|
-
|
82
|
-
if isinstance(value, str):
|
83
|
-
if should_format_str:
|
84
|
-
return f'"{value}"'
|
85
|
-
return value
|
86
68
|
|
87
|
-
|
69
|
+
def _FormattedExpected(
|
70
|
+
operator: str, expected: h.Any, expected_is_choices: bool, actual: h.Any, /
|
71
|
+
) -> str:
|
72
|
+
""""""
|
73
|
+
if isinstance(expected, h.Sequence) and expected_is_choices:
|
74
|
+
close_matches = diff.get_close_matches(actual, expected)
|
75
|
+
if close_matches.__len__() > 0:
|
76
|
+
close_matches = ", ".join(close_matches)
|
77
|
+
return f"Close matche(s): {close_matches}"
|
78
|
+
else:
|
79
|
+
expected = ", ".join(map(str, expected))
|
80
|
+
return f"Valid values: {expected}"
|
81
|
+
else:
|
82
|
+
if operator == "=":
|
83
|
+
stripe = f":{type(expected).__name__}"
|
84
|
+
else:
|
85
|
+
stripe = ""
|
86
|
+
if operator == ":":
|
87
|
+
operator = ": "
|
88
|
+
return f"Expected{operator}{expected}{stripe}"
|
88
89
|
|
89
90
|
|
90
91
|
"""
|
logger_36/task/format/rule.py
CHANGED
@@ -5,18 +5,24 @@ SEE COPYRIGHT NOTICE BELOW
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
|
8
|
-
def RuleAsText(text: str, /) -> str:
|
8
|
+
def RuleAsText(text: str | None, /) -> str:
|
9
9
|
""""""
|
10
|
-
|
10
|
+
if text is None:
|
11
|
+
return "---- ---- ---- ---- ---- ---- ---- ---- ----"
|
12
|
+
else:
|
13
|
+
return f"---- ---- ---- ---- {text} ---- ---- ---- ----"
|
11
14
|
|
12
15
|
|
13
16
|
try:
|
14
17
|
from rich.rule import Rule as rule_t
|
15
18
|
from rich.text import Text as text_t
|
16
19
|
|
17
|
-
def Rule(text: str, color: str, /) -> rule_t:
|
20
|
+
def Rule(text: str | None, color: str, /) -> rule_t | str:
|
18
21
|
""""""
|
19
|
-
|
22
|
+
if text is None:
|
23
|
+
return rule_t(style=color)
|
24
|
+
else:
|
25
|
+
return rule_t(title=text_t(text, style=f"bold {color}"), style=color)
|
20
26
|
|
21
27
|
except ModuleNotFoundError:
|
22
28
|
Rule = lambda _txt, _: RuleAsText(_txt)
|
logger_36/type/issue.py
CHANGED
@@ -25,6 +25,7 @@ def NewIssue(
|
|
25
25
|
level: int = lggg.ERROR,
|
26
26
|
actual: h.Any = NOT_PASSED,
|
27
27
|
expected: h.Any | None = None,
|
28
|
+
expected_is_choices: bool = False,
|
28
29
|
expected_op: expected_op_h = "=",
|
29
30
|
with_final_dot: bool = True,
|
30
31
|
) -> issue_t:
|
@@ -35,6 +36,7 @@ def NewIssue(
|
|
35
36
|
message,
|
36
37
|
actual=actual,
|
37
38
|
expected=expected,
|
39
|
+
expected_is_choices=expected_is_choices,
|
38
40
|
expected_op=expected_op,
|
39
41
|
with_final_dot=with_final_dot,
|
40
42
|
)
|
logger_36/type/logger.py
CHANGED
@@ -32,6 +32,7 @@ from logger_36.task.format.memory import (
|
|
32
32
|
FormattedUsageWithAutoUnit as FormattedMemoryUsage,
|
33
33
|
)
|
34
34
|
from logger_36.task.format.message import FormattedMessage
|
35
|
+
from logger_36.task.format.rule import Rule
|
35
36
|
from logger_36.task.measure.chronos import ElapsedTime
|
36
37
|
from logger_36.task.measure.memory import CurrentUsage as CurrentMemoryUsage
|
37
38
|
from logger_36.type.issue import NewIssue, issue_t
|
@@ -42,12 +43,14 @@ class logger_t(lggg.Logger):
|
|
42
43
|
name_: d.InitVar[str] = LOGGER_NAME
|
43
44
|
level_: d.InitVar[int] = lggg.NOTSET
|
44
45
|
activate_wrn_interceptions: d.InitVar[bool] = True
|
45
|
-
|
46
|
-
exit_on_critical: bool = False
|
46
|
+
|
47
47
|
# Must not be False until at least one handler has been added.
|
48
48
|
should_hold_messages: bool = True
|
49
|
+
exit_on_error: bool = False # Implies exit_on_critical.
|
50
|
+
exit_on_critical: bool = False
|
49
51
|
|
50
52
|
on_hold: list[lggg.LogRecord] = d.field(init=False, default_factory=list)
|
53
|
+
events: dict[int, int] = d.field(init=False, default_factory=dict)
|
51
54
|
last_message_date: str = d.field(init=False, default="")
|
52
55
|
any_handler_shows_memory: bool = d.field(init=False, default=False)
|
53
56
|
memory_usages: list[tuple[str, int]] = d.field(init=False, default_factory=list)
|
@@ -66,11 +69,19 @@ class logger_t(lggg.Logger):
|
|
66
69
|
self.setLevel(level_)
|
67
70
|
self.propagate = False # Part of lggg.Logger.
|
68
71
|
|
72
|
+
for level in lggg.getLevelNamesMapping().values():
|
73
|
+
self.events[level] = 0
|
74
|
+
|
69
75
|
if activate_wrn_interceptions:
|
70
76
|
self._ActivateWarningInterceptions()
|
71
77
|
if self.exit_on_error:
|
72
78
|
self.exit_on_critical = True
|
73
79
|
|
80
|
+
def ResetEventCounts(self) -> None:
|
81
|
+
""""""
|
82
|
+
for level in self.events:
|
83
|
+
self.events[level] = 0
|
84
|
+
|
74
85
|
def _ActivateWarningInterceptions(self) -> None:
|
75
86
|
"""
|
76
87
|
The log message will not appear if called from __post_init__ since there are no
|
@@ -214,6 +225,7 @@ class logger_t(lggg.Logger):
|
|
214
225
|
else:
|
215
226
|
lggg.Logger.handle(self, record)
|
216
227
|
|
228
|
+
self.events[record.levelno] += 1
|
217
229
|
if (self.exit_on_critical and (record.levelno is lggg.CRITICAL)) or (
|
218
230
|
self.exit_on_error and (record.levelno is lggg.ERROR)
|
219
231
|
):
|
@@ -221,7 +233,30 @@ class logger_t(lggg.Logger):
|
|
221
233
|
# __post_init__ set self.exit_on_critical if self.exit_on_error.
|
222
234
|
sstm.exit(1)
|
223
235
|
|
224
|
-
def
|
236
|
+
def Log(
|
237
|
+
self,
|
238
|
+
message: str,
|
239
|
+
/,
|
240
|
+
*,
|
241
|
+
level: int = lggg.ERROR,
|
242
|
+
actual: h.Any = NOT_PASSED,
|
243
|
+
expected: h.Any | None = None,
|
244
|
+
expected_is_choices: bool = False,
|
245
|
+
expected_op: expected_op_h = "=",
|
246
|
+
with_final_dot: bool = True,
|
247
|
+
) -> None:
|
248
|
+
""""""
|
249
|
+
message = FormattedMessage(
|
250
|
+
message,
|
251
|
+
actual=actual,
|
252
|
+
expected=expected,
|
253
|
+
expected_is_choices=expected_is_choices,
|
254
|
+
expected_op=expected_op,
|
255
|
+
with_final_dot=with_final_dot,
|
256
|
+
)
|
257
|
+
self.log(level, message)
|
258
|
+
|
259
|
+
def LogException(
|
225
260
|
self,
|
226
261
|
exception: Exception,
|
227
262
|
/,
|
@@ -236,11 +271,25 @@ class logger_t(lggg.Logger):
|
|
236
271
|
else:
|
237
272
|
# TODO: Explain:
|
238
273
|
# - Why it's not: "\n".join(lines)?
|
239
|
-
# - Why adding
|
274
|
+
# - Why adding exception name here and not when removing caller?
|
240
275
|
formatted = "".join(lines)
|
241
276
|
message = f"{type(exception).__name__}:\n{formatted}"
|
242
277
|
self.log(level, message)
|
243
278
|
|
279
|
+
def ShowMessage(self, message: str, /) -> None:
|
280
|
+
"""
|
281
|
+
See documentation of
|
282
|
+
logger_36.catalog.handler.generic.generic_handler_t.ShowMessage.
|
283
|
+
"""
|
284
|
+
for handler in self.handlers:
|
285
|
+
ShowMessage = getattr(handler, "ShowMessage", None)
|
286
|
+
if ShowMessage is not None:
|
287
|
+
ShowMessage(message)
|
288
|
+
|
289
|
+
def DisplayRule(self, /, *, text: str | None = None, color: str = "white") -> None:
|
290
|
+
""""""
|
291
|
+
self.ShowMessage(Rule(text, color))
|
292
|
+
|
244
293
|
def AddContextLevel(self, new_level: str, /) -> None:
|
245
294
|
""""""
|
246
295
|
self.context_levels.append(new_level)
|
@@ -262,6 +311,7 @@ class logger_t(lggg.Logger):
|
|
262
311
|
level: int = lggg.ERROR,
|
263
312
|
actual: h.Any = NOT_PASSED,
|
264
313
|
expected: h.Any | None = None,
|
314
|
+
expected_is_choices: bool = False,
|
265
315
|
expected_op: expected_op_h = "=",
|
266
316
|
with_final_dot: bool = False,
|
267
317
|
) -> None:
|
@@ -274,6 +324,7 @@ class logger_t(lggg.Logger):
|
|
274
324
|
level=level,
|
275
325
|
actual=actual,
|
276
326
|
expected=expected,
|
327
|
+
expected_is_choices=expected_is_choices,
|
277
328
|
expected_op=expected_op,
|
278
329
|
with_final_dot=with_final_dot,
|
279
330
|
)
|
@@ -335,16 +386,6 @@ class logger_t(lggg.Logger):
|
|
335
386
|
self.log(int(level), issue, stacklevel=2)
|
336
387
|
self.staged_issues.clear()
|
337
388
|
|
338
|
-
def ShowMessage(self, message: str, /) -> None:
|
339
|
-
"""
|
340
|
-
See documentation of
|
341
|
-
logger_36.catalog.handler.generic.generic_handler_t.ShowMessage.
|
342
|
-
"""
|
343
|
-
for handler in self.handlers:
|
344
|
-
ShowMessage = getattr(handler, "ShowMessage", None)
|
345
|
-
if ShowMessage is not None:
|
346
|
-
ShowMessage(message)
|
347
|
-
|
348
389
|
def __enter__(self) -> None:
|
349
390
|
""""""
|
350
391
|
pass
|
logger_36/version.py
CHANGED
@@ -5,10 +5,10 @@ logger_36/logger.py,sha256=7LJtdT7TmfFsn6r34iTr6OGvEjXlU6hKXEO2c5Lm2zY,2386
|
|
5
5
|
logger_36/logger_gpu.py,sha256=YYFk6aYQrBDJfxQaDm-ar16T6SlOSL6jJWTOgvpF4EU,2244
|
6
6
|
logger_36/measure.py,sha256=P507VNbVKAf4jYGnGX-3rlDrVbrYP0ZD3nxFmAFvhyI,2404
|
7
7
|
logger_36/storage.py,sha256=O8pDmiL0B3LJpKrhi8a9IMBXs6MwW6r1bMUn_cSDAaY,2246
|
8
|
-
logger_36/version.py,sha256=
|
8
|
+
logger_36/version.py,sha256=R2K8-57Lahk2FjSCqX05d_TyRALChV-T1s0nHQifns8,2206
|
9
9
|
logger_36/catalog/config/console_rich.py,sha256=QDkgSs3I7ZULvkd1q4J1hdvgyB857JJcJWxM9fdL51Y,2883
|
10
10
|
logger_36/catalog/handler/console.py,sha256=SF9S3CUoEPp5dh7RrqotywDJjMgRp0rD9sO3eLVXnkA,4004
|
11
|
-
logger_36/catalog/handler/console_rich.py,sha256=
|
11
|
+
logger_36/catalog/handler/console_rich.py,sha256=uLZzVURQ6OIUuQEGMc142vJkEyxBbE0-HJJGQ_zOJcI,8914
|
12
12
|
logger_36/catalog/handler/file.py,sha256=z5ovaOxemh61pbWDCK2sMMlbd1TKwGjMiQhgoicilm4,4456
|
13
13
|
logger_36/catalog/handler/generic.py,sha256=wG6Z1-lHj_9o6cPurEVpPctFlec3BFeqx2mZU_krJt8,8379
|
14
14
|
logger_36/catalog/logger/chronos.py,sha256=eLqQw8N9vaGO23OCf5RrYDPbUeu7epUvDt9rH-dN7i0,2522
|
@@ -26,7 +26,7 @@ logger_36/constant/handler.py,sha256=HM8qCSEMGNMCzddjUUNBPGL-3d0qU-EmG5eW4ZQHW6A
|
|
26
26
|
logger_36/constant/issue.py,sha256=01l8itRPWGS5F6gXtsXUJgGR-4lS1Eu3_YeKC-khKLw,2315
|
27
27
|
logger_36/constant/logger.py,sha256=0GhemAQ_YBiRO5WQBuNTczuejyVu2IYCsgqPRIbL8es,2780
|
28
28
|
logger_36/constant/memory.py,sha256=ZL1MwbdtNsrCrOwzEyfTsfOoOsRBTJtbbf3otHGnxXo,2343
|
29
|
-
logger_36/constant/message.py,sha256=
|
29
|
+
logger_36/constant/message.py,sha256=JMnCmW4j-oa-Cs1iZCJ5yAG6V4BzjLCGRIvEw6pQTtU,2719
|
30
30
|
logger_36/constant/record.py,sha256=zebZYR4buX1lGfc7IyuvEh8zOpk7hx0aS4pJ12H0flI,2311
|
31
31
|
logger_36/constant/system.py,sha256=G2mzBTxRXoJMxb53TnmBaceMJC_q3WonoCG7y6nC_R8,2430
|
32
32
|
logger_36/instance/logger.py,sha256=ttKjl9MD7FUjqCWjv5w2hmmpDYxgaORcYf9NaaE9W_M,2246
|
@@ -34,15 +34,15 @@ logger_36/instance/loggers.py,sha256=RCWpC1NPAf6vXnFc9NqsSALv-x-FEzcH6k_OlxTxeQk
|
|
34
34
|
logger_36/task/inspection.py,sha256=f9VkVrwMJ_ixV9rFu3XUNpmCbEgoo1tssqd2nMeGYLI,5028
|
35
35
|
logger_36/task/storage.py,sha256=XaSeu-iBCa0N8HNpwCV7cLprj-lbOJocpTIKUgSOvsc,5668
|
36
36
|
logger_36/task/format/memory.py,sha256=ECOdHjdxIqXivOwtcmwpLDMYUrutIeOTCn1L4d3-U8k,4241
|
37
|
-
logger_36/task/format/message.py,sha256=
|
38
|
-
logger_36/task/format/rule.py,sha256=
|
37
|
+
logger_36/task/format/message.py,sha256=HuV8we1mqh7Xcd4vbwoC0mJ8f_PjtP4sX3WFM6W7Oew,4420
|
38
|
+
logger_36/task/format/rule.py,sha256=M4a8uW7FEvMI9f4s32A9-DoP0WVlLkyXamGnqbzZ65A,2797
|
39
39
|
logger_36/task/measure/chronos.py,sha256=t-y0bVm1SmF-3wI9pR9Bp6-qzVlsE94fZTZr5a_hZUA,2884
|
40
40
|
logger_36/task/measure/memory.py,sha256=eVw5WOYLyn8o4O4mMArdX2MzsVuhhNDovjYEkk-MIaU,2504
|
41
41
|
logger_36/type/handler.py,sha256=BXpevZhLq5V_IdUfi_LZA4czzlH2SGLpgvbqUBe5X10,8311
|
42
|
-
logger_36/type/issue.py,sha256=
|
43
|
-
logger_36/type/logger.py,sha256=
|
42
|
+
logger_36/type/issue.py,sha256=Y7OCLCzVt6Yvkecwj8HXLdZjg33oMxexc9XkYHzUhh4,3202
|
43
|
+
logger_36/type/logger.py,sha256=GClqeLtTCiItaIM0G29NNEETw765vA23npa4klOoydQ,17178
|
44
44
|
logger_36/type/loggers.py,sha256=znqxWBnfQxvkg3VUfbTUvt3S6Kq0DAzWWepxQDt9suI,2871
|
45
|
-
logger_36-2024.
|
46
|
-
logger_36-2024.
|
47
|
-
logger_36-2024.
|
48
|
-
logger_36-2024.
|
45
|
+
logger_36-2024.24.dist-info/METADATA,sha256=B8cCu3tIwEJIFQ4nKmP-lP4AzaeBJCau_ns-bguXr-8,6276
|
46
|
+
logger_36-2024.24.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
47
|
+
logger_36-2024.24.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
|
48
|
+
logger_36-2024.24.dist-info/RECORD,,
|
File without changes
|