diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6e1c1820..3567589b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,9 @@ +`Unreleased`_ +============= + +- Make ``patch()`` calls cumulative instead of overriding the possibly existing patching function (`#462 `_). + + `0.6.0`_ (2022-01-29) ===================== diff --git a/loguru/__init__.py b/loguru/__init__.py index 3205a86c..5ed4a1a8 100644 --- a/loguru/__init__.py +++ b/loguru/__init__.py @@ -23,7 +23,7 @@ colors=False, raw=False, capture=True, - patcher=None, + patchers=[], extra={}, ) diff --git a/loguru/_logger.py b/loguru/_logger.py index 858ceff4..2596b2f3 100644 --- a/loguru/_logger.py +++ b/loguru/_logger.py @@ -95,7 +95,13 @@ from ._get_frame import get_frame from ._handler import Handler from ._locks_machinery import create_logger_lock -from ._recattrs import RecordException, RecordFile, RecordLevel, RecordProcess, RecordThread +from ._recattrs import ( + RecordException, + RecordFile, + RecordLevel, + RecordProcess, + RecordThread, +) from ._simple_sinks import AsyncSink, CallableSink, StandardSink, StreamSink if sys.version_info >= (3, 6): @@ -209,9 +215,9 @@ class Logger: You should not instantiate a |Logger| by yourself, use ``from loguru import logger`` instead. """ - def __init__(self, core, exception, depth, record, lazy, colors, raw, capture, patcher, extra): + def __init__(self, core, exception, depth, record, lazy, colors, raw, capture, patchers, extra): self._core = core - self._options = (exception, depth, record, lazy, colors, raw, capture, patcher, extra) + self._options = (exception, depth, record, lazy, colors, raw, capture, patchers, extra) def __repr__(self): return "" % list(self._core.handlers.values()) @@ -1426,6 +1432,9 @@ def patch(self, patcher): ``record`` dict itself, as some values are used internally by `Loguru`, and modify them may produce unexpected results. + The logger can be patched multiple times. In this case, the functions are called in the + same order as they are added. + Parameters ---------- patcher: |callable|_ @@ -1457,8 +1466,8 @@ def patch(self, patcher): ... level, message = record["level"], record["message"] ... logger.patch(lambda r: r.update(record)).log(level, message) """ - *options, _, extra = self._options - return Logger(self._core, *options, patcher, extra) + *options, patchers, extra = self._options + return Logger(self._core, *options, patchers + [patcher], extra) def level(self, name, no=None, color=None, icon=None): """Add, update or retrieve a logging level. @@ -1853,7 +1862,7 @@ def _log(self, level_id, static_level_no, from_decorator, options, message, args if not core.handlers: return - (exception, depth, record, lazy, colors, raw, capture, patcher, extra) = options + (exception, depth, record, lazy, colors, raw, capture, patchers, extra) = options frame = get_frame(depth + 2) @@ -1961,7 +1970,7 @@ def _log(self, level_id, static_level_no, from_decorator, options, message, args if core.patcher: core.patcher(log_record) - if patcher: + for patcher in patchers: patcher(log_record) for handler in core.handlers.values(): diff --git a/tests/conftest.py b/tests/conftest.py index 0d305b2b..0229ad6a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,9 +8,8 @@ import traceback import warnings -import pytest - import loguru +import pytest if sys.version_info < (3, 5, 3): @@ -83,7 +82,7 @@ def reset_logger(): def reset(): loguru.logger.remove() loguru.logger.__init__( - loguru._logger.Core(), None, 0, False, False, False, False, True, None, {} + loguru._logger.Core(), None, 0, False, False, False, False, True, [], {} ) loguru._logger.context.set({}) diff --git a/tests/test_patch.py b/tests/test_patch.py index af3f9cf1..684974ef 100644 --- a/tests/test_patch.py +++ b/tests/test_patch.py @@ -67,3 +67,19 @@ def test_override_configured(writer): logger2.debug("!") assert writer.read() == "456 678 !\n" + + +def test_multiple_patches(writer): + def patch_1(record): + record["extra"]["a"] = 5 + + def patch_2(record): + record["extra"]["a"] += 1 + + def patch_3(record): + record["extra"]["a"] *= 2 + + logger.add(writer, format="{extra[a]} {message}") + logger.patch(patch_1).patch(patch_2).patch(patch_3).info("Test") + + assert writer.read() == "12 Test\n"