from datetime import datetime
from typing import Optional, Iterable, Union, Mapping
from xml.etree.ElementTree import Element
from SDF.data_model._helper_functions import pop_child_element
from SDF.data_model.comment import Comment
from SDF.data_model.date import Date
from SDF.data_model.instrument import Instrument, InstrumentSet
from SDF.data_model.name import NameElement
from SDF.data_model.owner import Owner
from SDF.data_model.parameter import AnonymousParameterSet, ParameterType
from SDF.data_model.sample import Sample, SampleSet
[docs]class SDFObject:
"""Superclass for datasets and workspaces"""
def __init__(self, name: Union[str, NameElement], *,
owner: Optional[Union[str, Owner]] = None,
date: Optional[Union[datetime, Date]] = None,
comment: Optional[Union[str, Comment]] = None,
samples: Optional[Union[Iterable[Sample], Mapping[str, str]]] = None,
parameters: Optional[Iterable[ParameterType]] = None,
instruments: Optional[Iterable[Instrument]] = None):
# name
if isinstance(name, NameElement):
self.__name = name
else:
self.__name = NameElement(name)
# owner
if owner is None:
self.__owner = None
elif isinstance(owner, Owner):
self.__owner = owner
else:
self.__owner = Owner(owner)
# date
if date is None:
self.__date = None
elif isinstance(date, Date):
self.__date = date
else:
self.__date = Date(date)
# comment
if comment is None:
self.__comment = None
elif isinstance(comment, Comment):
self.__comment = comment
else:
self.__comment = Comment(comment)
# samples
self.__samples = SampleSet()
if hasattr(samples, "items"): # Mapping[str, str]
for key, value in samples.items():
self.samples[key] = value
elif samples is not None: # Iterable[Sample]
self.samples.update(samples)
# instruments
self.__instruments = InstrumentSet()
if instruments is not None:
self.instruments.update(instruments)
# parameters
self.__parameters = AnonymousParameterSet()
if parameters is not None:
self.parameters.update(parameters)
@property
def name(self) -> str:
return self.__name.name
@property
def owner(self) -> Optional[str]:
if self.__owner is None:
return None
return self.__owner.name
@owner.setter
def owner(self, _owner: Union[str, Owner]) -> None:
if isinstance(_owner, Owner):
self.__owner = _owner
else:
self.__owner = Owner(_owner)
@property
def date(self) -> Optional[datetime]:
if self.__date is None:
return None
return self.__date.date
@date.setter
def date(self, _date: Union[datetime, Date]) -> None:
if isinstance(_date, Date):
self.__date = _date
else:
self.__date = Date(_date)
@property
def comment(self) -> Optional[str]:
if self.__comment is None:
return None
return self.__comment.comment
@comment.setter
def comment(self, _comment: Union[str, Comment]):
if isinstance(_comment, Comment):
self.__comment = _comment
else:
self.__comment = Comment(_comment)
@property
def samples(self) -> SampleSet:
return self.__samples
@property
def parameters(self) -> AnonymousParameterSet:
return self.__parameters
@property
def instruments(self) -> InstrumentSet:
return self.__instruments
def _from_partial_xml_element(self, element: Element) -> None:
# expect an element with common optional fields for Dataset and Workspace
# adds `element`'s content to `self` and removes all consumed children from `element`
if len(element) and element[0].tag == "owner":
self.owner = Owner.from_xml_element(pop_child_element(element, 0))
if len(element) and element[0].tag == "date":
self.date = Date.from_xml_element(pop_child_element(element, 0))
if len(element) and element[0].tag == "comment":
self.comment = Comment.from_xml_element(pop_child_element(element, 0))
while len(element) and element[0].tag == "sample":
self.samples.add(Sample.from_xml_element(pop_child_element(element, 0)))
while len(element) and element[0].tag == "par":
self.parameters.add(ParameterType.from_xml_element(pop_child_element(element, 0)))
while len(element) and element[0].tag == "instrument":
self.instruments.add(Instrument.from_xml_element(pop_child_element(element, 0)))
def _to_partial_xml_element(self, element: Element) -> None:
# fills content of `self` to `element`
element.append(self.__name.to_xml_element())
if self.__owner is not None:
element.append(self.__owner.to_xml_element())
if self.__date is not None:
element.append(self.__date.to_xml_element())
if self.__comment is not None:
element.append(self.__comment.to_xml_element())
for sample in self.samples:
element.append(sample.to_xml_element())
for parameter in self.parameters:
element.append(parameter.to_xml_element())
for instrument in self.instruments:
element.append(instrument.to_xml_element())
def __eq__(self, other):
if isinstance(other, SDFObject):
return (self.__name == other.__name
and self.__owner == other.__owner
and self.__date == other.__date
and self.__comment == other.__comment
and self.samples == other.samples
and self.parameters == other.parameters
and self.instruments == other.instruments)
return False