From 213769651fa3b6740905e6160ea821345462d21e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 14 Mar 2026 19:22:10 +0000 Subject: [PATCH 1/2] test: add test coverage for logging_config.py (#43) Add tests/copilot_usage/test_logging_config.py covering: - setup_logging() adds exactly one sink - setup_logging() is idempotent (no duplicate handlers) - Sink targets sys.stderr at WARNING level - _emoji_patcher sets correct emoji for all known levels - _emoji_patcher falls back to ' ' for unknown levels - LEVEL_EMOJI covers all seven standard loguru levels Closes #43 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/copilot_usage/test_logging_config.py | 85 ++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 tests/copilot_usage/test_logging_config.py diff --git a/tests/copilot_usage/test_logging_config.py b/tests/copilot_usage/test_logging_config.py new file mode 100644 index 0000000..23d7a07 --- /dev/null +++ b/tests/copilot_usage/test_logging_config.py @@ -0,0 +1,85 @@ +"""Tests for copilot_usage.logging_config — setup_logging, _emoji_patcher, LEVEL_EMOJI.""" + +from __future__ import annotations + +import sys + +from loguru import logger + +from copilot_usage.logging_config import ( + LEVEL_EMOJI, + _emoji_patcher, # pyright: ignore[reportPrivateUsage] + setup_logging, +) + + +# --------------------------------------------------------------------------- +# setup_logging +# --------------------------------------------------------------------------- + + +def test_setup_logging_adds_exactly_one_sink() -> None: + """After setup_logging(), logger has exactly one handler.""" + setup_logging() + assert len(logger._core.handlers) == 1 # noqa: SLF001 # pyright: ignore[reportPrivateUsage] + + +def test_setup_logging_idempotent() -> None: + """Calling setup_logging() twice still results in exactly 1 sink.""" + setup_logging() + setup_logging() + assert len(logger._core.handlers) == 1 # noqa: SLF001 # pyright: ignore[reportPrivateUsage] + + +def test_setup_logging_targets_stderr() -> None: + """After setup_logging(), the single sink targets sys.stderr.""" + setup_logging() + handler = next(iter(logger._core.handlers.values())) # noqa: SLF001 # pyright: ignore[reportPrivateUsage] + assert handler._sink._stream is sys.stderr # noqa: SLF001 # pyright: ignore[reportPrivateUsage] + + +def test_setup_logging_level_is_warning() -> None: + """After setup_logging(), the minimum log level is WARNING.""" + setup_logging() + handler = next(iter(logger._core.handlers.values())) # noqa: SLF001 # pyright: ignore[reportPrivateUsage] + assert handler.levelno == logger.level("WARNING").no # pyright: ignore[reportPrivateUsage] + + +# --------------------------------------------------------------------------- +# _emoji_patcher +# --------------------------------------------------------------------------- + + +def test_emoji_patcher_known_levels() -> None: + """_emoji_patcher sets record['extra']['emoji'] for each known level.""" + for level_name, expected_emoji in LEVEL_EMOJI.items(): + record: dict[str, object] = { + "level": type("Level", (), {"name": level_name})(), + "extra": {}, + } + _emoji_patcher(record) # type: ignore[arg-type] + assert record["extra"]["emoji"] == expected_emoji # type: ignore[index] + + +def test_emoji_patcher_unknown_level_fallback() -> None: + """_emoji_patcher falls back to ' ' for an unknown level name.""" + record: dict[str, object] = { + "level": type("Level", (), {"name": "NONEXISTENT"})(), + "extra": {}, + } + _emoji_patcher(record) # type: ignore[arg-type] + assert record["extra"]["emoji"] == " " # type: ignore[index] + + +# --------------------------------------------------------------------------- +# LEVEL_EMOJI +# --------------------------------------------------------------------------- + +_STANDARD_LEVELS = frozenset( + {"TRACE", "DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL"} +) + + +def test_level_emoji_covers_all_standard_levels() -> None: + """LEVEL_EMOJI contains entries for all seven standard loguru levels.""" + assert _STANDARD_LEVELS.issubset(LEVEL_EMOJI.keys()) From e0049094e443d84ce2a186aa56d36886fd365273 Mon Sep 17 00:00:00 2001 From: Sasa Junuzovic Date: Sat, 14 Mar 2026 12:44:21 -0700 Subject: [PATCH 2/2] fix: resolve lint and pyright issues in logging_config tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/copilot_usage/test_logging_config.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/copilot_usage/test_logging_config.py b/tests/copilot_usage/test_logging_config.py index 23d7a07..fd9cbde 100644 --- a/tests/copilot_usage/test_logging_config.py +++ b/tests/copilot_usage/test_logging_config.py @@ -1,5 +1,11 @@ """Tests for copilot_usage.logging_config — setup_logging, _emoji_patcher, LEVEL_EMOJI.""" +# pyright: reportPrivateUsage=false +# pyright: reportUnknownMemberType=false +# pyright: reportAttributeAccessIssue=false +# pyright: reportUnknownVariableType=false +# pyright: reportUnknownArgumentType=false + from __future__ import annotations import sys @@ -8,11 +14,10 @@ from copilot_usage.logging_config import ( LEVEL_EMOJI, - _emoji_patcher, # pyright: ignore[reportPrivateUsage] + _emoji_patcher, setup_logging, ) - # --------------------------------------------------------------------------- # setup_logging # --------------------------------------------------------------------------- @@ -21,28 +26,28 @@ def test_setup_logging_adds_exactly_one_sink() -> None: """After setup_logging(), logger has exactly one handler.""" setup_logging() - assert len(logger._core.handlers) == 1 # noqa: SLF001 # pyright: ignore[reportPrivateUsage] + assert len(logger._core.handlers) == 1 def test_setup_logging_idempotent() -> None: """Calling setup_logging() twice still results in exactly 1 sink.""" setup_logging() setup_logging() - assert len(logger._core.handlers) == 1 # noqa: SLF001 # pyright: ignore[reportPrivateUsage] + assert len(logger._core.handlers) == 1 def test_setup_logging_targets_stderr() -> None: """After setup_logging(), the single sink targets sys.stderr.""" setup_logging() - handler = next(iter(logger._core.handlers.values())) # noqa: SLF001 # pyright: ignore[reportPrivateUsage] - assert handler._sink._stream is sys.stderr # noqa: SLF001 # pyright: ignore[reportPrivateUsage] + handler = next(iter(logger._core.handlers.values())) + assert handler._sink._stream is sys.stderr def test_setup_logging_level_is_warning() -> None: """After setup_logging(), the minimum log level is WARNING.""" setup_logging() - handler = next(iter(logger._core.handlers.values())) # noqa: SLF001 # pyright: ignore[reportPrivateUsage] - assert handler.levelno == logger.level("WARNING").no # pyright: ignore[reportPrivateUsage] + handler = next(iter(logger._core.handlers.values())) + assert handler.levelno == logger.level("WARNING").no # ---------------------------------------------------------------------------