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

[7431] Add --suppress-logger CLI option #10371

Merged
merged 12 commits into from
Oct 23, 2022
1 change: 1 addition & 0 deletions changelog/7431.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``--logger-disable`` CLI option added to disable individual loggers.
nicoddemus marked this conversation as resolved.
Show resolved Hide resolved
17 changes: 17 additions & 0 deletions src/_pytest/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,13 @@ def add_option_ini(option, dest, default=None, type=None, **kwargs):
default=None,
help="Auto-indent multiline messages passed to the logging module. Accepts true|on, false|off or an integer.",
)
group.addoption(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the new option just a command line option and not an ini option? I guess that it can't be specified in e.g. pytest.ini, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is possible to use addopts to set that for every invocation if one chooses, is that what you are asking?

Copy link
Contributor

@twmr twmr Oct 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, kind of. In the logging plugin we have the add_option_ini function which is used for most parameters of the logging plugin. I think that whenever we don't use this function, we should explain in a comment why we don't use it. Even better would be an explanation in the docstring of pytest_addoption in logging.py that explains if new options should be added as ini options, as cli options or as both.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's still time to change this, as 7.2.0 was not released yet. 😁

"--logger-disable",
itxasos23 marked this conversation as resolved.
Show resolved Hide resolved
action="append",
default=[],
dest="logger_disable",
help="Disable loggers by name",
itxasos23 marked this conversation as resolved.
Show resolved Hide resolved
)


_HandlerType = TypeVar("_HandlerType", bound=logging.Handler)
Expand Down Expand Up @@ -594,6 +601,16 @@ def __init__(self, config: Config) -> None:
get_option_ini(config, "log_auto_indent"),
)
self.log_cli_handler.setFormatter(log_cli_formatter)
self._disable_logger(loggers_to_disable=config.option.logger_disable)

def _disable_logger(self, loggers_to_disable: List[str]) -> None:
itxasos23 marked this conversation as resolved.
Show resolved Hide resolved
if not loggers_to_disable:
return

logger_names_to_suppress = set(loggers_to_disable)
for name in logger_names_to_suppress:
itxasos23 marked this conversation as resolved.
Show resolved Hide resolved
logger = logging.getLogger(name)
logger.disabled = True

def _create_formatter(self, log_format, log_date_format, auto_indent):
# Color option doesn't exist if terminal plugin is disabled.
Expand Down
75 changes: 75 additions & 0 deletions testing/logging/test_reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -1165,3 +1165,78 @@ def test_log_file_cli_subdirectories_are_successfully_created(
result = pytester.runpytest("--log-file=foo/bar/logf.log")
assert "logf.log" in os.listdir(expected)
assert result.ret == ExitCode.OK


def test_disable_loggers(testdir):
testdir.makepyfile(
"""
import logging
import os
disabled_log = logging.getLogger('disabled')
test_log = logging.getLogger('test')
def test_logger_propagation(caplog):
with caplog.at_level(logging.DEBUG):
disabled_log.warning("no log; no stderr")
test_log.debug("Visible text!")
print(os.linesep)
itxasos23 marked this conversation as resolved.
Show resolved Hide resolved
assert caplog.record_tuples == [('test', 10, 'Visible text!')]
"""
)
result = testdir.runpytest("--logger-disable=disabled", "-s")
assert result.ret == ExitCode.OK
assert not result.stderr.lines


def test_disable_loggers_does_not_propagate(testdir):
testdir.makepyfile(
"""
import logging
import os

parent_logger = logging.getLogger("parent")
child_logger = parent_logger.getChild("child")

def test_logger_propagation_to_parent(caplog):
with caplog.at_level(logging.DEBUG):
child_logger.warning("some message")
itxasos23 marked this conversation as resolved.
Show resolved Hide resolved
print(os.linesep)
itxasos23 marked this conversation as resolved.
Show resolved Hide resolved
assert not caplog.record_tuples
"""
)

result = testdir.runpytest("--logger-disable=parent.child", "-s")
assert result.ret == ExitCode.OK
assert not result.stderr.lines


def test_disabled_loggers_help(testdir):
itxasos23 marked this conversation as resolved.
Show resolved Hide resolved
result = testdir.runpytest("-h")
result.stdout.fnmatch_lines(
[" --logger-disable=LOGGER_DISABLE", "*Disable loggers by name*"]
)


def test_log_disabling_works_with_log_cli(testdir):
testdir.makepyfile(
"""
import logging
disabled_log = logging.getLogger('disabled')
test_log = logging.getLogger('test')

def test_log_cli_works(caplog):
test_log.info("Visible text!")
disabled_log.warning("This string will be suppressed.")
"""
)
result = testdir.runpytest(
"--log-cli-level=DEBUG",
"--logger-disable=disabled",
)
assert result.ret == ExitCode.OK
result.stdout.fnmatch_lines(
"INFO test:test_log_disabling_works_with_log_cli.py:6 Visible text!"
)
result.stdout.no_fnmatch_line(
"WARNING disabled:test_log_disabling_works_with_log_cli.py:7 This string will be suppressed."
)
assert not result.stderr.lines