from modeller.util import modutil import sys __docformat__ = "epytext en" class FixList(object): """A fixed-length list of Modeller data""" def __len__(self): raise NotImplementedError def _getfunc(self, indx): """Get the data at C{indx}""" raise NotImplementedError def _setfunc(self, indx, val): """Set the data at C{indx} to C{val}""" raise TypeError("this list is read-only") def __str__(self): return str([val for val in self]) def __repr__(self): return str(self) def _lookup_index(self, indx, require_inrange=True): return modutil.handle_seq_indx(self, indx, require_inrange=require_inrange) def __getitem__(self, indx): ret = self._lookup_index(indx) if isinstance(ret, int): return self._getfunc(ret) else: return [self[i] for i in ret] def __setitem__(self, indx, val): ret = self._lookup_index(indx) if isinstance(ret, int): self._setfunc(ret, val) else: if not isinstance(val, (list, tuple)) or len(val) != len(ret): raise ValueError("need a list of size %d for assignment" % len(ret)) for (i, v) in zip(ret, val): self[i] = v class AppendList(FixList): """A list of Modeller data which can be added to but not reordered""" def _setfunc(self, indx, val): raise TypeError("this list can only be appended to") def append(self, obj): """Append obj to the end of the list""" raise NotImplementedError def extend(self, objs): """Extend list by adding elements from objs""" for obj in objs: self.append(obj) class VarList(FixList): """A variable-length list of Modeller data""" def _setdimfunc(self, newdim): raise NotImplementedError def clear(self): """Clear all items from the list""" self._setdimfunc(0) def append(self, obj): """Append obj to the end of the list""" dim = len(self) self._setdimfunc(dim + 1) self[dim] = obj def extend(self, objs): """Extend list by adding elements from objs""" dim = len(self) self._setdimfunc(dim + len(objs)) for (n, obj) in enumerate(objs): self[dim + n] = obj def pop(self, index=-1): """Remove and return item at index (default last)""" if len(self) == 0: raise IndexError("pop from empty list") x = self[index] del self[index] return x def insert(self, indx, obj): """Insert object before index""" indx = self._lookup_index(indx, require_inrange=False) if not isinstance(indx, int): raise TypeError("an integer is required") dim = len(self) self._setdimfunc(dim+1) for n in range(dim, indx, -1): self[n] = self[n-1] self[indx] = obj def __delitem__(self, indx): ret = self._lookup_index(indx) if isinstance(ret, int): dim = len(self) for n in range(ret+1, dim): self[n-1] = self[n] self._setdimfunc(dim-1) else: if sys.version_info[:2] == (2,3): ret.sort() ret.reverse() else: ret = sorted(ret, reverse=True) # Not very efficient, particularly for long lists! for i in ret: del self[i] def set_fixlist(lst, obj): """Helper function to set members that are FixList objects""" if len(obj) != len(lst): raise ValueError("expecting a tuple or list of length %d" % len(lst)) for (n, val) in enumerate(obj): lst[n] = val def set_varlist(lst, obj): """Helper function to set members that are VarList objects""" lst.clear() lst.extend(obj) def del_varlist(lst): """Helper function to delete members that are VarList objects""" lst.clear() class LinkList(VarList): """A variable-length linked list of Modeller data""" def _delfunc(self, indx): raise NotImplementedError def _insfunc(self, indx, val): raise NotImplementedError def _setfunc(self, indx, val): self._delfunc(indx) self._insfunc(indx, val) def append(self, obj): """Append obj to the end of the list""" self.insert(len(self), obj) def extend(self, objs): """Extend list by adding elements from objs""" for obj in objs: self.append(obj) def insert(self, indx, obj): """Insert object before index""" indx = self._lookup_index(indx, require_inrange=False) if not isinstance(indx, int): raise TypeError("an integer is required") self._insfunc(indx, obj) def __delitem__(self, indx): ret = self._lookup_index(indx) if isinstance(ret, int): self._delfunc(ret) else: if sys.version_info[:2] == (2,3): ret.sort() ret.reverse() else: ret = sorted(ret, reverse=True) # Not very efficient, particularly for long lists! for i in ret: self._delfunc(i) class SimpleVarList(VarList): def __init__(self, modpt, getdimfunc, setdimfunc, getfunc, setfunc): VarList.__init__(self) self.__modpt = modpt self.__getdimfunc = getdimfunc self.__setdimfunc = setdimfunc self.__setfunc = setfunc self.__getfunc = getfunc def __len__(self): return self.__getdimfunc(self.__modpt) def _getfunc(self, indx): return self.__getfunc(self.__modpt, indx) def _setfunc(self, indx, val): self.__setfunc(self.__modpt, indx, val) def _setdimfunc(self, num): self.__setdimfunc(self.__modpt, num)