logging: use item's store for private attributes

This makes things type-safe and properly private.
This commit is contained in:
Ran Benita 2020-05-17 14:58:04 +03:00
parent d4dfe863c9
commit ac6c02f1e2
3 changed files with 17 additions and 11 deletions

View File

@ -0,0 +1,2 @@
The `item.catch_log_handler` and `item.catch_log_handlers` attributes, set by the
logging plugin and never meant to be public , are no longer available.

View File

@ -17,10 +17,14 @@ from _pytest.config import _strtobool
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import create_terminal_writer from _pytest.config import create_terminal_writer
from _pytest.pathlib import Path from _pytest.pathlib import Path
from _pytest.store import StoreKey
DEFAULT_LOG_FORMAT = "%(levelname)-8s %(name)s:%(filename)s:%(lineno)d %(message)s" DEFAULT_LOG_FORMAT = "%(levelname)-8s %(name)s:%(filename)s:%(lineno)d %(message)s"
DEFAULT_LOG_DATE_FORMAT = "%H:%M:%S" DEFAULT_LOG_DATE_FORMAT = "%H:%M:%S"
_ANSI_ESCAPE_SEQ = re.compile(r"\x1b\[[\d;]+m") _ANSI_ESCAPE_SEQ = re.compile(r"\x1b\[[\d;]+m")
catch_log_handler_key = StoreKey["LogCaptureHandler"]()
catch_log_handlers_key = StoreKey[Dict[str, "LogCaptureHandler"]]()
def _remove_ansi_escape_sequences(text): def _remove_ansi_escape_sequences(text):
@ -317,7 +321,7 @@ class LogCaptureHandler(logging.StreamHandler):
class LogCaptureFixture: class LogCaptureFixture:
"""Provides access and control of log capturing.""" """Provides access and control of log capturing."""
def __init__(self, item) -> None: def __init__(self, item: nodes.Node) -> None:
"""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
@ -338,7 +342,7 @@ class LogCaptureFixture:
""" """
:rtype: LogCaptureHandler :rtype: LogCaptureHandler
""" """
return self._item.catch_log_handler # type: ignore[no-any-return] return self._item._store[catch_log_handler_key]
def get_records(self, when: str) -> List[logging.LogRecord]: def get_records(self, when: str) -> List[logging.LogRecord]:
""" """
@ -352,9 +356,9 @@ class LogCaptureFixture:
.. versionadded:: 3.4 .. versionadded:: 3.4
""" """
handler = self._item.catch_log_handlers.get(when) handler = self._item._store[catch_log_handlers_key].get(when)
if handler: if handler:
return handler.records # type: ignore[no-any-return] return handler.records
else: else:
return [] return []
@ -645,16 +649,15 @@ class LoggingPlugin:
yield # run the test yield # run the test
return return
if not hasattr(item, "catch_log_handlers"): empty = {} # type: Dict[str, LogCaptureHandler]
item.catch_log_handlers = {} # type: ignore[attr-defined] item._store.setdefault(catch_log_handlers_key, empty)[when] = log_handler
item.catch_log_handlers[when] = log_handler # type: ignore[attr-defined] item._store[catch_log_handler_key] = log_handler
item.catch_log_handler = log_handler # type: ignore[attr-defined]
try: try:
yield # run test yield # run test
finally: finally:
if when == "teardown": if when == "teardown":
del item.catch_log_handler # type: ignore[attr-defined] del item._store[catch_log_handlers_key]
del item.catch_log_handlers # type: ignore[attr-defined] del item._store[catch_log_handler_key]
if self.print_logs: if self.print_logs:
# Add a captured log section to the report. # Add a captured log section to the report.

View File

@ -1,6 +1,7 @@
import logging import logging
import pytest import pytest
from _pytest.logging import catch_log_handlers_key
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
sublogger = logging.getLogger(__name__ + ".baz") sublogger = logging.getLogger(__name__ + ".baz")
@ -136,4 +137,4 @@ def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardow
assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]
# This reaches into private API, don't use this type of thing in real tests! # This reaches into private API, don't use this type of thing in real tests!
assert set(caplog._item.catch_log_handlers.keys()) == {"setup", "call"} assert set(caplog._item._store[catch_log_handlers_key]) == {"setup", "call"}