Skip to content
Snippets Groups Projects
Commit 65efe8f0 authored by DEBREUVE Eric's avatar DEBREUVE Eric
Browse files

logger now stores event counts, added DisplayRule, rich console interprets markup

parent fee3299c
No related branches found
No related tags found
No related merge requests found
......@@ -31,7 +31,6 @@ from logger_36.task.format.rule import Rule
from logger_36.type.handler import handler_extension_t
from rich.console import Console as console_t
from rich.console import RenderableType as renderable_t
from rich.markup import escape as EscapedForRich
from rich.text import Text as text_t
from rich.traceback import install as InstallTracebackHandler
......@@ -140,7 +139,7 @@ class console_rich_handler_t(lggg.Handler):
if hasattr(record, SHOW_W_RULE_ATTR):
richer = Rule(record.msg, DATE_TIME_COLOR)
else:
first, next_s = self.FormattedLines(record, PreProcessed=EscapedForRich)
first, next_s = self.FormattedLines(record)
should_highlight_back = self.alternating_lines == 1
if self.alternating_lines >= 0:
self.alternating_lines = (self.alternating_lines + 1) % 2
......@@ -173,7 +172,9 @@ def HighlightedVersion(
background_is_light: bool = True,
) -> renderable_t:
""""""
output = text_t(first_line)
# TODO: Is there a way to use html or something to enable message styling,
# regardless of the handler (would require styling conversion; html->rich here).
output = text_t.from_markup(first_line)
# Used instead of _CONTEXT_LENGTH which might include \t, thus creating a
# mismatch between character length and length when displayed in console.
......@@ -193,7 +194,7 @@ def HighlightedVersion(
output.stylize(ELAPSED_TIME_COLOR, start=elapsed_time_separator)
if next_lines is not None:
output.append(next_lines)
output.append(text_t.from_markup(next_lines))
_ = output.highlight_regex(ACTUAL_PATTERNS, style=ACTUAL_COLOR)
_ = output.highlight_regex(EXPECTED_PATTERNS, style=EXPECTED_COLOR)
......
......@@ -15,7 +15,7 @@ from logger_36.config.message import (
MESSAGE_MARKER,
)
from logger_36.constant.generic import NOT_PASSED
from logger_36.constant.message import EXPECTED_OP, expected_op_h
from logger_36.constant.message import expected_op_h
def MessageFormat(with_where: bool, with_memory_usage: bool, /) -> str:
......@@ -46,15 +46,6 @@ def FormattedMessage(
with_final_dot: bool = True,
) -> str:
""""""
if expected_op not in EXPECTED_OP:
raise ValueError(
FormattedMessage(
'Invalid "expected" section operator',
actual=expected_op,
expected=f"One of {str(EXPECTED_OP)[1:-1]}",
)
)
if actual is NOT_PASSED:
if with_final_dot:
if message[-1] != ".":
......
......@@ -5,18 +5,24 @@ SEE COPYRIGHT NOTICE BELOW
"""
def RuleAsText(text: str, /) -> str:
def RuleAsText(text: str | None, /) -> str:
""""""
return f"---- ---- ---- ---- {text} ---- ---- ---- ----"
if text is None:
return "---- ---- ---- ---- ---- ---- ---- ---- ----"
else:
return f"---- ---- ---- ---- {text} ---- ---- ---- ----"
try:
from rich.rule import Rule as rule_t
from rich.text import Text as text_t
def Rule(text: str, color: str, /) -> rule_t:
def Rule(text: str | None, color: str, /) -> rule_t | str:
""""""
return rule_t(title=text_t(text, style=f"bold {color}"), style=color)
if text is None:
return rule_t(style=color)
else:
return rule_t(title=text_t(text, style=f"bold {color}"), style=color)
except ModuleNotFoundError:
Rule = lambda _txt, _: RuleAsText(_txt)
......
......@@ -32,6 +32,7 @@ from logger_36.task.format.memory import (
FormattedUsageWithAutoUnit as FormattedMemoryUsage,
)
from logger_36.task.format.message import FormattedMessage
from logger_36.task.format.rule import Rule
from logger_36.task.measure.chronos import ElapsedTime
from logger_36.task.measure.memory import CurrentUsage as CurrentMemoryUsage
from logger_36.type.issue import NewIssue, issue_t
......@@ -42,12 +43,14 @@ class logger_t(lggg.Logger):
name_: d.InitVar[str] = LOGGER_NAME
level_: d.InitVar[int] = lggg.NOTSET
activate_wrn_interceptions: d.InitVar[bool] = True
exit_on_error: bool = False # Implies exit_on_critical.
exit_on_critical: bool = False
# Must not be False until at least one handler has been added.
should_hold_messages: bool = True
exit_on_error: bool = False # Implies exit_on_critical.
exit_on_critical: bool = False
on_hold: list[lggg.LogRecord] = d.field(init=False, default_factory=list)
events: dict[int, int] = d.field(init=False, default_factory=dict)
last_message_date: str = d.field(init=False, default="")
any_handler_shows_memory: bool = d.field(init=False, default=False)
memory_usages: list[tuple[str, int]] = d.field(init=False, default_factory=list)
......@@ -66,11 +69,19 @@ class logger_t(lggg.Logger):
self.setLevel(level_)
self.propagate = False # Part of lggg.Logger.
for level in lggg.getLevelNamesMapping().values():
self.events[level] = 0
if activate_wrn_interceptions:
self._ActivateWarningInterceptions()
if self.exit_on_error:
self.exit_on_critical = True
def ResetEventCounts(self) -> None:
""""""
for level in self.events:
self.events[level] = 0
def _ActivateWarningInterceptions(self) -> None:
"""
The log message will not appear if called from __post_init__ since there are no
......@@ -214,6 +225,7 @@ class logger_t(lggg.Logger):
else:
lggg.Logger.handle(self, record)
self.events[record.levelno] += 1
if (self.exit_on_critical and (record.levelno is lggg.CRITICAL)) or (
self.exit_on_error and (record.levelno is lggg.ERROR)
):
......@@ -264,6 +276,20 @@ class logger_t(lggg.Logger):
message = f"{type(exception).__name__}:\n{formatted}"
self.log(level, message)
def ShowMessage(self, message: str, /) -> None:
"""
See documentation of
logger_36.catalog.handler.generic.generic_handler_t.ShowMessage.
"""
for handler in self.handlers:
ShowMessage = getattr(handler, "ShowMessage", None)
if ShowMessage is not None:
ShowMessage(message)
def DisplayRule(self, /, *, text: str | None = None, color: str = "white") -> None:
""""""
self.ShowMessage(Rule(text, color))
def AddContextLevel(self, new_level: str, /) -> None:
""""""
self.context_levels.append(new_level)
......@@ -360,16 +386,6 @@ class logger_t(lggg.Logger):
self.log(int(level), issue, stacklevel=2)
self.staged_issues.clear()
def ShowMessage(self, message: str, /) -> None:
"""
See documentation of
logger_36.catalog.handler.generic.generic_handler_t.ShowMessage.
"""
for handler in self.handlers:
ShowMessage = getattr(handler, "ShowMessage", None)
if ShowMessage is not None:
ShowMessage(message)
def __enter__(self) -> None:
""""""
pass
......
......@@ -4,7 +4,7 @@ Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
SEE COPYRIGHT NOTICE BELOW
"""
__version__ = "2024.23"
__version__ = "2024.24"
"""
COPYRIGHT NOTICE
......
......@@ -61,6 +61,8 @@ with TemporaryDirectory() as tmp_folder:
LogSystemDetails()
LOGGER.DisplayRule()
for level in ("debug", "info", "warning", "error", "critical"):
LogMessage = getattr(LOGGER, level)
LogMessage(f"{level.capitalize()} message")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment