3232)
3333
3434
35- def read_stream (stream : modal .io_streams .StreamReader ) -> str :
36- """Read stream"""
37- strings = []
38- for line in stream :
39- strings .append (line )
40- return "\n " .join (strings )
41-
42-
4335class ExecutionBackend (StrEnum ):
4436 LOCAL = auto ()
4537 MODAL = auto ()
@@ -54,6 +46,7 @@ def __init__(
5446 num_cpus : int ,
5547 log_dir : Path ,
5648 files_to_copy : Optional [Files ] = None ,
49+ files_to_collect : Optional [Files ] = None ,
5750 ):
5851 """Create the remote execution context
5952
@@ -65,25 +58,13 @@ def __init__(
6558 self .timeout = timeout
6659 self .num_cpus = num_cpus
6760 self .log_dir = log_dir
61+ self .files_to_collect = files_to_collect
6862
6963 @abstractmethod
7064 def exec_run_with_timeout (self , command : str ) -> tuple [str , bool , float ]:
7165 """Execute a test command"""
7266 raise NotImplementedError
7367
74- def write_test_output (self , test_output : str , timed_out : bool ) -> None :
75- """Write test output"""
76- test_output_path = self .log_dir / "test_output.txt"
77- with open (test_output_path , "w" ) as f :
78- f .write (test_output )
79- if timed_out :
80- f .write (f"\n \n Timeout error: { self .timeout } seconds exceeded." )
81- raise EvaluationError (
82- self .spec .repo ,
83- f"Test timed out after { self .timeout } seconds." ,
84- self .logger ,
85- )
86-
8768 def __enter__ (self ):
8869 return self
8970
@@ -106,8 +87,9 @@ def __init__(
10687 num_cpus : int ,
10788 log_dir : Path ,
10889 files_to_copy : Optional [Files ] = None ,
90+ files_to_collect : Optional [Files ] = None ,
10991 ):
110- super ().__init__ (spec , logger , timeout , num_cpus , log_dir )
92+ super ().__init__ (spec , logger , timeout , num_cpus , log_dir , files_to_copy = files_to_copy , files_to_collect = files_to_collect )
11193
11294 self .client = docker .from_env ()
11395 self .container = create_container (
@@ -126,17 +108,18 @@ def exec_run_with_timeout(self, command: str) -> tuple[str, bool, float]:
126108 """Exec"""
127109 output = exec_run_with_timeout (self .container , command , self .timeout )
128110
129- # copy back report.json if there is any
130- report_file = Path (self .spec .repo_directory ) / "report.json"
131- # Run the test command inside the container to check if the file exists
132- exit_code , test_output = self .container .exec_run (
133- f"test -e { report_file } " , demux = True
134- )
135- # Check the exit code of the command
136- if exit_code == 0 :
137- copy_from_container (
138- self .container , report_file , self .log_dir / "report.json"
111+ for fname in self .files_to_collect :
112+ # copy back report.json if there is any
113+ file = Path (self .spec .repo_directory ) / fname
114+ # Run the test command inside the container to check if the file exists
115+ exit_code , test_output = self .container .exec_run (
116+ f"test -e { file } " , demux = True
139117 )
118+ # Check the exit code of the command
119+ if exit_code == 0 :
120+ copy_from_container (
121+ self .container , file , self .log_dir / fname
122+ )
140123 return output
141124
142125 def __exit__ (
@@ -158,8 +141,9 @@ def __init__(
158141 num_cpus : int ,
159142 log_dir : Path ,
160143 files_to_copy : Optional [Files ] = None ,
144+ files_to_collect : Optional [Files ] = None ,
161145 ):
162- super ().__init__ (spec , logger , timeout , num_cpus , log_dir )
146+ super ().__init__ (spec , logger , timeout , num_cpus , log_dir , files_to_copy = files_to_copy , files_to_collect = files_to_collect )
163147
164148 self .app = modal .App ()
165149
@@ -176,13 +160,17 @@ def exec_run_with_timeout(self, command: str) -> tuple[str, bool, float]:
176160 """Execute command on modal sandbox"""
177161 start_time = time .time ()
178162 with modal .Volume .ephemeral () as vol :
179- # copy back report.json if there is any
180- report_file = Path (self .spec .repo_directory ) / "report.json"
163+ cp_cmd = ""
164+ for fname in self .files_to_collect :
165+ remote_file = Path (self .spec .repo_directory ) / fname
166+ curr_cp_cmd = f" && cp { str (remote_file )} /vol/{ fname } 2>/dev/null"
167+ cp_cmd += curr_cp_cmd
181168
169+ command += cp_cmd
182170 self .sandbox = modal .Sandbox .create (
183171 "bash" ,
184172 "-c" ,
185- f" { command } && cp { str ( report_file ) } /vol/report.json" ,
173+ command ,
186174 image = self .image ,
187175 cpu = self .num_cpus ,
188176 timeout = self .timeout ,
@@ -191,26 +179,21 @@ def exec_run_with_timeout(self, command: str) -> tuple[str, bool, float]:
191179 )
192180 self .sandbox .wait ()
193181
194- # stdout has been redirected to stderr
195- stdout = read_stream (self .sandbox .stderr )
196-
197182 return_code = self .sandbox .returncode
198183 # https://github.com/modal-labs/modal-client/blob/d577b2916b5c3bf4ebbcb58fadced84d85e1cf8c/modal/sandbox.py#L413
199184 if return_code == 124 :
200185 timed_out = True
201186 else :
202187 timed_out = False
203188
204- # copy over report.json from mount
205- with (self .log_dir / "report.json" ).open ("wb" ) as f :
206- for data in vol .read_file ("report.json" ):
207- f .write (data )
189+ for fname in self . files_to_collect :
190+ with (self .log_dir / fname ).open ("wb" ) as f :
191+ for data in vol .read_file (fname ):
192+ f .write (data )
208193
209194 self .sandbox .terminate ()
210-
211195 end_time = time .time ()
212-
213- return stdout , timed_out , end_time - start_time
196+ return self .sandbox .stderr .read (), timed_out , end_time - start_time
214197
215198 def __exit__ (
216199 self ,
0 commit comments