@@ -289,6 +289,11 @@ def _test_gen_func_fails():
289289 yield # unreachable, keeps this a generator function
290290
291291
292+ def _test_gen_func_yields_then_fails ():
293+ yield "test"
294+ raise RuntimeError ("This is a test." )
295+
296+
292297def _test_gen_func_echo (file = None ):
293298 yield "test"
294299 click .echo ("hello" , file = file )
@@ -451,6 +456,41 @@ def test_echo_via_pager(monkeypatch, capfd, pager_cmd, test, tmp_path):
451456 )
452457
453458
459+ @pytest .mark .skipif (WIN , reason = "Different behavior on windows." )
460+ def test_echo_via_pager_yields_before_exception (monkeypatch , tmp_path ):
461+ """A generator that yields then raises: click writes the partial output to
462+ the pager stream before propagating the exception.
463+
464+ The pager file content is intentionally NOT asserted: pipe-drain timing
465+ between click and the pager subprocess is outside click's control
466+ (#2899, #3470). Spying on ``MaybeStripAnsi.write`` records what click sent
467+ to the pager, which is deterministic regardless of scheduling.
468+ """
469+ monkeypatch .setitem (os .environ , "PAGER" , "cat" )
470+ monkeypatch .setattr (click ._termui_impl , "isatty" , lambda x : True )
471+
472+ writes : list [str ] = []
473+ real_write = click ._termui_impl .MaybeStripAnsi .write
474+
475+ def spy (self , text ):
476+ writes .append (text )
477+ return real_write (self , text )
478+
479+ monkeypatch .setattr (click ._termui_impl .MaybeStripAnsi , "write" , spy )
480+
481+ pager_out_tmp = tmp_path / "pager_out.txt"
482+ with (
483+ pager_out_tmp .open ("w" ) as f ,
484+ patch .object (subprocess , "Popen" , partial (subprocess .Popen , stdout = f )),
485+ pytest .raises (RuntimeError , match = "This is a test." ),
486+ ):
487+ click .echo_via_pager (_test_gen_func_yields_then_fails ())
488+
489+ assert "" .join (writes ) == "test" , (
490+ f"click should have written the yielded chunk before exception, got { writes !r} "
491+ )
492+
493+
454494@pytest .mark .stress
455495@pytest .mark .skipif (WIN , reason = "Different behavior on windows." )
456496@pytest .mark .parametrize ("_" , range (1000 ))
0 commit comments