Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a set_filter() context manager to the caplog fixture #11610

Closed
jenstroeger opened this issue Nov 13, 2023 · 5 comments · Fixed by #11625
Closed

Add a set_filter() context manager to the caplog fixture #11610

jenstroeger opened this issue Nov 13, 2023 · 5 comments · Fixed by #11625

Comments

@jenstroeger
Copy link
Contributor

What's the problem this feature will solve?

I need to test a custom filter for logging, and currently I use one of the following two approaches:

def test_filter(caplog: pytest.LogCaptureFixture) -> None:
    caplog.set_level(logging.INFO)

    logger = logging.getLogger(__name__)  # This test module's logger.
    filter_ = SchnufteCustomFilter()
    logger.addFilter(filter_)

    # Run tests.
    assert len(caplog.record_tuples) == 1
    assert caplog.record_tuples[0] == ("test_custom_filter", 20, "Schnufte!")

    logger.removeFilter(filter_)

or

def test_filter(caplog: pytest.LogCaptureFixture) -> None:
    caplog.set_level(logging.INFO)

    filter_ = SchnufteCustomFilter()
    caplog.handler.addFilter(filter_)

    # Run tests.
    assert len(caplog.record_tuples) == 1
    assert caplog.record_tuples[0] == ("test_custom_filter", 20, "Schnufte!")     

    caplog.handler.removeFilter(filter_)

Describe the solution you'd like

Similar to the at_level() context manager I think it would be useful to wrap the second of the above filter setups into a custom context manager, that I can then call like so:

def test_filter(caplog: pytest.LogCaptureFixture) -> None:
    caplog.set_level(logging.INFO)

    filter_ = SchnufteCustomFilter()
    with caplog.set_filter(filter_):  # use_filter() or with_filter() or ...
        # Run tests.
        assert len(caplog.record_tuples) == 1
        assert caplog.record_tuples[0] == ("test_custom_filter", 20, "Schnufte!")     

Alternative Solutions

See above’s examples, I guess.

Additional context

I’m happy to give a PR a shot: I suppose the change would be adding a method to the LogCaptureFixture, for example:

@final
class LogCaptureFixture:

    @contextmanager
    def set_filter(filter_: logging.Filter) -> Generator[None, None, None]:  # Type needs to be aligned with _FilterType from stdlib/typeshed.
        self.handler.addFilter(filter_)
        try:
            yield
        finally:
            self.handler.removeFilter(filter_)
@nicoddemus
Copy link
Member

👍 from me.

Bikesheding:

with caplog.with_filter(SchnufteCustomFilter()): ...

with caplog.filtering(SchnufteCustomFilter()): ...

I prefer the latter, reads naturally to me (although I'm not a native speaker).

@jenstroeger
Copy link
Contributor Author

@nicoddemus shall I go ahead and create a PR?

@nicoddemus
Copy link
Member

Yes please

@jenstroeger
Copy link
Contributor Author

@nicoddemus what’s the recommendation regarding testing: the at_level() context manager has its own test functions here, so I could add the new filtering() context manager into those existing functions, or create new functions?

@nicoddemus
Copy link
Member

New functions are preferred. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants