MCPcopy
hub / github.com/pallets/click / test_capture_fd_logging_handler

Function test_capture_fd_logging_handler

tests/test_testing.py:600–642  ·  tests/test_testing.py::test_capture_fd_logging_handler

capture='fd' captures logging output from a handler holding a stale stderr reference (issue #2827). stdlib logging.StreamHandler grabs sys.stderr at configuration time. Under normal CliRunner (sys-level capture), the handler still writes to the original stream object and output is l

(tmp_path)

Source from the content-addressed store, hash-verified

598
599@needs_fd_capture
600def test_capture_fd_logging_handler(tmp_path):
601 class="st">"""capture=&class="cm">#x27;fd' captures logging output from a handler holding a stale
602 stderr reference (issue class="cm">#2827).
603
604 stdlib logging.StreamHandler grabs sys.stderr at configuration time.
605 Under normal CliRunner (sys-level capture), the handler still writes
606 to the original stream object and output is lost. fd-level capture
607 redirects the underlying file descriptor, so the writes are captured.
608 class="st">"""
609 import logging
610
611 class="cm"># Create a writer backed by the real fd 2, simulating a handler
612 class="cm"># configured at import time before pytest or CliRunner replaced
613 class="cm"># sys.stderr. open(2, closefd=False) mirrors the real scenario:
614 class="cm"># the original sys.stderr is a TextIOWrapper -> BufferedWriter ->
615 class="cm"># FileIO(fd=2).
616 stale_stderr = open(2, class="st">"w", closefd=False) class="cm"># noqa: SIM115
617 handler = logging.StreamHandler(stale_stderr)
618 handler.setFormatter(logging.Formatter(class="st">"%(message)s"))
619
620 logger = logging.getLogger(fclass="st">"click_test_{tmp_path.name}")
621 logger.addHandler(handler)
622 logger.setLevel(logging.INFO)
623 logger.propagate = False
624
625 @click.command()
626 def cli():
627 logger.info(class="st">"log from stale handler")
628 click.echo(class="st">"normal echo")
629
630 class="cm"># sys-level capture misses the log line (it bypasses sys.stderr).
631 runner_sys = CliRunner(capture=class="st">"sys")
632 result_sys = runner_sys.invoke(cli)
633 assert class="st">"normal echo" in result_sys.output
634 assert class="st">"log from stale handler" not in result_sys.output
635
636 class="cm"># fd-level capture catches it by redirecting fd 2.
637 runner_fd = CliRunner(capture=class="st">"fd")
638 result_fd = runner_fd.invoke(cli)
639 assert class="st">"normal echo" in result_fd.output
640 assert class="st">"log from stale handler" in result_fd.output
641
642 logger.removeHandler(handler)
643
644
645@needs_fd_capture

Callers

nothing calls this directly

Calls 3

invokeMethod · 0.95
CliRunnerClass · 0.90
openFunction · 0.85

Tested by

no test coverage detected