Merge pull request #7571 from bluetech/logging-setlevel-handler-restore
logging: fix capture handler level not reset on teardown after caplog.set_level()
This commit is contained in:
		
						commit
						cefe064bb0
					
				| 
						 | 
					@ -345,6 +345,7 @@ class LogCaptureFixture:
 | 
				
			||||||
        """Creates a new funcarg."""
 | 
					        """Creates a new funcarg."""
 | 
				
			||||||
        self._item = item
 | 
					        self._item = item
 | 
				
			||||||
        # dict of log name -> log level
 | 
					        # dict of log name -> log level
 | 
				
			||||||
 | 
					        self._initial_handler_level = None  # type: Optional[int]
 | 
				
			||||||
        self._initial_logger_levels = {}  # type: Dict[Optional[str], int]
 | 
					        self._initial_logger_levels = {}  # type: Dict[Optional[str], int]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _finalize(self) -> None:
 | 
					    def _finalize(self) -> None:
 | 
				
			||||||
| 
						 | 
					@ -353,6 +354,8 @@ class LogCaptureFixture:
 | 
				
			||||||
        This restores the log levels changed by :meth:`set_level`.
 | 
					        This restores the log levels changed by :meth:`set_level`.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        # restore log levels
 | 
					        # restore log levels
 | 
				
			||||||
 | 
					        if self._initial_handler_level is not None:
 | 
				
			||||||
 | 
					            self.handler.setLevel(self._initial_handler_level)
 | 
				
			||||||
        for logger_name, level in self._initial_logger_levels.items():
 | 
					        for logger_name, level in self._initial_logger_levels.items():
 | 
				
			||||||
            logger = logging.getLogger(logger_name)
 | 
					            logger = logging.getLogger(logger_name)
 | 
				
			||||||
            logger.setLevel(level)
 | 
					            logger.setLevel(level)
 | 
				
			||||||
| 
						 | 
					@ -434,6 +437,7 @@ class LogCaptureFixture:
 | 
				
			||||||
        # save the original log-level to restore it during teardown
 | 
					        # save the original log-level to restore it during teardown
 | 
				
			||||||
        self._initial_logger_levels.setdefault(logger, logger_obj.level)
 | 
					        self._initial_logger_levels.setdefault(logger, logger_obj.level)
 | 
				
			||||||
        logger_obj.setLevel(level)
 | 
					        logger_obj.setLevel(level)
 | 
				
			||||||
 | 
					        self._initial_handler_level = self.handler.level
 | 
				
			||||||
        self.handler.setLevel(level)
 | 
					        self.handler.setLevel(level)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @contextmanager
 | 
					    @contextmanager
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from _pytest.logging import caplog_records_key
 | 
					from _pytest.logging import caplog_records_key
 | 
				
			||||||
 | 
					from _pytest.pytester import Testdir
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logger = logging.getLogger(__name__)
 | 
					logger = logging.getLogger(__name__)
 | 
				
			||||||
sublogger = logging.getLogger(__name__ + ".baz")
 | 
					sublogger = logging.getLogger(__name__ + ".baz")
 | 
				
			||||||
| 
						 | 
					@ -27,8 +28,11 @@ def test_change_level(caplog):
 | 
				
			||||||
    assert "CRITICAL" in caplog.text
 | 
					    assert "CRITICAL" in caplog.text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_change_level_undo(testdir):
 | 
					def test_change_level_undo(testdir: Testdir) -> None:
 | 
				
			||||||
    """Ensure that 'set_level' is undone after the end of the test"""
 | 
					    """Ensure that 'set_level' is undone after the end of the test.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tests the logging output themselves (affacted both by logger and handler levels).
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    testdir.makepyfile(
 | 
					    testdir.makepyfile(
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        import logging
 | 
					        import logging
 | 
				
			||||||
| 
						 | 
					@ -50,6 +54,33 @@ def test_change_level_undo(testdir):
 | 
				
			||||||
    result.stdout.no_fnmatch_line("*log from test2*")
 | 
					    result.stdout.no_fnmatch_line("*log from test2*")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_change_level_undos_handler_level(testdir: Testdir) -> None:
 | 
				
			||||||
 | 
					    """Ensure that 'set_level' is undone after the end of the test (handler).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Issue #7569. Tests the handler level specifically.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    testdir.makepyfile(
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def test1(caplog):
 | 
				
			||||||
 | 
					            assert caplog.handler.level == 0
 | 
				
			||||||
 | 
					            caplog.set_level(41)
 | 
				
			||||||
 | 
					            assert caplog.handler.level == 41
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def test2(caplog):
 | 
				
			||||||
 | 
					            assert caplog.handler.level == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def test3(caplog):
 | 
				
			||||||
 | 
					            assert caplog.handler.level == 0
 | 
				
			||||||
 | 
					            caplog.set_level(43)
 | 
				
			||||||
 | 
					            assert caplog.handler.level == 43
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    result = testdir.runpytest()
 | 
				
			||||||
 | 
					    result.assert_outcomes(passed=3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_with_statement(caplog):
 | 
					def test_with_statement(caplog):
 | 
				
			||||||
    with caplog.at_level(logging.INFO):
 | 
					    with caplog.at_level(logging.INFO):
 | 
				
			||||||
        logger.debug("handler DEBUG level")
 | 
					        logger.debug("handler DEBUG level")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue