logger-36 2024.21__py3-none-any.whl → 2024.23__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.
@@ -9,6 +9,8 @@ import typing as h
9
9
  order_h = h.Literal["when", "context"]
10
10
  ORDER: tuple[str, ...] = h.get_args(order_h)
11
11
 
12
+ ISSUE_LEVEL_SEPARATOR = "#"
13
+
12
14
  """
13
15
  COPYRIGHT NOTICE
14
16
 
@@ -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
  """
@@ -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 (
@@ -40,6 +41,7 @@ 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:
@@ -64,27 +66,35 @@ def FormattedMessage(
64
66
 
65
67
  if message[-1] == ".":
66
68
  message = message[:-1]
67
- actual = _FormattedValue(actual)
68
- expected = _FormattedValue(expected)
69
-
69
+ expected = _FormattedExpected(expected_op, expected, expected_is_choices, actual)
70
70
  if with_final_dot:
71
71
  dot = "."
72
72
  else:
73
73
  dot = ""
74
- return f"{message}: Actual={actual}; Expected{expected_op}{expected}{dot}"
75
-
76
74
 
77
- def _FormattedValue(value: h.Any, /, *, should_format_str: bool = True) -> str:
78
- """"""
79
- if value is None:
80
- return "None"
75
+ return f"{message}: Actual={actual}:{type(actual).__name__}; {expected}{dot}"
81
76
 
82
- if isinstance(value, str):
83
- if should_format_str:
84
- return f'"{value}"'
85
- return value
86
77
 
87
- return str(value)
78
+ def _FormattedExpected(
79
+ operator: str, expected: h.Any, expected_is_choices: bool, actual: h.Any, /
80
+ ) -> str:
81
+ """"""
82
+ if isinstance(expected, h.Sequence) and expected_is_choices:
83
+ close_matches = diff.get_close_matches(actual, expected)
84
+ if close_matches.__len__() > 0:
85
+ close_matches = ", ".join(close_matches)
86
+ return f"Close matche(s): {close_matches}"
87
+ else:
88
+ expected = ", ".join(map(str, expected))
89
+ return f"Valid values: {expected}"
90
+ else:
91
+ if operator == "=":
92
+ stripe = f":{type(expected).__name__}"
93
+ else:
94
+ stripe = ""
95
+ if operator == ":":
96
+ operator = ": "
97
+ return f"Expected{operator}{expected}{stripe}"
88
98
 
89
99
 
90
100
  """
logger_36/type/issue.py CHANGED
@@ -4,10 +4,12 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
4
4
  SEE COPYRIGHT NOTICE BELOW
5
5
  """
6
6
 
7
+ import logging as lggg
7
8
  import typing as h
8
9
 
9
10
  from logger_36.config.issue import ISSUE_BASE_CONTEXT
10
11
  from logger_36.constant.generic import NOT_PASSED
12
+ from logger_36.constant.issue import ISSUE_LEVEL_SEPARATOR
11
13
  from logger_36.constant.message import expected_op_h
12
14
  from logger_36.task.format.message import FormattedMessage
13
15
 
@@ -20,8 +22,10 @@ def NewIssue(
20
22
  message: str,
21
23
  /,
22
24
  *,
25
+ level: int = lggg.ERROR,
23
26
  actual: h.Any = NOT_PASSED,
24
27
  expected: h.Any | None = None,
28
+ expected_is_choices: bool = False,
25
29
  expected_op: expected_op_h = "=",
26
30
  with_final_dot: bool = True,
27
31
  ) -> issue_t:
@@ -32,11 +36,12 @@ def NewIssue(
32
36
  message,
33
37
  actual=actual,
34
38
  expected=expected,
39
+ expected_is_choices=expected_is_choices,
35
40
  expected_op=expected_op,
36
41
  with_final_dot=with_final_dot,
37
42
  )
38
43
 
39
- return f"{context}{separator}{message}"
44
+ return f"{level}{ISSUE_LEVEL_SEPARATOR}{context}{separator}{message}"
40
45
 
41
46
 
42
47
  """
logger_36/type/logger.py CHANGED
@@ -17,7 +17,7 @@ from traceback import TracebackException as traceback_t
17
17
  from logger_36.config.issue import ISSUE_CONTEXT_END, ISSUE_CONTEXT_SEPARATOR
18
18
  from logger_36.config.message import DATE_FORMAT
19
19
  from logger_36.constant.generic import NOT_PASSED
20
- from logger_36.constant.issue import ORDER, order_h
20
+ from logger_36.constant.issue import ISSUE_LEVEL_SEPARATOR, ORDER, order_h
21
21
  from logger_36.constant.logger import (
22
22
  HIDE_WHERE_KWARG,
23
23
  LOGGER_NAME,
@@ -221,11 +221,35 @@ class logger_t(lggg.Logger):
221
221
  # __post_init__ set self.exit_on_critical if self.exit_on_error.
222
222
  sstm.exit(1)
223
223
 
224
- def error_for_exception(
224
+ def Log(
225
+ self,
226
+ message: str,
227
+ /,
228
+ *,
229
+ level: int = lggg.ERROR,
230
+ actual: h.Any = NOT_PASSED,
231
+ expected: h.Any | None = None,
232
+ expected_is_choices: bool = False,
233
+ expected_op: expected_op_h = "=",
234
+ with_final_dot: bool = True,
235
+ ) -> None:
236
+ """"""
237
+ message = FormattedMessage(
238
+ message,
239
+ actual=actual,
240
+ expected=expected,
241
+ expected_is_choices=expected_is_choices,
242
+ expected_op=expected_op,
243
+ with_final_dot=with_final_dot,
244
+ )
245
+ self.log(level, message)
246
+
247
+ def LogException(
225
248
  self,
226
249
  exception: Exception,
227
250
  /,
228
251
  *,
252
+ level: int = lggg.ERROR,
229
253
  should_remove_caller: bool = False,
230
254
  ) -> None:
231
255
  """"""
@@ -233,9 +257,12 @@ class logger_t(lggg.Logger):
233
257
  if should_remove_caller:
234
258
  message = "\n".join(lines[:1] + lines[2:])
235
259
  else:
260
+ # TODO: Explain:
261
+ # - Why it's not: "\n".join(lines)?
262
+ # - Why adding exception name here and not when removing caller?
236
263
  formatted = "".join(lines)
237
264
  message = f"{type(exception).__name__}:\n{formatted}"
238
- self.error(message)
265
+ self.log(level, message)
239
266
 
240
267
  def AddContextLevel(self, new_level: str, /) -> None:
241
268
  """"""
@@ -255,8 +282,10 @@ class logger_t(lggg.Logger):
255
282
  message: str,
256
283
  /,
257
284
  *,
285
+ level: int = lggg.ERROR,
258
286
  actual: h.Any = NOT_PASSED,
259
287
  expected: h.Any | None = None,
288
+ expected_is_choices: bool = False,
260
289
  expected_op: expected_op_h = "=",
261
290
  with_final_dot: bool = False,
262
291
  ) -> None:
@@ -266,8 +295,10 @@ class logger_t(lggg.Logger):
266
295
  context,
267
296
  ISSUE_CONTEXT_END,
268
297
  message,
298
+ level=level,
269
299
  actual=actual,
270
300
  expected=expected,
301
+ expected_is_choices=expected_is_choices,
271
302
  expected_op=expected_op,
272
303
  with_final_dot=with_final_dot,
273
304
  )
@@ -280,12 +311,15 @@ class logger_t(lggg.Logger):
280
311
 
281
312
  def CommitIssues(
282
313
  self,
283
- level: int | type[Exception],
284
314
  /,
285
315
  *,
286
316
  order: order_h = "when",
317
+ unified: bool = False,
287
318
  ) -> None:
288
- """"""
319
+ """
320
+ Note that issues after an issue with a level triggering process exit will not be
321
+ logged.
322
+ """
289
323
  if not self.has_staged_issues:
290
324
  return
291
325
 
@@ -302,22 +336,28 @@ class logger_t(lggg.Logger):
302
336
  issues = self.staged_issues
303
337
  else: # order == "context"
304
338
  issues = sorted(self.staged_issues, key=lambda _elm: _elm.context)
305
- issues = "\n".join(issues)
306
-
307
- if isinstance(level, type) and issubclass(level, Exception):
308
- try:
309
- raise level("\n" + issues)
310
- except Exception as exception:
311
- lines = ["Traceback (most recent call last):"] + tcbk.format_stack()[
312
- :-1
313
- ]
314
- lines[-1] = lines[-1][:-1]
315
- lines.extend(tcbk.format_exception_only(exception))
316
- print("\n".join(lines), file=sstm.stderr)
317
- sstm.exit(1)
318
-
319
- level: int
320
- self.log(level, issues, stacklevel=2)
339
+ """
340
+ Format issues as an exception:
341
+ try:
342
+ raise ValueError("\n" + "\n".join(issues))
343
+ except ValueError as exception:
344
+ lines = ["Traceback (most recent call last):"] + tcbk.format_stack()[:-1]
345
+ lines[-1] = lines[-1][:-1]
346
+ lines.extend(tcbk.format_exception_only(exception))
347
+ formatted = "\n".join(lines)
348
+ """
349
+
350
+ if unified:
351
+ level, _ = issues[0].split(ISSUE_LEVEL_SEPARATOR, maxsplit=1)
352
+ wo_level = []
353
+ for issue in issues:
354
+ _, issue = issue.split(ISSUE_LEVEL_SEPARATOR, maxsplit=1)
355
+ wo_level.append(issue)
356
+ self.log(int(level), "\n".join(wo_level), stacklevel=2)
357
+ else:
358
+ for issue in issues:
359
+ level, issue = issue.split(ISSUE_LEVEL_SEPARATOR, maxsplit=1)
360
+ self.log(int(level), issue, stacklevel=2)
321
361
  self.staged_issues.clear()
322
362
 
323
363
  def ShowMessage(self, message: str, /) -> None:
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__ = "2024.21"
7
+ __version__ = "2024.23"
8
8
 
9
9
  """
10
10
  COPYRIGHT NOTICE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: logger-36
3
- Version: 2024.21
3
+ Version: 2024.23
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
@@ -5,7 +5,7 @@ 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=rTDQY_iaCr8FcZO-_ELLxzcbp57fGX9nsGWkY7plJmk,2206
8
+ logger_36/version.py,sha256=4_FGnjQh_s8oYEhxb9KRp7Q6xpIM8ntNmNoRxRRQqfo,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
11
  logger_36/catalog/handler/console_rich.py,sha256=Ti1k2E1ox4egzicghTb9Wv30xiWaBbWwe8ouopJsujY,8792
@@ -23,10 +23,10 @@ logger_36/config/system.py,sha256=HD8ZuwsXhEAExeZrww8YoDkQGMs4T5RDqQMb1W4qVgc,24
23
23
  logger_36/constant/error.py,sha256=1gdnCwUu3d3ThL4AKxzjn7ijSTBWlr2g-8cAKbubl4A,2825
24
24
  logger_36/constant/generic.py,sha256=t6aRb66_NHwMhR1p7BZ4QXTU2jpLz-H5YAL4PuMtKx8,2244
25
25
  logger_36/constant/handler.py,sha256=HM8qCSEMGNMCzddjUUNBPGL-3d0qU-EmG5eW4ZQHW6A,2311
26
- logger_36/constant/issue.py,sha256=48c3QGNzgRcvQOenlp77_wAU4znZfLkQEdT2oE_CvMs,2286
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=RKQL-YmEDds5q7HuHTeDebz7_h3zWDX0PNxu-RTwL2I,2714
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=X9qtXPxhXgCIjnRYBJn93vj4rW4I-7dJP6LaXD5Qu2o,4142
37
+ logger_36/task/format/message.py,sha256=CP1E8tNY1hkc_dujrxTV2DW2iGopx4ew4xV_HgwOlDw,4705
38
38
  logger_36/task/format/rule.py,sha256=YEe8wG_QLy9vRZqmT2bWlvKT-Dxp4pGaZVmEuwwODyE,2598
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=cB8pSSJg9aqFPQ6yJr4TC2kJbngKGK8Hyq4ATBm6jAc,2973
43
- logger_36/type/logger.py,sha256=W6U0t_M6juGoc5cGb9vdwk29LhNeg2Sa-VeOKiWJrac,15234
42
+ logger_36/type/issue.py,sha256=Y7OCLCzVt6Yvkecwj8HXLdZjg33oMxexc9XkYHzUhh4,3202
43
+ logger_36/type/logger.py,sha256=1PNs4sGZM7JvIMuveU-2X4TL9CbrIm7WSHq54SjSpRw,16653
44
44
  logger_36/type/loggers.py,sha256=znqxWBnfQxvkg3VUfbTUvt3S6Kq0DAzWWepxQDt9suI,2871
45
- logger_36-2024.21.dist-info/METADATA,sha256=fsvDva8-byjx5YqWdp2yf83uIjNA04WYyBjTcdVAgbY,6276
46
- logger_36-2024.21.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
47
- logger_36-2024.21.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
48
- logger_36-2024.21.dist-info/RECORD,,
45
+ logger_36-2024.23.dist-info/METADATA,sha256=ycisLVTVoTOgt6tPDkBqwhEUSZhCVtqmEM_MAl6vEMQ,6276
46
+ logger_36-2024.23.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
47
+ logger_36-2024.23.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
48
+ logger_36-2024.23.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (72.2.0)
2
+ Generator: setuptools (74.1.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5