Source code for cobra.core.DictList

from copy import copy, deepcopy
import re

[docs]def get_id(object): """return an id for the object This allows the function to be generalize to non-cobra.core objects, however, this added function call slows things down. """ return object.id
[docs]class DictList(list): """A combined dict and list that feels like a list, but has the speed benefits of a dict. This may be eventually replaced by collections.OrderedDict. This was written to address the performance issues associated with searching, accessing, or iterating over a list in python that resulted in notable performance decays with COBRA for python. """ def __init__(self, *args, **kwargs): list.__init__(self, *args, **kwargs) self._dict = {} self._object_dict = {} self._generate_index() def _check(self, id): """make sure duplicate id's are not added. This function is called before adding in elements. """ if id in self._dict: raise ValueError, "id %s is already present in list" % str(id) def _generate_index(self): """rebuild the _dict index """ self._dict = {} self._object_dict = {} [(self._dict.update({v.id: k}), self._object_dict.update({v.id: v})) for k, v in enumerate(self)]
[docs] def get_by_id(self, id): """return the element with a matching id """ return self._object_dict[id]
[docs] def list_attr(self, attribute): """return a list of the given attribute for every object """ return [getattr(i, attribute) for i in self]
[docs] def query(self, search_function, attribute="id"): """query the list search_function: this will be used to select which objects to return This can be: - a string, in which case any object.attribute containing the string will be returned - a compiled regular expression - a boolean function which takes one argument and returns True for desired values attribute: the attribute to be searched for (default is 'id'). If this is None, the object itself is used. returns: a list of objects which match the query """ if attribute == None: select_attribute = lambda x : x else: select_attribute = lambda x: getattr(the_object, attribute) # if the search_function is a regular expression match_list = DictList() if isinstance(search_function, str): search_function = re.compile(search_function) if hasattr(search_function, "findall"): for the_object in self: if search_function.findall(select_attribute(the_object)) != []: match_list.append(the_object) else: for the_object in self: if search_function(select_attribute(the_object)): match_list.append(the_object) return match_list # overriding default list functions with new ones
def __setitem__(self, i, y): the_id = get_id(y) self._check(the_id) super(DictList, self).__setitem__(i, y) self._dict[the_id] = i self._object_dict[the_id] = y
[docs] def append(self, object): the_id = get_id(object) self._check(the_id) self._dict[the_id] = len(self) super(DictList, self).append(object) self._object_dict[the_id] = object
[docs] def union(self, iterable): """adds elements with id's not already in the model""" [self.append(i) for i in iterable if get_id(i) not in self._dict]
[docs] def extend(self, iterable): [self.append(i) for i in iterable]
def __add__(self, other, should_deepcopy=True): """ other: an DictList should_deepcopy: Boolean. Allow for shallow copying, however, this can cause problems if one doesn't know that the items are referenceable from different id """ if should_deepcopy: sum = deepcopy(self) # should this be deepcopy or shallow? else: sum = self sum.extend(other) sum._generate_index() return sum def __iadd__(self, other): self.extend(other) return self
[docs] def index(self, id): """ id: A string or a :class:`~cobra.core.Object` """ # because values are unique, start and stop are not relevant try: the_object = self._dict[id] except: the_object = self._dict[id.id] if self[the_object] is not id: raise Exception("The id for the cobra.object (%s) provided "%repr(id) +\ "is in this dictionary but the_id is not the cobra.object") return the_object
def __contains__(self, object): """DictList.__contains__(object) <==> object in DictList object can either be the object to search for itself, or simply the id """ if hasattr(object, "id"): the_id = get_id(object) # allow to check with the object itself in addition to the id else: the_id = object return self._dict.has_key(the_id) def __copy__(self): self._dict.clear() self._object_dict.clear() the_copy = copy(super(DictList, self)) self._generate_index() the_copy._generate_index() return the_copy def __deepcopy__(self, *args, **kwargs): self._dict.clear() self._object_dict.clear() the_copy = deepcopy(super(DictList, self), *args, **kwargs) self._generate_index() the_copy._generate_index() return the_copy # these functions are slower because they rebuild the _dict every time # TODO: speed up
[docs] def insert(index, object): self._check(get_id(object)) super(DictList, self).insert(index, object) self._generate_index()
[docs] def pop(self, *args, **kwargs): value = super(DictList, self).pop(*args, **kwargs) self._generate_index() return value
[docs] def remove(self, *args, **kwargs): super(DictList, self).remove(*args, **kwargs) self._generate_index()
[docs] def reverse(self, *args, **kwargs): super(DictList, self).reverse(*args, **kwargs) self._generate_index()
[docs] def sort(self, *args, **kwargs): super(DictList, self).sort(*args, **kwargs) self._generate_index()
def __setslice__(self, *args, **kwargs): super(DictList, self).__setslice__(*args, **kwargs) self._generate_index() def __delslice__(self, *args, **kwargs): super(DictList, self).__delslice__(*args, **kwargs) self._generate_index() def __delitem__(self, *args, **kwargs): super(DictList, self).__delitem__(*args, **kwargs) self._generate_index() def __getattr__(self, attr): try: return super(DictList, self).__getattribute__(attr) except: try: func = super(DictList, self).__getattribute__("get_by_id") return func(attr) except: raise AttributeError("DictList has no attribute or entry %s" % \ (attr)) def __dir__(self): attributes = self.__class__.__dict__.keys() attributes.extend(self._dict.keys()) return attributes