summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/util.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/util.py')
-rw-r--r--lib/sqlalchemy/util.py193
1 files changed, 12 insertions, 181 deletions
diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py
index 5f6d1796c..0e3282385 100644
--- a/lib/sqlalchemy/util.py
+++ b/lib/sqlalchemy/util.py
@@ -208,188 +208,19 @@ class OrderedSet(sets.Set):
self._data = OrderedDict()
if iterable is not None:
self._update(iterable)
-
-class HistoryArraySet(UserList.UserList):
- """extends a UserList to provide unique-set functionality as well as history-aware
- functionality, including information about what list elements were modified
- and commit/rollback capability. When a HistoryArraySet is created with or
- without initial data, it is in a "committed" state. as soon as changes are made
- to the list via the normal list-based access, it tracks "added" and "deleted" items,
- which remain until the history is committed or rolled back."""
- def __init__(self, data = None, readonly=False):
- # stores the array's items as keys, and a value of True, False or None indicating
- # added, deleted, or unchanged for that item
- self.records = OrderedDict()
- if data is not None:
- self.data = data
- for item in data:
- # add items without triggering any change events
- # *ASSUME* the list is unique already. might want to change this.
- self.records[item] = None
- else:
- self.data = []
- self.readonly=readonly
- def __iter__(self):
- return iter(self.data)
- def __getattr__(self, attr):
- """proxies unknown HistoryArraySet methods and attributes to the underlying
- data array. this allows custom list classes to be used."""
- return getattr(self.data, attr)
- def set_data(self, data):
- """sets the data for this HistoryArraySet to be that of the given data.
- duplicates in the incoming list will be removed."""
- # first mark everything current as "deleted"
- for item in self.data:
- self.records[item] = False
- self.do_value_deleted(item)
-
- # switch array
- self.data = data
-
- # TODO: fix this up, remove items from array while iterating
- for i in range(0, len(self.data)):
- if not self.__setrecord(self.data[i], False):
- del self.data[i]
- i -= 1
- for item in self.data:
- self.do_value_appended(item)
- def history_contains(self, obj):
- """returns true if the given object exists within the history
- for this HistoryArrayList."""
- return self.records.has_key(obj)
- def __hash__(self):
- return id(self)
- def do_value_appended(self, value):
- pass
- def do_value_deleted(self, value):
- pass
- def __setrecord(self, item, dochanged=True):
- try:
- val = self.records[item]
- if val is True or val is None:
- return False
- else:
- self.records[item] = None
- if dochanged:
- self.do_value_appended(item)
- return True
- except KeyError:
- self.records[item] = True
- if dochanged:
- self.do_value_appended(item)
- return True
- def __delrecord(self, item, dochanged=True):
- try:
- val = self.records[item]
- if val is None:
- self.records[item] = False
- if dochanged:
- self.do_value_deleted(item)
- return True
- elif val is True:
- del self.records[item]
- if dochanged:
- self.do_value_deleted(item)
- return True
- return False
- except KeyError:
- return False
- def commit(self):
- """commits the added values in this list to be the new "unchanged" values.
- values that have been marked as deleted are removed from the history."""
- for key in self.records.keys():
- value = self.records[key]
- if value is False:
- del self.records[key]
- else:
- self.records[key] = None
- def rollback(self):
- """rolls back changes to this list to the last "committed" state."""
- # TODO: speed this up
- list = []
- for key, status in self.records.iteritems():
- if status is False or status is None:
- list.append(key)
- self._clear_data()
- self.records = {}
- for l in list:
- self.append_nohistory(l)
- def clear(self):
- """clears the list and removes all history."""
- self._clear_data()
- self.records = {}
- def _clear_data(self):
- if isinstance(self.data, dict):
- self.data.clear()
- else:
- self.data[:] = []
- def added_items(self):
- """returns a list of items that have been added since the last "committed" state."""
- return [key for key in self.data if self.records[key] is True]
- def deleted_items(self):
- """returns a list of items that have been deleted since the last "committed" state."""
- return [key for key, value in self.records.iteritems() if value is False]
- def unchanged_items(self):
- """returns a list of items that have not been changed since the last "committed" state."""
- return [key for key in self.data if self.records[key] is None]
- def append_nohistory(self, item):
- """appends an item to the list without affecting the "history"."""
- if not self.records.has_key(item):
- self.records[item] = None
- self.data.append(item)
- def remove_nohistory(self, item):
- """removes an item from the list without affecting the "history"."""
- if self.records.has_key(item):
- del self.records[item]
- self.data.remove(item)
- def has_item(self, item):
- return self.records.has_key(item) and self.records[item] is not False
- def __setitem__(self, i, item):
- if self.__setrecord(item):
- self.data[i] = item
- def __delitem__(self, i):
- self.__delrecord(self.data[i])
- del self.data[i]
- def __setslice__(self, i, j, other):
- print "HAS SETSLICE"
- i = max(i, 0); j = max(j, 0)
- if isinstance(other, UserList.UserList):
- l = other.data
- elif isinstance(other, type(self.data)):
- l = other
- else:
- l = list(other)
- [self.__delrecord(x) for x in self.data[i:]]
- g = [a for a in l if self.__setrecord(a)]
- self.data[i:] = g
- def __delslice__(self, i, j):
- i = max(i, 0); j = max(j, 0)
- for a in self.data[i:j]:
- self.__delrecord(a)
- del self.data[i:j]
- def append(self, item):
- if self.__setrecord(item):
- self.data.append(item)
- def insert(self, i, item):
- if self.__setrecord(item):
- self.data.insert(i, item)
- def pop(self, i=-1):
- item = self.data[i]
- if self.__delrecord(item):
- return self.data.pop(i)
- def remove(self, item):
- if self.__delrecord(item):
- self.data.remove(item)
- def extend(self, item_list):
- for item in item_list:
- self.append(item)
- def __add__(self, other):
- raise NotImplementedError()
- def __radd__(self, other):
- raise NotImplementedError()
- def __iadd__(self, other):
- raise NotImplementedError()
+class UniqueAppender(object):
+ def __init__(self, data):
+ self.data = data
+ if hasattr(data, 'append'):
+ self._data_appender = data.append
+ elif hasattr(data, 'add'):
+ self._data_appender = data.add
+ self.set = Set()
+ def append(self, item):
+ if item not in self.set:
+ self.set.add(item)
+ self._data_appender(item)
class ScopedRegistry(object):
"""a Registry that can store one or multiple instances of a single class