diff --git a/loguru/_logger.py b/loguru/_logger.py
index 3d246de0..5e03b9e9 100644
--- a/loguru/_logger.py
+++ b/loguru/_logger.py
@@ -2107,7 +2107,7 @@ def _log(self, level, from_decorator, options, message, args, kwargs):
"function": co_name,
"level": RecordLevel(level_name, level_no, level_icon),
"line": f_lineno,
- "message": str(message),
+ "message": message,
"module": splitext(file_name)[0],
"name": name,
"process": RecordProcess(process.ident, process.name),
@@ -2130,23 +2130,25 @@ def _log(self, level, from_decorator, options, message, args, kwargs):
)
kwargs.update(record=log_record)
+ if core.patcher:
+ core.patcher(log_record)
+
+ for patcher in patchers:
+ patcher(log_record)
+
if colors:
if args or kwargs:
- colored_message = Colorizer.prepare_message(message, args, kwargs)
+ colored_message = Colorizer.prepare_message(log_record["message"], args, kwargs)
else:
- colored_message = Colorizer.prepare_simple_message(str(message))
+ colored_message = Colorizer.prepare_simple_message(str(log_record["message"]))
log_record["message"] = colored_message.stripped
elif args or kwargs:
colored_message = None
- log_record["message"] = message.format(*args, **kwargs)
+ log_record["message"] = log_record["message"].format(*args, **kwargs)
else:
colored_message = None
- if core.patcher:
- core.patcher(log_record)
-
- for patcher in patchers:
- patcher(log_record)
+ log_record["message"] = str(log_record["message"])
for handler in core.handlers.values():
handler.emit(log_record, level_id, from_decorator, raw, colored_message)
diff --git a/tests/test_patch.py b/tests/test_patch.py
index 684974ef..be9382b7 100644
--- a/tests/test_patch.py
+++ b/tests/test_patch.py
@@ -1,3 +1,7 @@
+import re
+
+import pytest
+
from loguru import logger
@@ -83,3 +87,46 @@ def patch_3(record):
logger.patch(patch_1).patch(patch_2).patch(patch_3).info("Test")
assert writer.read() == "12 Test\n"
+
+
+@pytest.mark.parametrize(
+ ("colorize", "colors", "expected"),
+ [
+ (False, False, "A\n"),
+ (False, True, "A\n"),
+ (True, False, "A\n"),
+ (True, True, "\x1b[31mA\x1b[0m\n"),
+ ],
+)
+def test_colorful_patch(colorize, colors, expected, writer):
+ logger.add(writer, format="{message}", colorize=colorize)
+
+ logger_patched = logger.patch(lambda r: r.update(message=f"{r['message']}"))
+ logger_patched.opt(colors=colors).debug("A")
+
+ assert writer.read() == expected
+
+
+@pytest.mark.parametrize(
+ ("colorize", "colors", "expected"),
+ [
+ (False, False, "A W, M\n"),
+ (False, True, "A W, M\n"),
+ (True, False, "A W, M\n"),
+ (True, True, "A \x1b[31mW\x1b[0m, \x1b[31mM\x1b[0m\n"),
+ ],
+)
+def test_automatic_colorful_patch(colorize, colors, expected, writer):
+ # regex matches on single curly braces and substitutes
+ # a color tag in-place
+ _regex_pattern = re.compile(r"(\{[^{}]*\})(?!\})")
+ _regex_repl = r"\1"
+
+ def patch(r):
+ r.update(message=re.sub(_regex_pattern, _regex_repl, r["message"]))
+
+ logger.add(writer, format="{message}", colorize=colorize)
+ logger_patched = logger.patch(patch)
+ logger_patched.opt(colors=colors).debug("A {}, {a}", "W", a="M")
+
+ assert writer.read() == expected