Skip to content

Commit cefe064

Browse files
authored
Merge pull request #7571 from bluetech/logging-setlevel-handler-restore
logging: fix capture handler level not reset on teardown after caplog.set_level()
2 parents 422685d + 0e0275d commit cefe064

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

src/_pytest/logging.py

+4
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ def __init__(self, item: nodes.Node) -> None:
345345
"""Creates a new funcarg."""
346346
self._item = item
347347
# dict of log name -> log level
348+
self._initial_handler_level = None # type: Optional[int]
348349
self._initial_logger_levels = {} # type: Dict[Optional[str], int]
349350

350351
def _finalize(self) -> None:
@@ -353,6 +354,8 @@ def _finalize(self) -> None:
353354
This restores the log levels changed by :meth:`set_level`.
354355
"""
355356
# restore log levels
357+
if self._initial_handler_level is not None:
358+
self.handler.setLevel(self._initial_handler_level)
356359
for logger_name, level in self._initial_logger_levels.items():
357360
logger = logging.getLogger(logger_name)
358361
logger.setLevel(level)
@@ -434,6 +437,7 @@ def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> Non
434437
# save the original log-level to restore it during teardown
435438
self._initial_logger_levels.setdefault(logger, logger_obj.level)
436439
logger_obj.setLevel(level)
440+
self._initial_handler_level = self.handler.level
437441
self.handler.setLevel(level)
438442

439443
@contextmanager

testing/logging/test_fixture.py

+33-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44
from _pytest.logging import caplog_records_key
5+
from _pytest.pytester import Testdir
56

67
logger = logging.getLogger(__name__)
78
sublogger = logging.getLogger(__name__ + ".baz")
@@ -27,8 +28,11 @@ def test_change_level(caplog):
2728
assert "CRITICAL" in caplog.text
2829

2930

30-
def test_change_level_undo(testdir):
31-
"""Ensure that 'set_level' is undone after the end of the test"""
31+
def test_change_level_undo(testdir: Testdir) -> None:
32+
"""Ensure that 'set_level' is undone after the end of the test.
33+
34+
Tests the logging output themselves (affacted both by logger and handler levels).
35+
"""
3236
testdir.makepyfile(
3337
"""
3438
import logging
@@ -50,6 +54,33 @@ def test2(caplog):
5054
result.stdout.no_fnmatch_line("*log from test2*")
5155

5256

57+
def test_change_level_undos_handler_level(testdir: Testdir) -> None:
58+
"""Ensure that 'set_level' is undone after the end of the test (handler).
59+
60+
Issue #7569. Tests the handler level specifically.
61+
"""
62+
testdir.makepyfile(
63+
"""
64+
import logging
65+
66+
def test1(caplog):
67+
assert caplog.handler.level == 0
68+
caplog.set_level(41)
69+
assert caplog.handler.level == 41
70+
71+
def test2(caplog):
72+
assert caplog.handler.level == 0
73+
74+
def test3(caplog):
75+
assert caplog.handler.level == 0
76+
caplog.set_level(43)
77+
assert caplog.handler.level == 43
78+
"""
79+
)
80+
result = testdir.runpytest()
81+
result.assert_outcomes(passed=3)
82+
83+
5384
def test_with_statement(caplog):
5485
with caplog.at_level(logging.INFO):
5586
logger.debug("handler DEBUG level")

0 commit comments

Comments
 (0)