Skip to content

Commit 85a06cf

Browse files
authored
Merge pull request #7227 from bluetech/logging-reuse-handler
logging: reuse LoggingCaptureHandler instance since it's expensive to create
2 parents fe2febf + d2d11a8 commit 85a06cf

File tree

2 files changed

+11
-15
lines changed

2 files changed

+11
-15
lines changed

src/_pytest/logging.py

+9-13
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
DEFAULT_LOG_DATE_FORMAT = "%H:%M:%S"
2828
_ANSI_ESCAPE_SEQ = re.compile(r"\x1b\[[\d;]+m")
2929
catch_log_handler_key = StoreKey["LogCaptureHandler"]()
30-
catch_log_handlers_key = StoreKey[Dict[str, "LogCaptureHandler"]]()
30+
catch_log_records_key = StoreKey[Dict[str, List[logging.LogRecord]]]()
3131

3232

3333
def _remove_ansi_escape_sequences(text):
@@ -351,11 +351,7 @@ def get_records(self, when: str) -> List[logging.LogRecord]:
351351
352352
.. versionadded:: 3.4
353353
"""
354-
handler = self._item._store[catch_log_handlers_key].get(when)
355-
if handler:
356-
return handler.records
357-
else:
358-
return []
354+
return self._item._store[catch_log_records_key].get(when, [])
359355

360356
@property
361357
def text(self):
@@ -497,6 +493,8 @@ def __init__(self, config: Config) -> None:
497493
get_option_ini(config, "log_auto_indent"),
498494
)
499495
self.log_level = get_log_level_for_setting(config, "log_level")
496+
self.log_handler = LogCaptureHandler()
497+
self.log_handler.setFormatter(self.formatter)
500498

501499
# File logging.
502500
self.log_file_level = get_log_level_for_setting(config, "log_file_level")
@@ -639,10 +637,9 @@ def pytest_runtest_logreport(self):
639637

640638
def _runtest_for(self, item: nodes.Item, when: str) -> Generator[None, None, None]:
641639
"""Implements the internals of pytest_runtest_xxx() hook."""
642-
log_handler = LogCaptureHandler()
643-
log_handler.setFormatter(self.formatter)
644-
with catching_logs(log_handler, level=self.log_level):
645-
item._store[catch_log_handlers_key][when] = log_handler
640+
with catching_logs(self.log_handler, level=self.log_level) as log_handler:
641+
log_handler.reset()
642+
item._store[catch_log_records_key][when] = log_handler.records
646643
item._store[catch_log_handler_key] = log_handler
647644

648645
yield
@@ -654,8 +651,7 @@ def _runtest_for(self, item: nodes.Item, when: str) -> Generator[None, None, Non
654651
def pytest_runtest_setup(self, item):
655652
self.log_cli_handler.set_when("setup")
656653

657-
empty = {} # type: Dict[str, LogCaptureHandler]
658-
item._store[catch_log_handlers_key] = empty
654+
item._store[catch_log_records_key] = {}
659655
yield from self._runtest_for(item, "setup")
660656

661657
@pytest.hookimpl(hookwrapper=True)
@@ -669,7 +665,7 @@ def pytest_runtest_teardown(self, item):
669665
self.log_cli_handler.set_when("teardown")
670666

671667
yield from self._runtest_for(item, "teardown")
672-
del item._store[catch_log_handlers_key]
668+
del item._store[catch_log_records_key]
673669
del item._store[catch_log_handler_key]
674670

675671
@pytest.hookimpl

testing/logging/test_fixture.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22

33
import pytest
4-
from _pytest.logging import catch_log_handlers_key
4+
from _pytest.logging import catch_log_records_key
55

66
logger = logging.getLogger(__name__)
77
sublogger = logging.getLogger(__name__ + ".baz")
@@ -137,4 +137,4 @@ def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardow
137137
assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]
138138

139139
# This reaches into private API, don't use this type of thing in real tests!
140-
assert set(caplog._item._store[catch_log_handlers_key]) == {"setup", "call"}
140+
assert set(caplog._item._store[catch_log_records_key]) == {"setup", "call"}

0 commit comments

Comments
 (0)