Skip to content

Commit 2075953

Browse files
committed
Fix logging handler option isolation
1 parent b384cf3 commit 2075953

2 files changed

Lines changed: 90 additions & 7 deletions

File tree

src/_pytask/logging.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -437,10 +437,10 @@ def from_config(cls, config: dict[str, Any]) -> LoggingManager:
437437
config["log_format"], datefmt=config["log_date_format"]
438438
),
439439
live_log_handler=live_log_handler,
440-
log_cli_level=log_cli_level,
440+
log_cli_level=log_cli_level if live_log_handler is not None else None,
441441
log_level=config["log_level"],
442442
log_file_handler=log_file_handler,
443-
log_file_level=log_file_level,
443+
log_file_level=log_file_level if log_file_handler is not None else None,
444444
)
445445

446446
@contextlib.contextmanager
@@ -453,11 +453,12 @@ def _catching_logs(self) -> Generator[None, None, None]:
453453
handlers.append(self.log_file_handler)
454454

455455
original_level = root_logger.level
456+
report_level = self.log_level if self.log_level is not None else original_level
456457
configured_levels = [
457458
level
458459
for level in (
460+
report_level,
459461
self.log_cli_level,
460-
self.log_level,
461462
self.log_file_level,
462463
)
463464
if level not in (None, logging.NOTSET)
@@ -469,9 +470,7 @@ def _catching_logs(self) -> Generator[None, None, None]:
469470
# reconfigures the root logger can affect pytask's own logging handlers.
470471
for handler in handlers:
471472
handler.setLevel(
472-
self.log_level
473-
if handler is self.report_handler and self.log_level is not None
474-
else handler.level
473+
report_level if handler is self.report_handler else handler.level
475474
)
476475
root_logger.addHandler(handler)
477476

@@ -562,7 +561,7 @@ def _create_log_file_handler(
562561
def _create_live_log_handler(
563562
*, config: dict[str, Any], log_cli_level: int | None
564563
) -> logging.Handler | None:
565-
if not (config["log_cli"] or config["log_cli_level"] is not None):
564+
if not config["log_cli"]:
566565
return None
567566

568567
live_log_handler = LiveLogHandler(plugin_manager=config["pm"])

tests/test_logging.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,90 @@ def task_example(produces=Path("out.txt")):
211211
assert "INFO:hello from live log" in result.stdout
212212

213213

214+
def test_log_cli_level_from_config_does_not_enable_live_logging(tmp_path):
215+
source = """
216+
import logging
217+
218+
logger = logging.getLogger(__name__)
219+
220+
def task_example():
221+
logger.info("hello from live log")
222+
"""
223+
tmp_path.joinpath("task_module.py").write_text(textwrap.dedent(source))
224+
tmp_path.joinpath("pyproject.toml").write_text(
225+
textwrap.dedent(
226+
"""
227+
[tool.pytask.ini_options]
228+
log_cli = false
229+
log_cli_level = "INFO"
230+
log_cli_format = "%(levelname)s:%(message)s"
231+
"""
232+
)
233+
)
234+
235+
result = run_in_subprocess(("pytask", tmp_path.as_posix()), cwd=tmp_path)
236+
237+
assert result.exit_code == ExitCode.OK
238+
assert "INFO:hello from live log" not in result.stdout
239+
240+
241+
@pytest.mark.parametrize(
242+
("destination_args", "expected_destination_output"),
243+
[
244+
(
245+
(
246+
"--log-cli",
247+
"--log-cli-level=INFO",
248+
"--log-cli-format=%(levelname)s:%(message)s",
249+
),
250+
"INFO:hello from destination-specific log",
251+
),
252+
(
253+
(
254+
"--log-file=build.log",
255+
"--log-file-level=INFO",
256+
"--log-file-format=%(levelname)s:%(message)s",
257+
),
258+
None,
259+
),
260+
],
261+
ids=["live-log", "log-file"],
262+
)
263+
def test_destination_specific_levels_do_not_affect_failure_report(
264+
tmp_path, destination_args, expected_destination_output
265+
):
266+
source = """
267+
import logging
268+
269+
logger = logging.getLogger(__name__)
270+
271+
def task_example():
272+
logger.info("hello from destination-specific log")
273+
raise Exception("boom")
274+
"""
275+
tmp_path.joinpath("task_module.py").write_text(textwrap.dedent(source))
276+
277+
result = run_in_subprocess(
278+
(
279+
"pytask",
280+
tmp_path.as_posix(),
281+
"--show-capture=log",
282+
*destination_args,
283+
),
284+
cwd=tmp_path,
285+
)
286+
287+
assert result.exit_code == ExitCode.FAILED
288+
assert "Captured log" not in result.stdout
289+
if expected_destination_output is not None:
290+
assert expected_destination_output in result.stdout
291+
else:
292+
assert (
293+
tmp_path.joinpath("build.log").read_text()
294+
== "INFO:hello from destination-specific log\n"
295+
)
296+
297+
214298
@pytest.mark.parametrize(
215299
("amount", "unit", "short_label", "expectation", "expected"),
216300
[

0 commit comments

Comments
 (0)