From cba74c78f8ca53791cca3cd0fa80ddbc2afdf942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Palancher?= Date: Thu, 2 Jul 2026 11:29:16 +0200 Subject: [PATCH 1/2] fix(log): clear existing log handlers by default setup_logger() now clear existing log handlers by default to prevent stacking. This can be avoided by setting clear=False. fix #88 --- CHANGELOG.md | 5 +++++ src/log/rfl/log/__init__.py | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25c4e13..4a6b2d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,11 @@ and this project adheres to - build: Make `authors` optional in setup converter (omit `author` and `author_email` when not specified). +### Fixed + +- log: Clear handlers in `setup_logger()` by default to avoid duplicate log + lines, with optional clear=False to keep existing handlers (#88). + ## [1.8.0] - 2026-05-22 ### Added diff --git a/src/log/rfl/log/__init__.py b/src/log/rfl/log/__init__.py index db4c0e2..9e04c96 100644 --- a/src/log/rfl/log/__init__.py +++ b/src/log/rfl/log/__init__.py @@ -26,8 +26,13 @@ def setup_logger( debug_flags: Optional[List[str]] = None, formatter: logging.Formatter = auto_formatter(), component: Optional[str] = None, + clear: bool = True, ) -> None: - """Setup root logger debug level, debug flags and formatter.""" + """Setup root logger debug level, debug flags and formatter. + + When clear is True (default), existing root logger handlers are removed + before adding a new one, similarly to logging.basicConfig(force=True). + """ if debug: logging_level = logging.DEBUG else: @@ -39,6 +44,10 @@ def setup_logger( debug_flags = [] root_logger = logging.getLogger() + if clear: + for existing_handler in root_logger.handlers[:]: + root_logger.removeHandler(existing_handler) + existing_handler.close() root_logger.setLevel(logging_level) handler = logging.StreamHandler() handler.setLevel(logging_level) From 64b5bdf6b86c73934b5fee37148a80cbb3379894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Palancher?= Date: Thu, 2 Jul 2026 11:33:25 +0200 Subject: [PATCH 2/2] tests(log): test log handlers clearing --- src/log/rfl/tests/test_setup.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/log/rfl/tests/test_setup.py b/src/log/rfl/tests/test_setup.py index 94f7045..42496e6 100644 --- a/src/log/rfl/tests/test_setup.py +++ b/src/log/rfl/tests/test_setup.py @@ -102,6 +102,21 @@ def test_setup_filter_debug_all(self): handler, {"name": "fail.pkg", "levelno": logging.DEBUG, "msg": "test"} ) + def test_setup_clears_handlers(self): + setup_logger() + setup_logger() + logger = logging.getLogger() + self.assertEqual(len(logger.handlers), 1) + + def test_setup_clear_false_stacks_handlers(self): + root_logger = logging.getLogger() + for handler in root_logger.handlers[:]: + root_logger.removeHandler(handler) + handler.close() + setup_logger(clear=False) + setup_logger(clear=False) + self.assertEqual(len(root_logger.handlers), 2) + class TestEnforceLogger(TestLogFilterer): def setUp(self):