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 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
- from logger_36.type.logger import logger_t
7
+ from logger_36.type.logger import logger_t # noqa
8
8
 
9
9
  """
10
10
  COPYRIGHT NOTICE
logger_36/api/storage.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
- from logger_36.task.storage import html_reader_t
7
+ from logger_36.task.storage import html_reader_t # noqa
8
8
 
9
9
  """
10
10
  COPYRIGHT NOTICE
@@ -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: h.Callable[..., tuple[str, str | None]] = d.field(init=False)
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 ShowMessage(self, message: str, /, *, indented: bool = False) -> None:
63
+ def LogAsIs(self, message: str, /) -> None:
60
64
  """
61
65
  See documentation of
62
- logger_36.catalog.handler.generic.generic_handler_t.ShowMessage.
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.ShowMessage(RuleAsText(text))
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, LINE_INDENT
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, rule_t
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: h.Callable[..., str] = d.field(init=False)
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 ShowMessage(self, message: str | rule_t, /, *, indented: bool = False) -> None:
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.ShowMessage.
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.ShowMessage(Rule(text, color))
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: h.Callable[..., tuple[str, str | None]] = d.field(init=False)
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 ShowMessage(self, message: str, /, *, indented: bool = False) -> None:
72
+ def LogAsIs(self, message: str, /) -> None:
70
73
  """
71
74
  See documentation of
72
- logger_36.catalog.handler.generic.generic_handler_t.ShowMessage.
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.ShowMessage(RuleAsText(text))
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
- try:
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
- except ModuleNotFoundError:
19
- console_t = console_options_t = EscapedForRich = DEFAULT_TERMINAL_THEME = None
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
- @h.runtime_checkable
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 display_rule_p(h.Protocol):
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
- ShowMessage:
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
- ShowMessage: show_message_p
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: display_rule_p = d.field(init=False)
69
+ DisplayRule: DisplayRule_p = d.field(init=False)
65
70
  extension: handler_extension_t = d.field(init=False)
66
- MessageFromRecord: h.Callable[..., tuple[str, str | None]] = d.field(init=False)
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.ShowMessage(message)
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.ShowMessage(RuleAsText(text))
184
+ self.LogAsIs(RuleAsText(text))
180
185
 
181
186
  def _DisplayRule(self, /, *, text: str | None = None, color: str = "white") -> None:
182
187
  """"""
183
- self.ShowMessage(Rule(text, color))
188
+ self.LogAsIs(Rule(text, color))
184
189
 
185
190
 
186
191
  """
@@ -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:
@@ -16,7 +16,7 @@ MEMORY_MEASURE_ERROR = (
16
16
  "is not installed or not importable."
17
17
  )
18
18
 
19
- MISSING_RICH_ERROR = (
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. "
@@ -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
- HANDLER_CODES: tuple[str, ...] = h.get_args(handler_codes_h)
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
 
@@ -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 logging as l
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 = regx.compile(WARNING_TYPE_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 logging as l
7
+ import inspect as nspt
8
+ import tempfile as tmps
9
+ from pathlib import Path as path_t
8
10
 
9
- from logger_36.catalog.handler.console import console_handler_t
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
- module = frame.f_code.co_filename
34
- function = frame.f_code.co_name
35
- line = frame.f_lineno
36
-
37
- home = str(path_t.home())
38
- if module.startswith(home):
39
- module = "~" + module[home.__len__() :]
40
-
41
- message = str(exception)
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}.{function}@{line}\n"
50
- f"{message} Full report at: {document.name}",
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
@@ -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
- from logger_36.catalog.logger.gpu import LogGPURelatedDetails
7
+ from logger_36.catalog.logger.gpu import LogGPURelatedDetails # noqa
8
8
 
9
9
  """
10
10
  COPYRIGHT NOTICE