Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ Javier Romero
Jeff Rackauckas
Jeff Widman
Jenni Rinker
Jens Tröger
John Eddie Ayson
John Litborn
John Towler
Expand Down
2 changes: 2 additions & 0 deletions changelog/11610.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Added :func:`LogCaptureFixture.filtering() <pytest.LogCaptureFixture.filtering>` context manager that
adds a given :class:`logging.Filter` object to the caplog fixture.
16 changes: 16 additions & 0 deletions src/_pytest/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,22 @@ def at_level(
self.handler.setLevel(handler_orig_level)
logging.disable(original_disable_level)

@contextmanager
def filtering(self, filter_: logging.Filter) -> Generator[None, None, None]:
"""Context manager that temporarily adds the given filter to the caplog's
:meth:`handler` for the 'with' statement block, and removes that filter at the
end of the block.

:param filter_: A custom :class:`logging.Filter` object.

.. versionadded:: 7.5
"""
self.handler.addFilter(filter_)
try:
yield
finally:
self.handler.removeFilter(filter_)


@fixture
def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]:
Expand Down
22 changes: 20 additions & 2 deletions testing/logging/test_fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def test3(caplog):
result.assert_outcomes(passed=3)


def test_with_statement(caplog: pytest.LogCaptureFixture) -> None:
def test_with_statement_at_level(caplog: pytest.LogCaptureFixture) -> None:
with caplog.at_level(logging.INFO):
logger.debug("handler DEBUG level")
logger.info("handler INFO level")
Expand All @@ -159,7 +159,9 @@ def test_with_statement(caplog: pytest.LogCaptureFixture) -> None:
assert "CRITICAL" in caplog.text


def test_with_statement_logging_disabled(caplog: pytest.LogCaptureFixture) -> None:
def test_with_statement_at_level_logging_disabled(
caplog: pytest.LogCaptureFixture,
) -> None:
logging.disable(logging.CRITICAL)
assert logging.root.manager.disable == logging.CRITICAL
with caplog.at_level(logging.WARNING):
Expand All @@ -185,6 +187,22 @@ def test_with_statement_logging_disabled(caplog: pytest.LogCaptureFixture) -> No
assert logging.root.manager.disable == logging.CRITICAL


def test_with_statement_filtering(caplog: pytest.LogCaptureFixture) -> None:
class TestFilter(logging.Filter):
def filter(self, record: logging.LogRecord) -> bool:
record.msg = "filtered handler call"
return True

with caplog.at_level(logging.INFO):
with caplog.filtering(TestFilter()):
logger.info("handler call")
logger.info("handler call")

filtered_tuple, unfiltered_tuple = caplog.record_tuples
assert filtered_tuple == ("test_fixture", 20, "filtered handler call")
assert unfiltered_tuple == ("test_fixture", 20, "handler call")


@pytest.mark.parametrize(
"level_str,expected_disable_level",
[
Expand Down