1
1
from __future__ import annotations
2
2
3
3
import json
4
+ import shutil
4
5
from collections .abc import Generator
5
6
from datetime import datetime
6
7
from functools import cached_property
@@ -47,6 +48,7 @@ class LocalExperiment(BaseMode):
47
48
_parameter_file = Path ("parameter.json" )
48
49
_responses_file = Path ("responses.json" )
49
50
_metadata_file = Path ("metadata.json" )
51
+ _templates_file = Path ("templates.json" )
50
52
51
53
def __init__ (
52
54
self ,
@@ -86,6 +88,7 @@ def create(
86
88
observations : dict [str , pl .DataFrame ] | None = None ,
87
89
simulation_arguments : dict [Any , Any ] | None = None ,
88
90
name : str | None = None ,
91
+ templates : list [tuple [str , str ]] | None = None ,
89
92
) -> LocalExperiment :
90
93
"""
91
94
Create a new LocalExperiment and store its configuration data.
@@ -108,6 +111,8 @@ def create(
108
111
Simulation arguments for the experiment.
109
112
name : str, optional
110
113
Experiment name. Defaults to current date if None.
114
+ templates : list of tuple[str, str], optional
115
+ Run templates for the experiment. Defaults to None.
111
116
112
117
Returns
113
118
-------
@@ -130,6 +135,23 @@ def create(
130
135
json .dumps (parameter_data , indent = 2 ).encode ("utf-8" ),
131
136
)
132
137
138
+ if templates :
139
+ templates_path = path / "templates"
140
+ templates_path .mkdir (parents = True , exist_ok = True )
141
+ templates_abs : list [tuple [str , str ]] = []
142
+ for idx , (src , dst ) in enumerate (templates ):
143
+ incoming_template = Path (src )
144
+ template_file_path = (
145
+ templates_path
146
+ / f"{ incoming_template .stem } _{ idx } { incoming_template .suffix } "
147
+ )
148
+ shutil .copyfile (incoming_template , template_file_path )
149
+ templates_abs .append ((str (template_file_path .relative_to (path )), dst ))
150
+ storage ._write_transaction (
151
+ path / cls ._templates_file ,
152
+ json .dumps (templates_abs ).encode ("utf-8" ),
153
+ )
154
+
133
155
response_data = {}
134
156
for response in responses or []:
135
157
response_data .update ({response .response_type : response .to_dict ()})
@@ -248,6 +270,27 @@ def parameter_info(self) -> dict[str, Any]:
248
270
info = json .load (f )
249
271
return info
250
272
273
+ @property
274
+ def templates_configuration (self ) -> list [tuple [str , str ]]:
275
+ try :
276
+ templates : list [tuple [str , str ]] = []
277
+ with open (self .mount_point / self ._templates_file , encoding = "utf-8" ) as f :
278
+ templates = json .load (f )
279
+ templates_with_content : list [tuple [str , str ]] = []
280
+ for source_file , target_file in templates :
281
+ try :
282
+ file_content = (self .mount_point / source_file ).read_text ("utf-8" )
283
+ templates_with_content .append ((file_content , target_file ))
284
+ except UnicodeDecodeError as e :
285
+ raise ValueError (
286
+ f"Unsupported non UTF-8 character found in file: { source_file } "
287
+ ) from e
288
+ return templates_with_content
289
+ except (FileNotFoundError , json .JSONDecodeError ):
290
+ pass
291
+ # If the file is missing or broken, we return an empty list
292
+ return []
293
+
251
294
@property
252
295
def response_info (self ) -> dict [str , Any ]:
253
296
info : dict [str , Any ]
0 commit comments