Skip to content

Commit 9e1804a

Browse files
authored
Add --log-disable CLI option (#10371)
Fixes #7431
1 parent bc2c3b6 commit 9e1804a

File tree

4 files changed

+93
-0
lines changed

4 files changed

+93
-0
lines changed

changelog/7431.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``--log-disable`` CLI option added to disable individual loggers.

doc/en/how-to/logging.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ These options can also be customized through ``pytest.ini`` file:
5555
log_format = %(asctime)s %(levelname)s %(message)s
5656
log_date_format = %Y-%m-%d %H:%M:%S
5757
58+
Specific loggers can be disabled via ``--log-disable={logger_name}``.
59+
This argument can be passed multiple times:
60+
61+
.. code-block:: bash
62+
63+
pytest --log-disable=main --log-disable=testing
64+
5865
Further it is possible to disable reporting of captured content (stdout,
5966
stderr and logs) on failed tests completely with:
6067

src/_pytest/logging.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,13 @@ def add_option_ini(option, dest, default=None, type=None, **kwargs):
297297
default=None,
298298
help="Auto-indent multiline messages passed to the logging module. Accepts true|on, false|off or an integer.",
299299
)
300+
group.addoption(
301+
"--log-disable",
302+
action="append",
303+
default=[],
304+
dest="logger_disable",
305+
help="Disable a logger by name. Can be passed multipe times.",
306+
)
300307

301308

302309
_HandlerType = TypeVar("_HandlerType", bound=logging.Handler)
@@ -594,6 +601,15 @@ def __init__(self, config: Config) -> None:
594601
get_option_ini(config, "log_auto_indent"),
595602
)
596603
self.log_cli_handler.setFormatter(log_cli_formatter)
604+
self._disable_loggers(loggers_to_disable=config.option.logger_disable)
605+
606+
def _disable_loggers(self, loggers_to_disable: List[str]) -> None:
607+
if not loggers_to_disable:
608+
return
609+
610+
for name in loggers_to_disable:
611+
logger = logging.getLogger(name)
612+
logger.disabled = True
597613

598614
def _create_formatter(self, log_format, log_date_format, auto_indent):
599615
# Color option doesn't exist if terminal plugin is disabled.

testing/logging/test_reporting.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,3 +1165,72 @@ def test_log_file_cli_subdirectories_are_successfully_created(
11651165
result = pytester.runpytest("--log-file=foo/bar/logf.log")
11661166
assert "logf.log" in os.listdir(expected)
11671167
assert result.ret == ExitCode.OK
1168+
1169+
1170+
def test_disable_loggers(testdir):
1171+
testdir.makepyfile(
1172+
"""
1173+
import logging
1174+
import os
1175+
disabled_log = logging.getLogger('disabled')
1176+
test_log = logging.getLogger('test')
1177+
def test_logger_propagation(caplog):
1178+
with caplog.at_level(logging.DEBUG):
1179+
disabled_log.warning("no log; no stderr")
1180+
test_log.debug("Visible text!")
1181+
assert caplog.record_tuples == [('test', 10, 'Visible text!')]
1182+
"""
1183+
)
1184+
result = testdir.runpytest("--log-disable=disabled", "-s")
1185+
assert result.ret == ExitCode.OK
1186+
assert not result.stderr.lines
1187+
1188+
1189+
def test_disable_loggers_does_not_propagate(testdir):
1190+
testdir.makepyfile(
1191+
"""
1192+
import logging
1193+
import os
1194+
1195+
parent_logger = logging.getLogger("parent")
1196+
child_logger = parent_logger.getChild("child")
1197+
1198+
def test_logger_propagation_to_parent(caplog):
1199+
with caplog.at_level(logging.DEBUG):
1200+
parent_logger.warning("some parent logger message")
1201+
child_logger.warning("some child logger message")
1202+
assert len(caplog.record_tuples) == 1
1203+
assert caplog.record_tuples[0][0] == "parent"
1204+
assert caplog.record_tuples[0][2] == "some parent logger message"
1205+
"""
1206+
)
1207+
1208+
result = testdir.runpytest("--log-disable=parent.child", "-s")
1209+
assert result.ret == ExitCode.OK
1210+
assert not result.stderr.lines
1211+
1212+
1213+
def test_log_disabling_works_with_log_cli(testdir):
1214+
testdir.makepyfile(
1215+
"""
1216+
import logging
1217+
disabled_log = logging.getLogger('disabled')
1218+
test_log = logging.getLogger('test')
1219+
1220+
def test_log_cli_works(caplog):
1221+
test_log.info("Visible text!")
1222+
disabled_log.warning("This string will be suppressed.")
1223+
"""
1224+
)
1225+
result = testdir.runpytest(
1226+
"--log-cli-level=DEBUG",
1227+
"--log-disable=disabled",
1228+
)
1229+
assert result.ret == ExitCode.OK
1230+
result.stdout.fnmatch_lines(
1231+
"INFO test:test_log_disabling_works_with_log_cli.py:6 Visible text!"
1232+
)
1233+
result.stdout.no_fnmatch_line(
1234+
"WARNING disabled:test_log_disabling_works_with_log_cli.py:7 This string will be suppressed."
1235+
)
1236+
assert not result.stderr.lines

0 commit comments

Comments
 (0)