Source code for lsst.validate.base.blob

# See COPYRIGHT file at the top of the source tree.
from __future__ import print_function, division

import abc
import uuid

from .jsonmixin import JsonSerializationMixin
from .datummixin import DatumAttributeMixin
from .datum import Datum


__all__ = ['BlobBase', 'DeserializedBlob']


[docs]class BlobBase(JsonSerializationMixin, DatumAttributeMixin): """Base class for blobs: flexible containers of data that are serialized to JSON. .. seealso:: The page :ref:`validate-base-creating-blobs` describes how to create blob classes. """ datums = None """`dict` of `Datum` instances contained by the blob instance. The values of blobs can also be accessed as attributes of the `BlobBase` subclass. Keys in `datums` and attributes share the same names. """ def __init__(self): self.datums = {} self._id = uuid.uuid4().hex def __getattr__(self, key): if key in self.datums: return self.datums[key].quantity else: raise AttributeError("%r object has no attribute %r" % (self.__class__, key)) def __setattr__(self, key, value): if key != 'datums' and key in self.datums: # Setting value of a serialized Datum self.datums[key].quantity = value else: super(BlobBase, self).__setattr__(key, value) @abc.abstractproperty def name(self): """Name of this blob (the `BlobBase` subclass's Python namespace).""" pass @property def identifier(self): """Unique UUID4-based identifier for this blob (`str`).""" return self._id @classmethod
[docs] def from_json(cls, json_data): """Construct a Blob from a JSON dataset. Parameters ---------- json_data : `dict` Blob JSON object. Returns ------- blob : `BlobBase`-type Blob from JSON. """ datums = {k: Datum.from_json(v) for k, v in json_data['data'].items()} return cls(json_data['name'], json_data['identifier'], datums)
@property def json(self): """Job data as a JSON-serializable `dict`.""" json_doc = JsonSerializationMixin.jsonify_dict({ 'identifier': self.identifier, 'name': self.name, 'data': self.datums}) return json_doc
[docs] def register_datum(self, name, quantity=None, label=None, description=None, datum=None): """Register a new `Datum` to be contained by, and serialized via, this blob. The value of the `Datum` can either be set at registration time (with the ``quantity`` or ``datum`` arguments) or later by setting the instance attribute named ``name``. Values of `Datum`\ s can always be accessed or updated through instance attributes. The full `Datum` object can be accessed as items of the `datums` dictionary attached to this class. This method is useful for accessing or updating metadata about a `Datum`, such as: `~Datum.unit`, `~Datum.label`, or `~Datum.description`. Parameters ---------- name : `str` Name of the `Datum`; used as the key in the `datums` attribute of this object. value : obj Value of the `Datum`. label : `str`, optional Label suitable for plot axes (without units). By default the `name` is used as the ``label``. Setting this label argument overrides this default. description : `str`, optional Extended description. datum : `Datum`, optional If a `Datum` is provided, its value, units and label will be used unless overriden by other arguments to `register_datum`. """ self._register_datum_attribute(self.datums, name, quantity=quantity, label=label, description=description, datum=datum)
[docs]class DeserializedBlob(BlobBase): """A concrete Blob deserialized from JSON. This class should only be used internally. """ name = None def __init__(self, name, id_, datums): BlobBase.__init__(self) self.name = name self._id = id_ self.datums = datums