idmtools-platform-general 0.0.0.dev0__py3-none-any.whl → 0.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- idmtools_platform_file/__init__.py +18 -0
- idmtools_platform_file/assets/__init__.py +77 -0
- idmtools_platform_file/assets/_run.sh.jinja2 +47 -0
- idmtools_platform_file/assets/batch.sh.jinja2 +24 -0
- idmtools_platform_file/assets/run_simulation.sh +8 -0
- idmtools_platform_file/cli/__init__.py +5 -0
- idmtools_platform_file/cli/file.py +185 -0
- idmtools_platform_file/file_operations/__init__.py +4 -0
- idmtools_platform_file/file_operations/file_operations.py +298 -0
- idmtools_platform_file/file_operations/operations_interface.py +74 -0
- idmtools_platform_file/file_platform.py +288 -0
- idmtools_platform_file/platform_operations/__init__.py +5 -0
- idmtools_platform_file/platform_operations/asset_collection_operations.py +172 -0
- idmtools_platform_file/platform_operations/experiment_operations.py +314 -0
- idmtools_platform_file/platform_operations/json_metadata_operations.py +320 -0
- idmtools_platform_file/platform_operations/simulation_operations.py +212 -0
- idmtools_platform_file/platform_operations/suite_operations.py +243 -0
- idmtools_platform_file/platform_operations/utils.py +461 -0
- idmtools_platform_file/plugin_info.py +82 -0
- idmtools_platform_file/tools/__init__.py +4 -0
- idmtools_platform_file/tools/job_history.py +334 -0
- idmtools_platform_file/tools/status_report/__init__.py +4 -0
- idmtools_platform_file/tools/status_report/status_report.py +222 -0
- idmtools_platform_file/tools/status_report/utils.py +159 -0
- idmtools_platform_general-0.0.3.dist-info/METADATA +81 -0
- idmtools_platform_general-0.0.3.dist-info/RECORD +35 -0
- idmtools_platform_general-0.0.3.dist-info/entry_points.txt +6 -0
- idmtools_platform_general-0.0.3.dist-info/licenses/LICENSE.TXT +3 -0
- idmtools_platform_general-0.0.3.dist-info/top_level.txt +2 -0
- idmtools_platform_process/__init__.py +17 -0
- idmtools_platform_process/platform_operations/__init__.py +5 -0
- idmtools_platform_process/platform_operations/experiment_operations.py +53 -0
- idmtools_platform_process/plugin_info.py +80 -0
- idmtools_platform_process/process_platform.py +52 -0
- idmtools_platform_general/__init__.py +0 -8
- idmtools_platform_general-0.0.0.dev0.dist-info/METADATA +0 -41
- idmtools_platform_general-0.0.0.dev0.dist-info/RECORD +0 -5
- idmtools_platform_general-0.0.0.dev0.dist-info/top_level.txt +0 -1
- {idmtools_platform_general-0.0.0.dev0.dist-info → idmtools_platform_general-0.0.3.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is FilePlatform operations utils.
|
|
3
|
+
|
|
4
|
+
Copyright 2025, Gates Foundation. All rights reserved.
|
|
5
|
+
"""
|
|
6
|
+
import os
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from logging import getLogger
|
|
9
|
+
from typing import Dict, Union, List, Optional
|
|
10
|
+
from idmtools.core.interfaces.ientity import IEntity
|
|
11
|
+
from idmtools.entities import Suite
|
|
12
|
+
from idmtools.core import EntityStatus, ItemType
|
|
13
|
+
from idmtools.entities.experiment import Experiment
|
|
14
|
+
from idmtools.entities.simulation import Simulation
|
|
15
|
+
|
|
16
|
+
logger = getLogger(__name__)
|
|
17
|
+
user_logger = getLogger("user")
|
|
18
|
+
|
|
19
|
+
FILE_MAPS = {
|
|
20
|
+
"0": EntityStatus.SUCCEEDED,
|
|
21
|
+
"-1": EntityStatus.FAILED,
|
|
22
|
+
"100": EntityStatus.RUNNING,
|
|
23
|
+
"None": EntityStatus.CREATED
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class FileItem:
|
|
28
|
+
"""
|
|
29
|
+
Represent File Object.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
_metas: Dict
|
|
33
|
+
_platform_directory: Path
|
|
34
|
+
|
|
35
|
+
def __init__(self, metas: Dict):
|
|
36
|
+
"""
|
|
37
|
+
Constructor.
|
|
38
|
+
Args:
|
|
39
|
+
metas: metadata
|
|
40
|
+
"""
|
|
41
|
+
self._metas = metas
|
|
42
|
+
self._platform_directory = Path(metas["dir"])
|
|
43
|
+
|
|
44
|
+
def get_platform_object(self):
|
|
45
|
+
"""
|
|
46
|
+
Get platform.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Platform
|
|
50
|
+
"""
|
|
51
|
+
return self
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class FileSuite(FileItem, Suite):
|
|
55
|
+
"""
|
|
56
|
+
Represents a Suite loaded from a file platform.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def __init__(self, metas: Dict):
|
|
60
|
+
"""
|
|
61
|
+
Initialize a FileSuite object from metadata.
|
|
62
|
+
|
|
63
|
+
This constructor extracts common suite metadata such as ID, name, status, experiments,
|
|
64
|
+
and tags from a given metadata dictionary.
|
|
65
|
+
Args:
|
|
66
|
+
metas (Dict): A dictionary containing suite metadata. Expected keys:
|
|
67
|
+
- 'id': Unique identifier for the suite.
|
|
68
|
+
- 'name': Name of the suite.
|
|
69
|
+
- 'status': Execution status.
|
|
70
|
+
- 'experiments': List of experiment IDs or IEntity instances.
|
|
71
|
+
- 'tags': Dictionary of metadata tags.
|
|
72
|
+
"""
|
|
73
|
+
FileItem.__init__(self, metas)
|
|
74
|
+
self.uid = metas['id']
|
|
75
|
+
self.name = metas['name']
|
|
76
|
+
self.status = metas['status']
|
|
77
|
+
self.__experiments: Optional[List[str, IEntity]] = metas['experiments']
|
|
78
|
+
self.tags = metas['tags']
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def experiments(self) -> List:
|
|
82
|
+
"""
|
|
83
|
+
Retrieve the list of experiments associated with this suite.
|
|
84
|
+
Returns:
|
|
85
|
+
List: A list of resolved `Experiment` objects.
|
|
86
|
+
"""
|
|
87
|
+
return self.get_experiments()
|
|
88
|
+
|
|
89
|
+
def get_experiments(self) -> List:
|
|
90
|
+
"""
|
|
91
|
+
Resolve and return the list of experiments.
|
|
92
|
+
|
|
93
|
+
For any unresolved entries (e.g., experiment IDs), this method uses
|
|
94
|
+
the current platform to retrieve the full `Experiment` object. Already
|
|
95
|
+
resolved `Experiment` instances are returned as-is.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
List: A list of `Experiment` objects resolved from the internal metadata.
|
|
99
|
+
"""
|
|
100
|
+
platform = self.get_current_platform_or_error()
|
|
101
|
+
exp_list = []
|
|
102
|
+
for exp in self.__experiments:
|
|
103
|
+
if isinstance(exp, Experiment):
|
|
104
|
+
exp_list.append(exp)
|
|
105
|
+
else:
|
|
106
|
+
exp_list.append(platform.get_item(exp, item_type=ItemType.EXPERIMENT, force=True, raw=True))
|
|
107
|
+
self.__experiments = exp_list
|
|
108
|
+
return exp_list
|
|
109
|
+
|
|
110
|
+
@experiments.setter
|
|
111
|
+
def experiments(self, experiments: List):
|
|
112
|
+
"""
|
|
113
|
+
Set the list of experiments for this suite.
|
|
114
|
+
|
|
115
|
+
Accepts either resolved `Experiment` objects or a mix of IDs and objects.
|
|
116
|
+
The list will be resolved to full objects upon next access(get_experiments()).
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
experiments (List): A list of experiment IDs or `Experiment` instances.
|
|
120
|
+
"""
|
|
121
|
+
self.__experiments = experiments
|
|
122
|
+
|
|
123
|
+
def __repr__(self):
|
|
124
|
+
"""
|
|
125
|
+
String representation of suite.
|
|
126
|
+
"""
|
|
127
|
+
return f"<{self.__class__.__name__} {self.uid} - {len(self.experiments)} experiments>"
|
|
128
|
+
|
|
129
|
+
def add_experiment(self, experiment: 'Experiment') -> 'NoReturn': # noqa: F821
|
|
130
|
+
"""
|
|
131
|
+
Add an experiment to the suite.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
experiment: the experiment to be linked to suite
|
|
135
|
+
"""
|
|
136
|
+
self.__experiments.append(experiment)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class FileExperiment(FileItem, Experiment):
|
|
140
|
+
"""
|
|
141
|
+
Represents an Experiment loaded from a file platform.
|
|
142
|
+
|
|
143
|
+
This subclass of `Experiment` maps metadata into a lightweight experiment representation,
|
|
144
|
+
where simulations may initially be stored as either IDs or resolved `Simulation` objects.
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
def __init__(self, metas: Dict):
|
|
148
|
+
"""
|
|
149
|
+
Initialize a FileExperiment from a metadata dictionary.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
metas (Dict): Metadata dictionary containing keys:
|
|
153
|
+
- 'id': Unique identifier for the experiment.
|
|
154
|
+
- 'name': Experiment name.
|
|
155
|
+
- 'status': Status of the experiment (raw value).
|
|
156
|
+
- 'suite_id': ID of the parent suite.
|
|
157
|
+
- 'simulations': List of simulation IDs or `Simulation` objects.
|
|
158
|
+
- 'tags': Dictionary of experiment tags.
|
|
159
|
+
- 'assets': Asset collection or related metadata.
|
|
160
|
+
"""
|
|
161
|
+
FileItem.__init__(self, metas)
|
|
162
|
+
self.suite_id = self.parent_id = metas['suite_id']
|
|
163
|
+
self.__simulations: Optional[List[str, IEntity]] = metas['simulations']
|
|
164
|
+
self.uid = metas['id']
|
|
165
|
+
self.name = metas['name']
|
|
166
|
+
self._status = metas['status']
|
|
167
|
+
self.tags = metas['tags']
|
|
168
|
+
self.assets = metas['assets']
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def simulations(self) -> List:
|
|
172
|
+
"""
|
|
173
|
+
Access the list of simulations associated with the experiment.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
List: A list containing either simulation IDs or resolved `Simulation` objects.
|
|
177
|
+
"""
|
|
178
|
+
return self.get_simulations()
|
|
179
|
+
|
|
180
|
+
def get_simulations(self) -> List:
|
|
181
|
+
"""
|
|
182
|
+
Resolve and return full `Simulation` objects from their IDs.
|
|
183
|
+
|
|
184
|
+
This method uses file platform to retrieve any simulations
|
|
185
|
+
that are not yet resolved, and replaces unresolved IDs in-place.
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
List: Fully resolved list of `Simulation` objects.
|
|
189
|
+
"""
|
|
190
|
+
platform = self.get_current_platform_or_error()
|
|
191
|
+
sim_list = []
|
|
192
|
+
for sim in self.__simulations:
|
|
193
|
+
if isinstance(sim, Simulation):
|
|
194
|
+
sim_list.append(sim)
|
|
195
|
+
else:
|
|
196
|
+
sim_list.append(platform.get_item(sim, item_type=ItemType.SIMULATION, force=True, raw=True))
|
|
197
|
+
self.__simulations = sim_list
|
|
198
|
+
return sim_list
|
|
199
|
+
|
|
200
|
+
@simulations.setter
|
|
201
|
+
def simulations(self, simulations: List):
|
|
202
|
+
"""
|
|
203
|
+
Set the simulations list directly.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
simulations (List): A list of simulation IDs or `Simulation` instances.
|
|
207
|
+
"""
|
|
208
|
+
self.__simulations = simulations
|
|
209
|
+
|
|
210
|
+
def add_simulation(self, simulation: 'Simulation') -> 'NoReturn': # noqa: F821
|
|
211
|
+
"""
|
|
212
|
+
Add a single simulation to the experiment.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
simulation (Simulation): The simulation to add.
|
|
216
|
+
"""
|
|
217
|
+
# Check possible duplicate
|
|
218
|
+
ids = [sim.id if isinstance(sim, Simulation) else sim for sim in self.__simulations]
|
|
219
|
+
if simulation.id in ids:
|
|
220
|
+
return
|
|
221
|
+
|
|
222
|
+
# Set parent
|
|
223
|
+
simulation.parent = self
|
|
224
|
+
|
|
225
|
+
self.__simulations.append(simulation)
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def status(self):
|
|
229
|
+
"""
|
|
230
|
+
Get status.
|
|
231
|
+
Returns:
|
|
232
|
+
Status
|
|
233
|
+
"""
|
|
234
|
+
return self._status
|
|
235
|
+
|
|
236
|
+
@status.setter
|
|
237
|
+
def status(self, status):
|
|
238
|
+
"""
|
|
239
|
+
Set Status.
|
|
240
|
+
Args:
|
|
241
|
+
status: status
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
None
|
|
245
|
+
"""
|
|
246
|
+
self._status = status
|
|
247
|
+
|
|
248
|
+
def __repr__(self):
|
|
249
|
+
"""
|
|
250
|
+
String representation of experiment.
|
|
251
|
+
"""
|
|
252
|
+
return f"<{self.__class__.__name__} {self.uid} - {len(self.simulations)} simulations>"
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class FileSimulation(FileItem, Simulation):
|
|
256
|
+
"""
|
|
257
|
+
Represents a simulation loaded from file metadata.
|
|
258
|
+
|
|
259
|
+
This class is a lightweight wrapper around the standard `Simulation` object,
|
|
260
|
+
used by the FilePlatform. It initializes the simulation using values from
|
|
261
|
+
a metadata dictionary, typically derived from file contents.
|
|
262
|
+
|
|
263
|
+
Attributes:
|
|
264
|
+
uid (str): uid of simulation.
|
|
265
|
+
parent_id (str): ID of the parent experiment.
|
|
266
|
+
experiment_id (str): Alias of `parent_id` for clarity.
|
|
267
|
+
name (str): Name of the simulation.
|
|
268
|
+
status (EntityStatus or raw value): Execution status.
|
|
269
|
+
tags (Dict): Key-value metadata tags.
|
|
270
|
+
task (Any): Task definition or reference (platform-dependent).
|
|
271
|
+
assets (Any): Asset metadata or collection.
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
def __init__(self, metas: Dict):
|
|
275
|
+
"""
|
|
276
|
+
Constructor.
|
|
277
|
+
Args:
|
|
278
|
+
metas: Metas dict
|
|
279
|
+
"""
|
|
280
|
+
FileItem.__init__(self, metas)
|
|
281
|
+
self.uid = metas['id']
|
|
282
|
+
self.parent_id = metas['parent_id']
|
|
283
|
+
self.experiment_id = metas['parent_id']
|
|
284
|
+
self.name = metas['name']
|
|
285
|
+
self.status = metas['status']
|
|
286
|
+
self.tags = metas['tags']
|
|
287
|
+
self.task = metas['task']
|
|
288
|
+
self.assets = metas['assets']
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def clean_item_name(experiment_name: str, maxlen: int = 30) -> str:
|
|
292
|
+
"""
|
|
293
|
+
Handle some special characters in experiment names.
|
|
294
|
+
Args:
|
|
295
|
+
experiment_name: name of the experiment
|
|
296
|
+
maxlen: max length of the experiment name
|
|
297
|
+
Returns:
|
|
298
|
+
the experiment name allowed for use
|
|
299
|
+
"""
|
|
300
|
+
import re
|
|
301
|
+
chars_to_replace = ['/', '\\', ':', "'", '"', '?', '<', '>', '*', '|', "\0", "(", ")", "[", "]", '`', ',', '!', '$',
|
|
302
|
+
'&', '"', ' ']
|
|
303
|
+
clean_names_expr = re.compile(f'[{re.escape("".join(chars_to_replace))}]')
|
|
304
|
+
|
|
305
|
+
experiment_name = clean_names_expr.sub("_", experiment_name)
|
|
306
|
+
s = experiment_name.encode("ascii", "ignore").decode('utf8').strip()
|
|
307
|
+
# Truncate to maxlen
|
|
308
|
+
return s[:maxlen]
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def add_dummy_suite(experiment: Experiment, suite_name: str = None, tags: Dict = None) -> Suite:
|
|
312
|
+
"""
|
|
313
|
+
Create Suite parent for given experiment.
|
|
314
|
+
Args:
|
|
315
|
+
experiment: idmtools Experiment
|
|
316
|
+
suite_name: new Suite name
|
|
317
|
+
tags: new Suite tags
|
|
318
|
+
Returns:
|
|
319
|
+
Suite
|
|
320
|
+
"""
|
|
321
|
+
if suite_name is None:
|
|
322
|
+
suite_name = 'Suite'
|
|
323
|
+
suite = Suite(name=suite_name)
|
|
324
|
+
|
|
325
|
+
if tags is not None:
|
|
326
|
+
suite.tags = tags
|
|
327
|
+
|
|
328
|
+
# add experiment
|
|
329
|
+
suite.add_experiment(experiment)
|
|
330
|
+
return suite
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def get_max_filepath(dir_path: Union[Path, str]) -> str:
|
|
334
|
+
"""
|
|
335
|
+
Get the maximum file path in a directory.
|
|
336
|
+
Args:
|
|
337
|
+
dir_path: directory path
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
maximum file relative path
|
|
341
|
+
"""
|
|
342
|
+
max_length = 0 # Variable to store the maximum filename length
|
|
343
|
+
max_file_path = None # Variable to store the maximum relative filepath
|
|
344
|
+
|
|
345
|
+
# Walk through all files and subdirectories recursively
|
|
346
|
+
dir_path = os.path.abspath(dir_path)
|
|
347
|
+
for root, dirs, files in os.walk(dir_path):
|
|
348
|
+
for file in files:
|
|
349
|
+
full_path = os.path.join(root, file)
|
|
350
|
+
file_path = full_path.replace(dir_path, '').lstrip('\\')
|
|
351
|
+
if max_file_path is None:
|
|
352
|
+
max_file_path = file_path
|
|
353
|
+
max_length = len(max_file_path)
|
|
354
|
+
else:
|
|
355
|
+
max_length_new = max(max_length, len(file_path))
|
|
356
|
+
if max_length_new > max_length:
|
|
357
|
+
max_file_path = file_path
|
|
358
|
+
max_length = len(max_file_path)
|
|
359
|
+
|
|
360
|
+
return max_file_path
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def validate_folder_files_path_length(common_asset_dir: Union[Path, str], link_dir: Union[Path, str],
|
|
364
|
+
limit: int = 256):
|
|
365
|
+
"""
|
|
366
|
+
Validate common asset path length.
|
|
367
|
+
Args:
|
|
368
|
+
common_asset_dir: common asset directory
|
|
369
|
+
link_dir: link directory
|
|
370
|
+
limit: path length limit
|
|
371
|
+
Returns:
|
|
372
|
+
None
|
|
373
|
+
"""
|
|
374
|
+
if not is_windows():
|
|
375
|
+
return
|
|
376
|
+
if is_long_paths_enabled():
|
|
377
|
+
return
|
|
378
|
+
asset_path = get_max_filepath(common_asset_dir)
|
|
379
|
+
if asset_path is None:
|
|
380
|
+
validate_file_path_length(link_dir, limit)
|
|
381
|
+
else:
|
|
382
|
+
sim_asset_path = os.path.join(str(link_dir), asset_path)
|
|
383
|
+
validate_file_path_length(sim_asset_path, limit)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def validate_file_copy_path_length(src: Union[Path, str], dest: Union[Path, str], limit: int = 256):
|
|
387
|
+
"""
|
|
388
|
+
Validate file copy path length.
|
|
389
|
+
Args:
|
|
390
|
+
src: source path
|
|
391
|
+
dest: destination path
|
|
392
|
+
limit: path length limit
|
|
393
|
+
Returns:
|
|
394
|
+
None
|
|
395
|
+
"""
|
|
396
|
+
if not is_windows():
|
|
397
|
+
return
|
|
398
|
+
if is_long_paths_enabled():
|
|
399
|
+
return
|
|
400
|
+
filename = Path(src).name
|
|
401
|
+
dest_file = Path(dest, filename)
|
|
402
|
+
validate_file_path_length(dest_file, limit)
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def validate_file_path_length(file_path: Union[Path, str], limit: int = 256):
|
|
406
|
+
"""
|
|
407
|
+
Validate file path length.
|
|
408
|
+
Args:
|
|
409
|
+
file_path: file path
|
|
410
|
+
limit: path length limit
|
|
411
|
+
Returns:
|
|
412
|
+
None
|
|
413
|
+
"""
|
|
414
|
+
if not is_windows():
|
|
415
|
+
return
|
|
416
|
+
if is_long_paths_enabled():
|
|
417
|
+
return
|
|
418
|
+
total_length = len(str(file_path))
|
|
419
|
+
if total_length > limit:
|
|
420
|
+
user_logger.warning(
|
|
421
|
+
f"\nFile path length too long: {total_length} > {limit}. Refer to file: '{file_path}'")
|
|
422
|
+
user_logger.warning(
|
|
423
|
+
"You may want to adjust your job_directory location, short Experiment name or Suite name to reduce the file path length. Or you can enable long paths in Windows, refer to https://www.autodesk.com/support/technical/article/caas/sfdcarticles/sfdcarticles/The-Windows-10-default-path-length-limitation-MAX-PATH-is-256-characters.html.")
|
|
424
|
+
# raise FileNotFoundError(f"File path length too long: {total_length} > {limit}. Refer to file: '{file_path}'")
|
|
425
|
+
exit(-1)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
def is_windows() -> bool:
|
|
429
|
+
"""
|
|
430
|
+
Check if the platform is Windows.
|
|
431
|
+
Returns:
|
|
432
|
+
True if Windows, False otherwise
|
|
433
|
+
"""
|
|
434
|
+
# return os.name == 'nt'
|
|
435
|
+
import platform
|
|
436
|
+
return platform.system() in ["Windows"]
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def is_long_paths_enabled() -> bool:
|
|
440
|
+
"""Check if long paths are enabled in Windows."""
|
|
441
|
+
import winreg
|
|
442
|
+
try:
|
|
443
|
+
# Open the registry key where LongPathsEnabled is stored
|
|
444
|
+
registry_key = winreg.OpenKey(
|
|
445
|
+
winreg.HKEY_LOCAL_MACHINE,
|
|
446
|
+
r"SYSTEM\CurrentControlSet\Control\FileSystem",
|
|
447
|
+
0,
|
|
448
|
+
winreg.KEY_READ
|
|
449
|
+
)
|
|
450
|
+
# Query the value of LongPathsEnabled
|
|
451
|
+
long_paths_enabled, _ = winreg.QueryValueEx(registry_key, "LongPathsEnabled")
|
|
452
|
+
winreg.CloseKey(registry_key)
|
|
453
|
+
|
|
454
|
+
# Return True if it's enabled (i.e., value is 1), otherwise False
|
|
455
|
+
return long_paths_enabled == 1
|
|
456
|
+
except FileNotFoundError:
|
|
457
|
+
# The registry key or value does not exist
|
|
458
|
+
return False
|
|
459
|
+
except Exception as e:
|
|
460
|
+
print(f"Error checking long paths: {e}")
|
|
461
|
+
return
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""
|
|
2
|
+
idmtools file platform plugin definition.
|
|
3
|
+
|
|
4
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
5
|
+
"""
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Type, Dict
|
|
8
|
+
from idmtools.entities.iplatform import IPlatform
|
|
9
|
+
from idmtools.registry.platform_specification import example_configuration_impl, get_platform_impl, \
|
|
10
|
+
get_platform_type_impl, PlatformSpecification
|
|
11
|
+
from idmtools.registry.plugin_specification import get_description_impl
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
FILE_EXAMPLE_CONFIG = """
|
|
15
|
+
[File]
|
|
16
|
+
job_directory = /data
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class FilePlatformSpecification(PlatformSpecification):
|
|
21
|
+
"""
|
|
22
|
+
File Platform Specification definition.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
@get_description_impl
|
|
26
|
+
def get_description(self) -> str:
|
|
27
|
+
"""
|
|
28
|
+
Retrieve description.
|
|
29
|
+
"""
|
|
30
|
+
return "Provides access to the Local Platform to IDM Tools"
|
|
31
|
+
|
|
32
|
+
@get_platform_impl
|
|
33
|
+
def get(self, **configuration) -> IPlatform:
|
|
34
|
+
"""
|
|
35
|
+
Build our file platform from the passed in configuration object.
|
|
36
|
+
|
|
37
|
+
We do our import of platform here to avoid any weirdness
|
|
38
|
+
Args:
|
|
39
|
+
configuration:
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
IPlatform
|
|
43
|
+
"""
|
|
44
|
+
from idmtools_platform_file.file_platform import FilePlatform
|
|
45
|
+
return FilePlatform(**configuration)
|
|
46
|
+
|
|
47
|
+
@example_configuration_impl
|
|
48
|
+
def example_configuration(self):
|
|
49
|
+
"""
|
|
50
|
+
Retrieve example configuration.
|
|
51
|
+
"""
|
|
52
|
+
return FILE_EXAMPLE_CONFIG
|
|
53
|
+
|
|
54
|
+
@get_platform_type_impl
|
|
55
|
+
def get_type(self) -> Type['FilePlatform']: # noqa: F821
|
|
56
|
+
"""
|
|
57
|
+
Get type.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Type
|
|
61
|
+
"""
|
|
62
|
+
from idmtools_platform_file.file_platform import FilePlatform
|
|
63
|
+
return FilePlatform
|
|
64
|
+
|
|
65
|
+
def get_version(self) -> str:
|
|
66
|
+
"""
|
|
67
|
+
Returns the version of the plugin.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Plugin Version
|
|
71
|
+
"""
|
|
72
|
+
from idmtools_platform_file import __version__
|
|
73
|
+
return __version__
|
|
74
|
+
|
|
75
|
+
def get_configuration_aliases(self) -> Dict[str, Dict]:
|
|
76
|
+
"""Provides configuration aliases that exist in FILE."""
|
|
77
|
+
config_aliases = dict(
|
|
78
|
+
FILE=dict(
|
|
79
|
+
job_directory=str(Path.home())
|
|
80
|
+
)
|
|
81
|
+
)
|
|
82
|
+
return config_aliases
|