Skip to content

Handle logging.disable() in caplog.set_level and caplog.at_level #8711

@alexlambson

Description

@alexlambson

What's the problem this feature will solve?

Currently, caplog will not catch logs if logging.disable(LEVEL) was called somewhere, in my case it's called in my django
settings for test runs.

Describe the solution you'd like

caplog.at_level and caplog.set_level should both take a new arg called force_enable that tells caplog to set the disable setting to one level below whatever level was requested to caplog.
Or it should force enable the logging level if rootLogger.manager.disable >= level so that logging will always
be enabled for the level a test is trying to capture.

This will allow caplog to capture logs at the desired level even if they were disabled.

e.g.

# settings/testing.py
# disables all logs
import logging
logging.disable(logging.CRITICAL)


# test_file.py
import logging


def test_stuff(caplog):
    caplog.set_level(logging.WARNING)
    logging.error("Sierra 117")
    assert len(caplog.records) == 1
    assert "117" in caplog.text

The test will currently fail because caplog doesn't override logging.disable which is a separate setting from log level.

My proposal is to add a call to logging.disable(max(level-10, 0)) inside both set_level and at_level. The -10 means disable everything below the requested level for caplog. We set a minimum of 0 because that's the lowest log level.

This can be reset by adding an attribute to keep track of the initial disabled level, similar to the one added to fix #7133.

Alternative Solutions

This is my current workaround in one of my tests

with caplog.at_level(logging.WARNING):
    # logging.disable needs to be called because caplog doesn't handle disabled logging.
    logging.disable(logging.WARNING)
    # inside this request a `logging.error()` is called.
    response = ah_client.get("/api/redacted/")
    # re-disable all logs.
    logging.disable(logging.CRITICAL)

Additional context

I have an example PR that I can transition to a full PR if the team decides they want this behavior
alexlambson#1

Metadata

Metadata

Assignees

No one assigned

    Labels

    plugin: loggingrelated to the logging builtin plugintype: proposalproposal for a new feature, often to gather opinions or design the API around the new feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions