1313from queue import Empty , Queue
1414from threading import Thread
1515from types import TracebackType
16- from typing import TYPE_CHECKING , Generator , Optional , Sequence , Type , Union
16+ from typing import TYPE_CHECKING , Generator , List , Optional , Sequence , Type , Union
1717
1818import pytest
1919
@@ -113,10 +113,13 @@ def main(
113113 # pylint: disable=redefined-builtin
114114 input : Optional [bytes ] = None ,
115115 check : bool = True ,
116+ capture_output : bool = False ,
116117) -> "subprocess.CompletedProcess[bytes]" :
117118 cmd = [sys .executable , "-m" , "gitrevise" , * args ]
118- print ("Running" , cmd , dict (cwd = cwd , input = input , check = check ))
119- return subprocess .run (cmd , cwd = cwd , input = input , check = check )
119+ print (f"Running { cmd } {{{ cwd = } , { input = } , { check = } , { capture_output = } }}" )
120+ return subprocess .run (
121+ cmd , cwd = cwd , input = input , check = check , capture_output = capture_output
122+ )
120123
121124
122125@contextmanager
@@ -125,9 +128,11 @@ def editor_main(
125128 cwd : Optional ["StrPath" ] = None ,
126129 # pylint: disable=redefined-builtin
127130 input : Optional [bytes ] = None ,
131+ stdout_stderr_out : Optional [List [bytes ]] = None ,
128132) -> "Generator[Editor, None, subprocess.CompletedProcess[bytes]]" :
129133 with pytest .MonkeyPatch ().context () as monkeypatch , Editor () as ed , ThreadPoolExecutor () as tpe :
130134 host , port = ed .server_address
135+ assert isinstance (host , str ) # Satisfy mypy
131136 editor_cmd = " " .join (
132137 shlex .quote (p )
133138 for p in (
@@ -138,8 +143,12 @@ def editor_main(
138143 )
139144 monkeypatch .setenv ("GIT_EDITOR" , editor_cmd )
140145
146+ capture_output = stdout_stderr_out is not None
147+
141148 # Run the command asynchronously.
142- future = tpe .submit (main , args , cwd = cwd , input = input )
149+ future = tpe .submit (
150+ main , args , cwd = cwd , input = input , capture_output = capture_output
151+ )
143152
144153 # If it fails, cancel anything waiting on `ed.next_file()`.
145154 def cancel_on_error (future : "Future[Any]" ) -> None :
@@ -152,7 +161,12 @@ def cancel_on_error(future: "Future[Any]") -> None:
152161 # Yield the editor, so that tests can process incoming requests via `ed.next_file()`.
153162 yield ed
154163
155- return future .result ()
164+ result = future .result ()
165+ if stdout_stderr_out is not None :
166+ # Mutate instead of reassigning the out-argument object
167+ # to make the change observable to the caller.
168+ stdout_stderr_out += [result .stdout , result .stderr ]
169+ return result
156170
157171
158172class EditorFile :
@@ -189,7 +203,9 @@ class EditorFileRequestHandler(BaseHTTPRequestHandler):
189203
190204 # pylint: disable=invalid-name
191205 def do_POST (self ) -> None :
192- length = int (self .headers .get ("content-length" ))
206+ content_length = self .headers .get ("content-length" )
207+ assert isinstance (content_length , str ) # Satisfy mypy
208+ length = int (content_length )
193209 in_data = self .rfile .read (length )
194210
195211 status , out_data = 500 , b"no traceback"
0 commit comments