--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/django/contrib/gis/geos/mutable_list.py Wed Jan 20 00:34:04 2010 +0100
@@ -0,0 +1,309 @@
+# Copyright (c) 2008-2009 Aryeh Leib Taurog, all rights reserved.
+# Released under the New BSD license.
+"""
+This module contains a base type which provides list-style mutations
+without specific data storage methods.
+
+See also http://www.aryehleib.com/MutableLists.html
+
+Author: Aryeh Leib Taurog.
+"""
+class ListMixin(object):
+ """
+ A base class which provides complete list interface.
+ Derived classes must call ListMixin's __init__() function
+ and implement the following:
+
+ function _get_single_external(self, i):
+ Return single item with index i for general use.
+ The index i will always satisfy 0 <= i < len(self).
+
+ function _get_single_internal(self, i):
+ Same as above, but for use within the class [Optional]
+ Note that if _get_single_internal and _get_single_internal return
+ different types of objects, _set_list must distinguish
+ between the two and handle each appropriately.
+
+ function _set_list(self, length, items):
+ Recreate the entire object.
+
+ NOTE: items may be a generator which calls _get_single_internal.
+ Therefore, it is necessary to cache the values in a temporary:
+ temp = list(items)
+ before clobbering the original storage.
+
+ function _set_single(self, i, value):
+ Set the single item at index i to value [Optional]
+ If left undefined, all mutations will result in rebuilding
+ the object using _set_list.
+
+ function __len__(self):
+ Return the length
+
+ int _minlength:
+ The minimum legal length [Optional]
+
+ int _maxlength:
+ The maximum legal length [Optional]
+
+ type or tuple _allowed:
+ A type or tuple of allowed item types [Optional]
+
+ class _IndexError:
+ The type of exception to be raise on invalid index [Optional]
+ """
+
+ _minlength = 0
+ _maxlength = None
+ _IndexError = IndexError
+
+ ### Python initialization and special list interface methods ###
+
+ def __init__(self, *args, **kwargs):
+ if not hasattr(self, '_get_single_internal'):
+ self._get_single_internal = self._get_single_external
+
+ if not hasattr(self, '_set_single'):
+ self._set_single = self._set_single_rebuild
+ self._assign_extended_slice = self._assign_extended_slice_rebuild
+
+ super(ListMixin, self).__init__(*args, **kwargs)
+
+ def __getitem__(self, index):
+ "Get the item(s) at the specified index/slice."
+ if isinstance(index, slice):
+ return [self._get_single_external(i) for i in xrange(*index.indices(len(self)))]
+ else:
+ index = self._checkindex(index)
+ return self._get_single_external(index)
+
+ def __delitem__(self, index):
+ "Delete the item(s) at the specified index/slice."
+ if not isinstance(index, (int, long, slice)):
+ raise TypeError("%s is not a legal index" % index)
+
+ # calculate new length and dimensions
+ origLen = len(self)
+ if isinstance(index, (int, long)):
+ index = self._checkindex(index)
+ indexRange = [index]
+ else:
+ indexRange = range(*index.indices(origLen))
+
+ newLen = origLen - len(indexRange)
+ newItems = ( self._get_single_internal(i)
+ for i in xrange(origLen)
+ if i not in indexRange )
+
+ self._rebuild(newLen, newItems)
+
+ def __setitem__(self, index, val):
+ "Set the item(s) at the specified index/slice."
+ if isinstance(index, slice):
+ self._set_slice(index, val)
+ else:
+ index = self._checkindex(index)
+ self._check_allowed((val,))
+ self._set_single(index, val)
+
+ def __iter__(self):
+ "Iterate over the items in the list"
+ for i in xrange(len(self)):
+ yield self[i]
+
+ ### Special methods for arithmetic operations ###
+ def __add__(self, other):
+ 'add another list-like object'
+ return self.__class__(list(self) + list(other))
+
+ def __radd__(self, other):
+ 'add to another list-like object'
+ return other.__class__(list(other) + list(self))
+
+ def __iadd__(self, other):
+ 'add another list-like object to self'
+ self.extend(list(other))
+ return self
+
+ def __mul__(self, n):
+ 'multiply'
+ return self.__class__(list(self) * n)
+
+ def __rmul__(self, n):
+ 'multiply'
+ return self.__class__(list(self) * n)
+
+ def __imul__(self, n):
+ 'multiply'
+ if n <= 0:
+ del self[:]
+ else:
+ cache = list(self)
+ for i in range(n-1):
+ self.extend(cache)
+ return self
+
+ def __cmp__(self, other):
+ 'cmp'
+ slen = len(self)
+ for i in range(slen):
+ try:
+ c = cmp(self[i], other[i])
+ except IndexError:
+ # must be other is shorter
+ return 1
+ else:
+ # elements not equal
+ if c: return c
+
+ return cmp(slen, len(other))
+
+ ### Public list interface Methods ###
+ ## Non-mutating ##
+ def count(self, val):
+ "Standard list count method"
+ count = 0
+ for i in self:
+ if val == i: count += 1
+ return count
+
+ def index(self, val):
+ "Standard list index method"
+ for i in xrange(0, len(self)):
+ if self[i] == val: return i
+ raise ValueError('%s not found in object' % str(val))
+
+ ## Mutating ##
+ def append(self, val):
+ "Standard list append method"
+ self[len(self):] = [val]
+
+ def extend(self, vals):
+ "Standard list extend method"
+ self[len(self):] = vals
+
+ def insert(self, index, val):
+ "Standard list insert method"
+ if not isinstance(index, (int, long)):
+ raise TypeError("%s is not a legal index" % index)
+ self[index:index] = [val]
+
+ def pop(self, index=-1):
+ "Standard list pop method"
+ result = self[index]
+ del self[index]
+ return result
+
+ def remove(self, val):
+ "Standard list remove method"
+ del self[self.index(val)]
+
+ def reverse(self):
+ "Standard list reverse method"
+ self[:] = self[-1::-1]
+
+ def sort(self, cmp=cmp, key=None, reverse=False):
+ "Standard list sort method"
+ if key:
+ temp = [(key(v),v) for v in self]
+ temp.sort(cmp=cmp, key=lambda x: x[0], reverse=reverse)
+ self[:] = [v[1] for v in temp]
+ else:
+ temp = list(self)
+ temp.sort(cmp=cmp, reverse=reverse)
+ self[:] = temp
+
+ ### Private routines ###
+ def _rebuild(self, newLen, newItems):
+ if newLen < self._minlength:
+ raise ValueError('Must have at least %d items' % self._minlength)
+ if self._maxlength is not None and newLen > self._maxlength:
+ raise ValueError('Cannot have more than %d items' % self._maxlength)
+
+ self._set_list(newLen, newItems)
+
+ def _set_single_rebuild(self, index, value):
+ self._set_slice(slice(index, index + 1, 1), [value])
+
+ def _checkindex(self, index, correct=True):
+ length = len(self)
+ if 0 <= index < length:
+ return index
+ if correct and -length <= index < 0:
+ return index + length
+ raise self._IndexError('invalid index: %s' % str(index))
+
+ def _check_allowed(self, items):
+ if hasattr(self, '_allowed'):
+ if False in [isinstance(val, self._allowed) for val in items]:
+ raise TypeError('Invalid type encountered in the arguments.')
+
+ def _set_slice(self, index, values):
+ "Assign values to a slice of the object"
+ try:
+ iter(values)
+ except TypeError:
+ raise TypeError('can only assign an iterable to a slice')
+
+ self._check_allowed(values)
+
+ origLen = len(self)
+ valueList = list(values)
+ start, stop, step = index.indices(origLen)
+
+ # CAREFUL: index.step and step are not the same!
+ # step will never be None
+ if index.step is None:
+ self._assign_simple_slice(start, stop, valueList)
+ else:
+ self._assign_extended_slice(start, stop, step, valueList)
+
+ def _assign_extended_slice_rebuild(self, start, stop, step, valueList):
+ 'Assign an extended slice by rebuilding entire list'
+ indexList = range(start, stop, step)
+ # extended slice, only allow assigning slice of same size
+ if len(valueList) != len(indexList):
+ raise ValueError('attempt to assign sequence of size %d '
+ 'to extended slice of size %d'
+ % (len(valueList), len(indexList)))
+
+ # we're not changing the length of the sequence
+ newLen = len(self)
+ newVals = dict(zip(indexList, valueList))
+ def newItems():
+ for i in xrange(newLen):
+ if i in newVals:
+ yield newVals[i]
+ else:
+ yield self._get_single_internal(i)
+
+ self._rebuild(newLen, newItems())
+
+ def _assign_extended_slice(self, start, stop, step, valueList):
+ 'Assign an extended slice by re-assigning individual items'
+ indexList = range(start, stop, step)
+ # extended slice, only allow assigning slice of same size
+ if len(valueList) != len(indexList):
+ raise ValueError('attempt to assign sequence of size %d '
+ 'to extended slice of size %d'
+ % (len(valueList), len(indexList)))
+
+ for i, val in zip(indexList, valueList):
+ self._set_single(i, val)
+
+ def _assign_simple_slice(self, start, stop, valueList):
+ 'Assign a simple slice; Can assign slice of any length'
+ origLen = len(self)
+ stop = max(start, stop)
+ newLen = origLen - stop + start + len(valueList)
+ def newItems():
+ for i in xrange(origLen + 1):
+ if i == start:
+ for val in valueList:
+ yield val
+
+ if i < origLen:
+ if i < start or i >= stop:
+ yield self._get_single_internal(i)
+
+ self._rebuild(newLen, newItems())