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