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,17 @@ 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 (
120+ "Running" ,
121+ cmd ,
122+ dict (cwd = cwd , input = input , check = check , capture_output = capture_output ),
123+ )
124+ return subprocess .run (
125+ cmd , cwd = cwd , input = input , check = check , capture_output = capture_output
126+ )
120127
121128
122129@contextmanager
@@ -125,9 +132,11 @@ def editor_main(
125132 cwd : Optional ["StrPath" ] = None ,
126133 # pylint: disable=redefined-builtin
127134 input : Optional [bytes ] = None ,
135+ stdout_stderr_out : Optional [List [bytes ]] = None ,
128136) -> "Generator[Editor, None, subprocess.CompletedProcess[bytes]]" :
129137 with pytest .MonkeyPatch ().context () as monkeypatch , Editor () as ed , ThreadPoolExecutor () as tpe :
130138 host , port = ed .server_address
139+ assert isinstance (host , str ) # Satisfy mypy
131140 editor_cmd = " " .join (
132141 shlex .quote (p )
133142 for p in (
@@ -138,8 +147,12 @@ def editor_main(
138147 )
139148 monkeypatch .setenv ("GIT_EDITOR" , editor_cmd )
140149
150+ capture_output = stdout_stderr_out is not None
151+
141152 # Run the command asynchronously.
142- future = tpe .submit (main , args , cwd = cwd , input = input )
153+ future = tpe .submit (
154+ main , args , cwd = cwd , input = input , capture_output = capture_output
155+ )
143156
144157 # If it fails, cancel anything waiting on `ed.next_file()`.
145158 def cancel_on_error (future : "Future[Any]" ) -> None :
@@ -152,7 +165,12 @@ def cancel_on_error(future: "Future[Any]") -> None:
152165 # Yield the editor, so that tests can process incoming requests via `ed.next_file()`.
153166 yield ed
154167
155- return future .result ()
168+ result = future .result ()
169+ if stdout_stderr_out is not None :
170+ # Mutate instead of reassigning the out-argument object
171+ # to make the change observable to the caller.
172+ stdout_stderr_out += [result .stdout , result .stderr ]
173+ return result
156174
157175
158176class EditorFile :
@@ -189,7 +207,9 @@ class EditorFileRequestHandler(BaseHTTPRequestHandler):
189207
190208 # pylint: disable=invalid-name
191209 def do_POST (self ) -> None :
192- length = int (self .headers .get ("content-length" ))
210+ content_length = self .headers .get ("content-length" )
211+ assert isinstance (content_length , str ) # Satisfy mypy
212+ length = int (content_length )
193213 in_data = self .rfile .read (length )
194214
195215 status , out_data = 500 , b"no traceback"
0 commit comments