Source code for mass.util.dict_with_id

# -*- coding: utf-8 -*-
"""
DictWithID and OrderedDictWithID are dictionaries with identifers attributes.

The :mod:`~.dict_with_id` submodule utilizes the built-in :class:`type` to
dynamically create the :class:`DictWithID` and :class:`OrderedDictWithID`
classes based on whether the parent class should be a standard :class:`dict`
or an :class:`~.collections.OrderedDict`, therefore allowing each object to
inherit its parent class methods and generable behavior.

The :class:`DictWithID` and :class:`OrderedDictWithID` classes are primarily
used for in order to use dictionaries with the speciailized
:class:`~cobra.core.dictlist.DictList` container for both performance gains
and user convenience.
"""
from collections import OrderedDict
from copy import copy

from six import string_types


def __constructor(self, id=None, data_dict=None):
    """Initialize a DictWithID instance.

    Parameters
    ----------
    id: str, None
        The identifier to associate with the object.
    data_dict: dict, optional
        If provided, the new DictWithID will contain the key:value pairs from
        "data_dict". Otherwise the new DictWithID is initialized as empty.

    Warnings
    --------
    This object is primarily intended for internal use only.

    """
    super(type(self), self).__setattr__("_id", id)
    if isinstance(data_dict, dict):
        self.update(data_dict)
    elif data_dict is None:
        pass
    else:
        raise TypeError("data_dict must be a dict")


@property
def __id(self):
    """Return identifier of the dictionary."""
    return getattr(self, "_id", None)


@__id.setter
def __id(self, value):
    """Set the identifier of the dictionary."""
    if value == self.id:
        pass
    elif not isinstance(value, string_types):
        raise TypeError("ID must be a string")
    elif getattr(self, "_model", None) is not None:
        self._set_id_with_model(value)
    else:
        self._id = value


def __set_id_with_model(self, value):
    """Set the id of the dictionary to the associated MassModel.

    Warnings
    --------
    This method is intended for internal use only.

    """
    self._id = value


def __copy(self):
    """Copy a DictWithID object."""
    return copy(self)


def __copy__(self):
    """Override default copy() implementation."""
    return copy(super(type(self), self))


def __repr__(self):
    """Override of default repr() implementation."""
    return "<%s %s at 0x%x>" % (self.__class__.__name__, self.id, id(self))


def __str__(self):
    """Override of default str() implementation."""
    return dict(self).__str__()


def __doc__(self):
    """Return the docstring for the class."""
    cls_name = self.__class__.__name__
    supercls_str, all_subclasses = {
        "DictWithID": ["dict", ["MassSolution"]],
        "OrderedDictWithID": ["OrderedDict", ["EnzymeDict"]],
    }[cls_name]

    return """A specialized {1} with an additional ID attribute.

    The {0} class is essentially a subclass of an {1} with a string identifier.
    The {2} objects are all subclasses of {0}.

    Parameters
    ----------
    id: str, None
        The identifier to associate with the {0}.
    data_dict: dict, optional
        If provided, the new {0} will contain the key:value pairs from
        "data_dict". Otherwise the new {0} is initialized as empty.

    """.format(
        cls_name, supercls_str, str(tuple(all_subclasses))
    )


def __make_class_constructor(ordered=False):
    """Create a class constructor for a specialized dictionary class.

    Parameters
    ----------
    ordered: bool
        If True, the constructor will make a subclass of an OrderedDict.
        Otherwise,  the constructor will make a subclass of a regular dict.

    Returns:
    --------
    constructor: class constructor
        The class constructor for OrderedDictWithID or DictWithID

    Warnings
    --------
    This object is primarily intended for internal use only.

    """
    if ordered:
        cls_name, obj = ("OrderedDictWithID", OrderedDict)
    else:
        cls_name, obj = ("DictWithID", dict)

    constructor = type(
        cls_name,
        (obj,),
        {
            "__init__": __constructor,
            "id": __id,
            "copy": __copy,
            "_set_id_with_model": __set_id_with_model,
            "__copy__": __copy__,
            "__repr__": __repr__,
            "__str__": __str__,
            "__doc__": __doc__,
        },
    )

    return constructor


[docs]DictWithID = __make_class_constructor(False)
""" class: Has ID attribute, inherits :class:`dict` methods"""
[docs]OrderedDictWithID = __make_class_constructor(True)
""" class: Has ID attribute, inherits :class:`~collections.OrderedDict` methods.""" __all__ = ("DictWithID", "OrderedDictWithID")