idmtools 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/__init__.py +27 -8
- idmtools/analysis/__init__.py +5 -0
- idmtools/analysis/add_analyzer.py +89 -0
- idmtools/analysis/analyze_manager.py +490 -0
- idmtools/analysis/csv_analyzer.py +103 -0
- idmtools/analysis/download_analyzer.py +96 -0
- idmtools/analysis/map_worker_entry.py +100 -0
- idmtools/analysis/platform_analysis_bootstrap.py +94 -0
- idmtools/analysis/platform_anaylsis.py +291 -0
- idmtools/analysis/tags_analyzer.py +93 -0
- idmtools/assets/__init__.py +9 -0
- idmtools/assets/asset.py +453 -0
- idmtools/assets/asset_collection.py +514 -0
- idmtools/assets/content_handlers.py +19 -0
- idmtools/assets/errors.py +23 -0
- idmtools/assets/file_list.py +191 -0
- idmtools/builders/__init__.py +11 -0
- idmtools/builders/arm_simulation_builder.py +152 -0
- idmtools/builders/csv_simulation_builder.py +76 -0
- idmtools/builders/simulation_builder.py +348 -0
- idmtools/builders/sweep_arm.py +109 -0
- idmtools/builders/yaml_simulation_builder.py +82 -0
- idmtools/config/__init__.py +7 -0
- idmtools/config/idm_config_parser.py +486 -0
- idmtools/core/__init__.py +10 -0
- idmtools/core/cache_enabled.py +114 -0
- idmtools/core/context.py +68 -0
- idmtools/core/docker_task.py +207 -0
- idmtools/core/enums.py +51 -0
- idmtools/core/exceptions.py +91 -0
- idmtools/core/experiment_factory.py +71 -0
- idmtools/core/id_file.py +70 -0
- idmtools/core/interfaces/__init__.py +5 -0
- idmtools/core/interfaces/entity_container.py +64 -0
- idmtools/core/interfaces/iassets_enabled.py +58 -0
- idmtools/core/interfaces/ientity.py +331 -0
- idmtools/core/interfaces/iitem.py +206 -0
- idmtools/core/interfaces/imetadata_operations.py +89 -0
- idmtools/core/interfaces/inamed_entity.py +17 -0
- idmtools/core/interfaces/irunnable_entity.py +159 -0
- idmtools/core/logging.py +387 -0
- idmtools/core/platform_factory.py +316 -0
- idmtools/core/system_information.py +104 -0
- idmtools/core/task_factory.py +145 -0
- idmtools/entities/__init__.py +10 -0
- idmtools/entities/command_line.py +229 -0
- idmtools/entities/command_task.py +155 -0
- idmtools/entities/experiment.py +787 -0
- idmtools/entities/generic_workitem.py +43 -0
- idmtools/entities/ianalyzer.py +163 -0
- idmtools/entities/iplatform.py +1106 -0
- idmtools/entities/iplatform_default.py +39 -0
- idmtools/entities/iplatform_ops/__init__.py +5 -0
- idmtools/entities/iplatform_ops/iplatform_asset_collection_operations.py +148 -0
- idmtools/entities/iplatform_ops/iplatform_experiment_operations.py +415 -0
- idmtools/entities/iplatform_ops/iplatform_simulation_operations.py +315 -0
- idmtools/entities/iplatform_ops/iplatform_suite_operations.py +322 -0
- idmtools/entities/iplatform_ops/iplatform_workflowitem_operations.py +301 -0
- idmtools/entities/iplatform_ops/utils.py +185 -0
- idmtools/entities/itask.py +316 -0
- idmtools/entities/iworkflow_item.py +167 -0
- idmtools/entities/platform_requirements.py +20 -0
- idmtools/entities/relation_type.py +14 -0
- idmtools/entities/simulation.py +255 -0
- idmtools/entities/suite.py +188 -0
- idmtools/entities/task_proxy.py +37 -0
- idmtools/entities/templated_simulation.py +325 -0
- idmtools/frozen/frozen_dict.py +71 -0
- idmtools/frozen/frozen_list.py +66 -0
- idmtools/frozen/frozen_set.py +86 -0
- idmtools/frozen/frozen_tuple.py +18 -0
- idmtools/frozen/frozen_utils.py +179 -0
- idmtools/frozen/ifrozen.py +66 -0
- idmtools/plugins/__init__.py +5 -0
- idmtools/plugins/git_commit.py +117 -0
- idmtools/registry/__init__.py +4 -0
- idmtools/registry/experiment_specification.py +105 -0
- idmtools/registry/functions.py +28 -0
- idmtools/registry/hook_specs.py +132 -0
- idmtools/registry/master_plugin_registry.py +51 -0
- idmtools/registry/platform_specification.py +138 -0
- idmtools/registry/plugin_specification.py +129 -0
- idmtools/registry/task_specification.py +104 -0
- idmtools/registry/utils.py +119 -0
- idmtools/services/__init__.py +5 -0
- idmtools/services/ipersistance_service.py +135 -0
- idmtools/services/platforms.py +13 -0
- idmtools/utils/__init__.py +5 -0
- idmtools/utils/caller.py +24 -0
- idmtools/utils/collections.py +246 -0
- idmtools/utils/command_line.py +45 -0
- idmtools/utils/decorators.py +300 -0
- idmtools/utils/display/__init__.py +22 -0
- idmtools/utils/display/displays.py +181 -0
- idmtools/utils/display/settings.py +25 -0
- idmtools/utils/dropbox_location.py +30 -0
- idmtools/utils/entities.py +127 -0
- idmtools/utils/file.py +72 -0
- idmtools/utils/file_parser.py +151 -0
- idmtools/utils/filter_simulations.py +182 -0
- idmtools/utils/filters/__init__.py +5 -0
- idmtools/utils/filters/asset_filters.py +88 -0
- idmtools/utils/general.py +286 -0
- idmtools/utils/gitrepo.py +336 -0
- idmtools/utils/hashing.py +239 -0
- idmtools/utils/info.py +124 -0
- idmtools/utils/json.py +82 -0
- idmtools/utils/language.py +107 -0
- idmtools/utils/local_os.py +40 -0
- idmtools/utils/time.py +22 -0
- idmtools-0.0.3.dist-info/METADATA +120 -0
- idmtools-0.0.3.dist-info/RECORD +116 -0
- idmtools-0.0.3.dist-info/entry_points.txt +9 -0
- idmtools-0.0.3.dist-info/licenses/LICENSE.TXT +3 -0
- idmtools-0.0.0.dev0.dist-info/METADATA +0 -41
- idmtools-0.0.0.dev0.dist-info/RECORD +0 -5
- {idmtools-0.0.0.dev0.dist-info → idmtools-0.0.3.dist-info}/WHEEL +0 -0
- {idmtools-0.0.0.dev0.dist-info → idmtools-0.0.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"""
|
|
2
|
+
IEntity definition. IEntity is the base of most of our Remote server entitiies like Experiment, Simulation, WorkItems, and Suites.
|
|
3
|
+
|
|
4
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
5
|
+
"""
|
|
6
|
+
from abc import ABCMeta
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from logging import getLogger
|
|
9
|
+
from os import PathLike
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import NoReturn, List, Any, Dict, Union, TYPE_CHECKING
|
|
12
|
+
from idmtools.core import EntityStatus, ItemType, NoPlatformException
|
|
13
|
+
from idmtools.core.interfaces.iitem import IItem
|
|
14
|
+
from idmtools.core.id_file import read_id_file, write_id_file
|
|
15
|
+
from idmtools.services.platforms import PlatformPersistService
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
18
|
+
from idmtools.entities.iplatform import IPlatform
|
|
19
|
+
|
|
20
|
+
logger = getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class IEntity(IItem, metaclass=ABCMeta):
|
|
25
|
+
"""
|
|
26
|
+
Interface for all entities in the system.
|
|
27
|
+
"""
|
|
28
|
+
#: ID of the platform
|
|
29
|
+
platform_id: str = field(default=None, compare=False, metadata={"md": True})
|
|
30
|
+
#: Platform
|
|
31
|
+
_platform: 'IPlatform' = field(default=None, compare=False, metadata={"pickle_ignore": False}) # noqa E821
|
|
32
|
+
#: Parent id
|
|
33
|
+
parent_id: str = field(default=None, metadata={"md": True})
|
|
34
|
+
#: Parent object
|
|
35
|
+
_parent: 'IEntity' = field(default=None, compare=False, metadata={"pickle_ignore": False})
|
|
36
|
+
#: Status of item
|
|
37
|
+
status: EntityStatus = field(default=None, compare=False, metadata={"pickle_ignore": False})
|
|
38
|
+
#: Tags for item
|
|
39
|
+
tags: Dict[str, Any] = field(default_factory=lambda: {}, metadata={"md": True})
|
|
40
|
+
#: Item Type(Experiment, Suite, Asset, etc)
|
|
41
|
+
item_type: ItemType = field(default=None, compare=False)
|
|
42
|
+
#: Platform Representation of Entity
|
|
43
|
+
_platform_object: Any = field(default=None, compare=False, metadata={"pickle_ignore": True})
|
|
44
|
+
|
|
45
|
+
def update_tags(self, tags: dict = None) -> NoReturn:
|
|
46
|
+
"""
|
|
47
|
+
Shortcut to update the tags with the given dictionary.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
tags: New tags
|
|
51
|
+
"""
|
|
52
|
+
self.tags.update(tags)
|
|
53
|
+
|
|
54
|
+
def post_creation(self, platform: 'IPlatform') -> None:
|
|
55
|
+
"""
|
|
56
|
+
Post creation hook for object.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
None
|
|
60
|
+
"""
|
|
61
|
+
self.status = EntityStatus.CREATED
|
|
62
|
+
super().post_creation(platform)
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def from_id_file(cls, filename: Union[PathLike, str], platform: 'IPlatform' = None,
|
|
66
|
+
**kwargs) -> 'IEntity': # noqa E821:
|
|
67
|
+
"""
|
|
68
|
+
Load from a file that container the id.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
filename: Filename to load
|
|
72
|
+
platform: Platform object to load id from. This can be loaded from file if saved there.
|
|
73
|
+
**kwargs: Platform extra arguments
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Entity loaded from id file
|
|
77
|
+
|
|
78
|
+
Raises:
|
|
79
|
+
EnvironmentError if item type is None.
|
|
80
|
+
"""
|
|
81
|
+
item_id, item_type_in_file, platform_block, extra_args = read_id_file(filename)
|
|
82
|
+
|
|
83
|
+
if platform is None:
|
|
84
|
+
if platform_block:
|
|
85
|
+
from idmtools.core.platform_factory import Platform
|
|
86
|
+
platform = Platform(platform_block, **kwargs)
|
|
87
|
+
else:
|
|
88
|
+
platform = cls.get_current_platform_or_error()
|
|
89
|
+
if cls.item_type is None:
|
|
90
|
+
raise EnvironmentError(
|
|
91
|
+
"ItemType is None. This is most likely a badly derived IEntity that doesn't run set the default item type on the class")
|
|
92
|
+
|
|
93
|
+
return platform.get_item(item_id, cls.item_type, **kwargs)
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def from_id(cls, item_id: str, platform: 'IPlatform' = None, **kwargs) -> 'IEntity': # noqa E821
|
|
97
|
+
"""
|
|
98
|
+
Load an item from an id.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
item_id: Id of item
|
|
102
|
+
platform: Platform. If not supplied, we check the current context
|
|
103
|
+
**kwargs: Optional platform args
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
IEntity of object
|
|
107
|
+
"""
|
|
108
|
+
if platform is None:
|
|
109
|
+
platform = cls.get_current_platform_or_error()
|
|
110
|
+
if cls.item_type is None:
|
|
111
|
+
raise EnvironmentError(
|
|
112
|
+
"ItemType is None. This is most likely a badly derived IEntity that doesn't run set the default item type on the class")
|
|
113
|
+
return platform.get_item(item_id, cls.item_type, **kwargs)
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def parent(self):
|
|
117
|
+
"""
|
|
118
|
+
Return parent object for item.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Parent entity if set
|
|
122
|
+
"""
|
|
123
|
+
if not self._parent:
|
|
124
|
+
if not self.parent_id:
|
|
125
|
+
return None
|
|
126
|
+
if not self.platform:
|
|
127
|
+
raise NoPlatformException("The object has no platform set...")
|
|
128
|
+
self._parent = self.platform.get_parent(self.uid, self.item_type)
|
|
129
|
+
|
|
130
|
+
return self._parent
|
|
131
|
+
|
|
132
|
+
@parent.setter
|
|
133
|
+
def parent(self, parent: 'IEntity'): # noqa E821
|
|
134
|
+
"""
|
|
135
|
+
Sets the parent object for item.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
parent: Parent object
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
None
|
|
142
|
+
"""
|
|
143
|
+
if parent:
|
|
144
|
+
self._parent = parent
|
|
145
|
+
self.parent_id = parent.uid
|
|
146
|
+
else:
|
|
147
|
+
self.parent_id = self._parent = None
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def platform(self) -> 'IPlatform': # noqa E821
|
|
151
|
+
"""
|
|
152
|
+
Get objects platform object.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Platform
|
|
156
|
+
"""
|
|
157
|
+
if not self._platform and self.platform_id:
|
|
158
|
+
self._platform = PlatformPersistService.retrieve(self.platform_id)
|
|
159
|
+
return self._platform
|
|
160
|
+
|
|
161
|
+
@platform.setter
|
|
162
|
+
def platform(self, platform: 'IPlatform'): # noqa E821
|
|
163
|
+
"""
|
|
164
|
+
Sets object platform.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
platform: Platform to set
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
None
|
|
171
|
+
"""
|
|
172
|
+
if platform:
|
|
173
|
+
self.platform_id = platform.uid
|
|
174
|
+
self._platform = platform
|
|
175
|
+
else:
|
|
176
|
+
self._platform = self.platform_id = None
|
|
177
|
+
|
|
178
|
+
def get_platform_object(self, force: bool = False, platform: 'IPlatform' = None, **kwargs):
|
|
179
|
+
"""
|
|
180
|
+
Get the platform representation of an object.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
force: Force reload of platform object
|
|
184
|
+
platform: Allow passing platform object to fetch
|
|
185
|
+
**kwargs: Optional args used for specific platform behaviour
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Platform Object
|
|
189
|
+
"""
|
|
190
|
+
if platform:
|
|
191
|
+
self.platform = platform
|
|
192
|
+
if not self.platform:
|
|
193
|
+
raise NoPlatformException("The object has no platform set...")
|
|
194
|
+
if self._platform_object is None or force:
|
|
195
|
+
self._platform_object = self.platform.get_item(self.uid, self.item_type, raw=True, force=force, **kwargs)
|
|
196
|
+
return self._platform_object
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def done(self):
|
|
200
|
+
"""
|
|
201
|
+
Returns if a item is done.
|
|
202
|
+
|
|
203
|
+
For an item to be done, it should be in either failed or succeeded state.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
True if status is succeeded or failed
|
|
207
|
+
"""
|
|
208
|
+
return self.status in (EntityStatus.SUCCEEDED, EntityStatus.FAILED)
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def succeeded(self):
|
|
212
|
+
"""
|
|
213
|
+
Returns if an item has succeeded.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
True if status is SUCCEEDED
|
|
217
|
+
"""
|
|
218
|
+
return self.status == EntityStatus.SUCCEEDED
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def failed(self):
|
|
222
|
+
"""
|
|
223
|
+
Returns is a item has failed.
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
True if status is failed
|
|
227
|
+
"""
|
|
228
|
+
return self.status == EntityStatus.FAILED
|
|
229
|
+
|
|
230
|
+
def __hash__(self):
|
|
231
|
+
"""
|
|
232
|
+
Returns hash for object. For entities, the hash is the id.
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
Hash id
|
|
236
|
+
"""
|
|
237
|
+
return id(self.uid)
|
|
238
|
+
|
|
239
|
+
def _check_for_platform_from_context(self, platform) -> 'IPlatform':
|
|
240
|
+
"""
|
|
241
|
+
Try to determine platform of current object from self or current platform.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
platform: Passed in platform object
|
|
245
|
+
|
|
246
|
+
Raises:
|
|
247
|
+
NoPlatformException: when no platform is on current context
|
|
248
|
+
Returns:
|
|
249
|
+
Platform object
|
|
250
|
+
"""
|
|
251
|
+
if self.platform is None:
|
|
252
|
+
# check context for current platform
|
|
253
|
+
if platform is None:
|
|
254
|
+
platform = self.get_current_platform_or_error()
|
|
255
|
+
self.platform = platform
|
|
256
|
+
return self.platform
|
|
257
|
+
|
|
258
|
+
@staticmethod
|
|
259
|
+
def get_current_platform_or_error():
|
|
260
|
+
"""
|
|
261
|
+
Try to fetch the current platform from context. If no platform is set, error.
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
Platform if set
|
|
265
|
+
|
|
266
|
+
Raises:
|
|
267
|
+
NoPlatformException if no platform is set on the current context
|
|
268
|
+
"""
|
|
269
|
+
from idmtools.core.context import get_current_platform
|
|
270
|
+
p = get_current_platform()
|
|
271
|
+
if p is None:
|
|
272
|
+
raise NoPlatformException("No Platform defined on object, in current context, or passed to run")
|
|
273
|
+
return p
|
|
274
|
+
|
|
275
|
+
def to_id_file(self, filename: Union[str, PathLike], save_platform: bool = False, platform_args: Dict = None):
|
|
276
|
+
"""
|
|
277
|
+
Write a id file.
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
filename: Filename to create
|
|
281
|
+
save_platform: Save platform to the file as well
|
|
282
|
+
platform_args: Platform Args
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
None
|
|
286
|
+
"""
|
|
287
|
+
write_id_file(filename, self, save_platform, platform_args)
|
|
288
|
+
|
|
289
|
+
def get_directory(self) -> Path:
|
|
290
|
+
"""
|
|
291
|
+
Retrieve the directory path associated with the current item.
|
|
292
|
+
|
|
293
|
+
This method returns the local platform-specific directory for the item,
|
|
294
|
+
such as a simulation, experiment, or suite. It is only supported for
|
|
295
|
+
non-COMPS platforms and for items of type SIMULATION, EXPERIMENT, or SUITE.
|
|
296
|
+
|
|
297
|
+
Raises:
|
|
298
|
+
RuntimeError: If the current platform is COMPSPlatform, or if the item
|
|
299
|
+
type is not one of SIMULATION, EXPERIMENT, or SUITE.
|
|
300
|
+
AttributeError: If the item does not have an associated platform object.
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
pathlib.Path: The path to the item's working directory on the current platform.
|
|
304
|
+
"""
|
|
305
|
+
platform = self.get_current_platform_or_error()
|
|
306
|
+
if not hasattr(platform, 'job_directory'):
|
|
307
|
+
raise RuntimeError(f'Not support get_directory for {platform.__class__.__name__}')
|
|
308
|
+
if self.item_type not in (ItemType.SIMULATION, ItemType.EXPERIMENT, ItemType.SUITE):
|
|
309
|
+
raise RuntimeError('Only support Suite/Experiment/Simulation for get_directory() for now.')
|
|
310
|
+
return platform.get_directory(self)
|
|
311
|
+
|
|
312
|
+
@property
|
|
313
|
+
def directory(self) -> Path:
|
|
314
|
+
"""
|
|
315
|
+
The get directory for the current item. This is a convenience alias for get_directory.
|
|
316
|
+
Returns:
|
|
317
|
+
pathlib.Path: The path to the item's working directory on the current platform.
|
|
318
|
+
"""
|
|
319
|
+
return self.get_directory()
|
|
320
|
+
|
|
321
|
+
def get_tags(self) -> Dict[str, Any]:
|
|
322
|
+
"""
|
|
323
|
+
Get the tags associated with the entity (alias for the `tags` property).
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
Dict[str, Any]: The dictionary of tags.
|
|
327
|
+
"""
|
|
328
|
+
return self.tags
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
IEntityList = List[IEntity]
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
IItem is the base of all items that have ids such as AssetCollections, Experiments, etc.
|
|
3
|
+
|
|
4
|
+
Copyright 2025, Bill Foundation. All rights reserved.
|
|
5
|
+
"""
|
|
6
|
+
from dataclasses import dataclass, field, fields
|
|
7
|
+
from inspect import signature
|
|
8
|
+
from logging import getLogger, DEBUG
|
|
9
|
+
from typing import List, Callable, TYPE_CHECKING, Any, Dict
|
|
10
|
+
from uuid import uuid4
|
|
11
|
+
|
|
12
|
+
from idmtools.utils.hashing import ignore_fields_in_dataclass_on_pickle
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
15
|
+
from idmtools.entities.iplatform import IPlatform
|
|
16
|
+
|
|
17
|
+
logger = getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
PRE_POST_CREATION_HOOK = Callable[['IItem', 'IPlatform'], None]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(repr=False)
|
|
23
|
+
class IItem:
|
|
24
|
+
"""
|
|
25
|
+
IItem represents items that have identifiable ids.
|
|
26
|
+
|
|
27
|
+
In addition, IItem facilities pre and post creation hooks through the __pre_creation_hooks, __post_creation_hooks, add_pre_creation_hook, add_post_creation_hook
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
_uid: str = field(default=None, metadata={"md": True})
|
|
31
|
+
__pre_creation_hooks: List[PRE_POST_CREATION_HOOK] = field(default_factory=list, metadata={"md": True})
|
|
32
|
+
__post_creation_hooks: List[PRE_POST_CREATION_HOOK] = field(default_factory=list, metadata={"md": True})
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def uid(self):
|
|
36
|
+
"""
|
|
37
|
+
UID Of the object.
|
|
38
|
+
Returns:
|
|
39
|
+
ID
|
|
40
|
+
"""
|
|
41
|
+
if self._uid is None:
|
|
42
|
+
self._uid = str(uuid4())
|
|
43
|
+
return self._uid
|
|
44
|
+
|
|
45
|
+
@uid.setter
|
|
46
|
+
def uid(self, uid):
|
|
47
|
+
"""
|
|
48
|
+
Set the uid on the objects.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
uid: Uid to set
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
None
|
|
55
|
+
"""
|
|
56
|
+
self._uid = uid
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def id(self):
|
|
60
|
+
"""
|
|
61
|
+
Alias for uid.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
UID of object
|
|
65
|
+
|
|
66
|
+
Notes:
|
|
67
|
+
What is relation to uid?
|
|
68
|
+
"""
|
|
69
|
+
if self.uid:
|
|
70
|
+
return str(self.uid)
|
|
71
|
+
else:
|
|
72
|
+
return self.uid
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def metadata(self) -> Dict[str, Any]:
|
|
76
|
+
"""
|
|
77
|
+
Identify the metadata from the fields.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Metadata dict
|
|
81
|
+
"""
|
|
82
|
+
attrs = set(vars(self).keys())
|
|
83
|
+
obj_dict = {k: getattr(self, k) for k in attrs.intersection(self.metadata_fields)}
|
|
84
|
+
return obj_dict
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def pickle_ignore_fields(self):
|
|
88
|
+
"""
|
|
89
|
+
Get list of fields that will be ignored when pickling.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Set of fields that are ignored when pickling the item
|
|
93
|
+
"""
|
|
94
|
+
return set(f.name for f in fields(self) if "pickle_ignore" in f.metadata and f.metadata["pickle_ignore"])
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def metadata_fields(self):
|
|
98
|
+
"""
|
|
99
|
+
Get list of fields that have metadata.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Set of fields that have metadata
|
|
103
|
+
"""
|
|
104
|
+
return set(f.name for f in fields(self) if "md" in f.metadata and f.metadata["md"])
|
|
105
|
+
|
|
106
|
+
def display(self) -> str:
|
|
107
|
+
"""
|
|
108
|
+
Display as string representation.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
String of item
|
|
112
|
+
"""
|
|
113
|
+
return self.__repr__()
|
|
114
|
+
|
|
115
|
+
# region Events methods
|
|
116
|
+
def pre_creation(self, platform: 'IPlatform') -> None:
|
|
117
|
+
"""
|
|
118
|
+
Called before the actual creation of the entity.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
platform: Platform item is being created on
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
None
|
|
125
|
+
"""
|
|
126
|
+
for hook in self.__pre_creation_hooks:
|
|
127
|
+
if logger.isEnabledFor(DEBUG):
|
|
128
|
+
logger.debug(f'Calling pre-create hook named {hook.__name__ if hasattr(hook, "__name__") else str(hook)}')
|
|
129
|
+
hook(self, platform)
|
|
130
|
+
|
|
131
|
+
def post_creation(self, platform: 'IPlatform') -> None:
|
|
132
|
+
"""
|
|
133
|
+
Called after the actual creation of the entity.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
platform: Platform item was created on
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
None
|
|
140
|
+
"""
|
|
141
|
+
for hook in self.__post_creation_hooks:
|
|
142
|
+
if logger.isEnabledFor(DEBUG):
|
|
143
|
+
logger.debug(f'Calling post-create hook named {hook.__name__ if hasattr(hook, "__name__") else str(hook)}')
|
|
144
|
+
hook(self, platform)
|
|
145
|
+
|
|
146
|
+
def add_pre_creation_hook(self, hook: PRE_POST_CREATION_HOOK):
|
|
147
|
+
"""
|
|
148
|
+
Adds a hook function to be called before an item is created.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
hook: Hook function. This should have two arguments, the item and the platform
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
None
|
|
155
|
+
"""
|
|
156
|
+
if len(signature(hook).parameters) != 2:
|
|
157
|
+
raise ValueError("Pre creation hooks should have 2 arguments. The first argument will be the item, the second the platform")
|
|
158
|
+
self.__pre_creation_hooks.append(hook)
|
|
159
|
+
|
|
160
|
+
def add_post_creation_hook(self, hook: PRE_POST_CREATION_HOOK):
|
|
161
|
+
"""
|
|
162
|
+
Adds a hook function to be called after an item is created.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
hook: Hook function. This should have two arguments, the item and the platform
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
None
|
|
169
|
+
"""
|
|
170
|
+
if len(signature(hook).parameters) != 2:
|
|
171
|
+
raise ValueError("Post creation hooks should have 2 arguments. The first argument will be the item, the second the platform")
|
|
172
|
+
self.__post_creation_hooks.append(hook)
|
|
173
|
+
|
|
174
|
+
def post_setstate(self):
|
|
175
|
+
"""
|
|
176
|
+
Function called after restoring the state if additional initialization is required.
|
|
177
|
+
"""
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
def pre_getstate(self):
|
|
181
|
+
"""
|
|
182
|
+
Function called before picking and return default values for "pickle-ignore" fields.
|
|
183
|
+
"""
|
|
184
|
+
pass
|
|
185
|
+
|
|
186
|
+
# endregion
|
|
187
|
+
|
|
188
|
+
# region State management
|
|
189
|
+
def __getstate__(self):
|
|
190
|
+
"""
|
|
191
|
+
Ignore the fields in pickle_ignore_fields during pickling.
|
|
192
|
+
"""
|
|
193
|
+
return ignore_fields_in_dataclass_on_pickle(self)
|
|
194
|
+
|
|
195
|
+
def __setstate__(self, state):
|
|
196
|
+
"""
|
|
197
|
+
Add ignored fields back since they don't exist in the pickle.
|
|
198
|
+
"""
|
|
199
|
+
self.__dict__.update(state)
|
|
200
|
+
|
|
201
|
+
# Restore the pickle fields with values requested
|
|
202
|
+
self.post_setstate()
|
|
203
|
+
# endregion
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
IItemList = List[IItem]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Here we implement the Metadata operations interface.
|
|
3
|
+
|
|
4
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
5
|
+
"""
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Dict, List
|
|
9
|
+
from idmtools.core import ItemType
|
|
10
|
+
from idmtools.core.interfaces.ientity import IEntity
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class IMetadataOperations(ABC):
|
|
15
|
+
"""
|
|
16
|
+
Operations to handle metadata for SlurmPlatform.
|
|
17
|
+
"""
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def get(self, item: IEntity) -> Dict:
|
|
20
|
+
"""
|
|
21
|
+
Obtain item's metadata.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
item: idmtools entity (Suite, Experiment and Simulation, etc.)
|
|
25
|
+
Returns:
|
|
26
|
+
a key/value dict of metadata from the given item
|
|
27
|
+
"""
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def dump(self, item: IEntity) -> None:
|
|
32
|
+
"""
|
|
33
|
+
Save item's metadata to a file.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
item: idmtools entity (Suite, Experiment and Simulation, etc.)
|
|
37
|
+
Returns:
|
|
38
|
+
None
|
|
39
|
+
"""
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
@abstractmethod
|
|
43
|
+
def load(self, item: IEntity) -> Dict:
|
|
44
|
+
"""
|
|
45
|
+
Obtain item's metadata file.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
item: idmtools entity (Suite, Experiment and Simulation, etc.)
|
|
49
|
+
Returns:
|
|
50
|
+
key/value dict of item's metadata file
|
|
51
|
+
"""
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def update(self, item: IEntity) -> None:
|
|
56
|
+
"""
|
|
57
|
+
Update item's metadata file.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
item: idmtools entity (Suite, Experiment and Simulation, etc.)
|
|
61
|
+
Returns:
|
|
62
|
+
None
|
|
63
|
+
"""
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def clear(self, item: IEntity) -> None:
|
|
68
|
+
"""
|
|
69
|
+
Clear the item's metadata file.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
item: idmtools entity (Suite, Experiment and Simulation, etc.)
|
|
73
|
+
Returns:
|
|
74
|
+
None
|
|
75
|
+
"""
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
@abstractmethod
|
|
79
|
+
def filter(self, item_type: ItemType, item_filter: Dict = None) -> List:
|
|
80
|
+
"""
|
|
81
|
+
Obtain all items that match the given item_filter key/value pairs passed.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
item_type: the type of items to search for matches (simulation, experiment, suite, etc)
|
|
85
|
+
item_filter: a dict of metadata key/value pairs for exact match searching
|
|
86
|
+
Returns:
|
|
87
|
+
a list of matching items
|
|
88
|
+
"""
|
|
89
|
+
pass
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
INamedEntity definition. INamedEntity Provides a class with a name like Experiments or Suites.
|
|
3
|
+
|
|
4
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
5
|
+
"""
|
|
6
|
+
from abc import ABCMeta
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
|
|
9
|
+
from idmtools.core.interfaces.ientity import IEntity
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class INamedEntity(IEntity, metaclass=ABCMeta):
|
|
14
|
+
"""
|
|
15
|
+
INamedEntity extends the IEntity adding the name property.
|
|
16
|
+
"""
|
|
17
|
+
name: str = field(default=None, metadata={"md": True}, compare=False)
|