diff options
Diffstat (limited to 'lib/sqlalchemy/util.py')
-rw-r--r-- | lib/sqlalchemy/util.py | 193 |
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 |