Source code for idmtools.utils.entities
"""
utilities for dataclasses.
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
"""
import ast
import os
import dataclasses
import typing
from logging import getLogger
from pathlib import Path
if typing.TYPE_CHECKING:
from idmtools.entities.experiment import Experiment
from idmtools.entities.iworkflow_item import IWorkflowItem
from idmtools.entities.iplatform import IPlatform
user_logger = getLogger('user')
[docs]def get_dataclass_common_fields(src, dest, exclude_none: bool = True) -> typing.Dict:
"""
Extracts fields from a dataclass source object who are also defined on destination object.
Useful for situations like nested configurations of data class options.
Args:
src: Source dataclass object
dest: Dest dataclass object
exclude_none: When true, values of None will be excluded
Returns:
Dictionary of common fields between source and destination object
"""
dest_fields = [f.name for f in dataclasses.fields(dest)]
src_fields = dataclasses.fields(src)
result = dict()
for field in src_fields:
if field.name in dest_fields and (not exclude_none or (exclude_none and getattr(src, field.name, None) is not None)):
result[field.name] = getattr(src, field.name)
return result
[docs]def as_dict(src, exclude: typing.List[str] = None, exclude_private_fields: bool = True):
"""
Converts a dataclass to a dict while also obeys rules for exclusion.
Args:
src:
exclude: List of fields to exclude
exclude_private_fields: Should fields that star
Returns:
Data class as dict
"""
if exclude is None:
exclude = []
result = dict()
# get metadata
metadata = dataclasses.fields(src.__class__)
for field in metadata:
field_metadata = field.metadata
if (not exclude_private_fields or field.name[0] != '_') and \
('exclude_from_metadata' not in field_metadata or not field_metadata['exclude_from_metadata']) and \
field.name not in exclude:
result[field.name] = getattr(src, field.name)
return result
[docs]def save_id_as_file_as_hook(item: typing.Union['Experiment', 'IWorkflowItem'], platform: 'IPlatform'):
"""
Predefined hook that will save ids to files for Experiment or WorkItems.
Args:
item:
platform:
Returns:
None
"""
# Import locally because of circular deps
from idmtools.entities.experiment import Experiment
from idmtools.entities.iworkflow_item import IWorkflowItem
if not isinstance(item, (Experiment, IWorkflowItem)):
raise NotImplementedError("Saving id is currently only support for Experiments and Workitems")
id_file = Path(f'{item.item_type}.{item.name}.id')
if os.path.exists(id_file):
os.remove(id_file)
item.to_id_file(id_file)