home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyo (Python 2.6) from thread import get_ident from weakref import ref from peak.util import addons, decorators import sys import UserDict import UserList import sets import stm import types import new import weakref import copy from peak.util.extremes import Max from peak.util.symbols import Symbol, NOT_GIVEN __all__ = [ 'Cell', 'Constant', 'make', 'todo', 'todos', 'modifier', 'Component', 'repeat', 'poll', 'InputConflict', 'Dict', 'List', 'Set', 'mark_dirty', 'ctrl', 'ConstantMixin', 'Sensor', 'AbstractConnector', 'Connector', 'Effector', 'init_attrs', 'attr', 'attrs', 'compute', 'maintain', 'perform', 'Performer', 'Pipe'] NO_VALUE = Symbol('NO_VALUE', __name__) _sentinel = NO_VALUE class InputConflict(Exception): pass def init_attrs(self, **kw): if kw: cls = type(self) for k, v in kw.iteritems(): if not hasattr(cls, k): raise TypeError('%s() has no keyword argument %r' % (cls.__name__, k)) hasattr(cls, k) setattr(self, k, v) def named_lambda(func, name): if getattr(func, '__name__', None) == '<lambda>': try: func.__name__ = name except TypeError: pass except: None<EXCEPTION MATCH>TypeError None<EXCEPTION MATCH>TypeError return func try: set = set except NameError: set = sets.Set frozenset = sets.ImmutableSet set_like = sets.BaseSet dictlike = (dict, sets.BaseSet) set_like = (set, frozenset, sets.BaseSet) dictlike = (dict,) + set_like class AbstractCell(object): __slots__ = () rule = None value = None _value = None _needs_init = None writer = None connector = None was_set = False _uninit_repr = ' [uninitialized]' def get_value(self): return self.value def __repr__(self): rule = reset = ni = '' if getattr(self, 'rule', None) is not None: rule = repr(self.rule) + ', ' if self._needs_init: ni = self._uninit_repr if getattr(self, '_reset', _sentinel) is not _sentinel: reset = ', discrete[' + repr(self._reset) + ']' return '%s(%s%r%s%s)' % (self.__class__.__name__, rule, self._value, ni, reset) class _ReadValue(stm.AbstractSubject, AbstractCell): __slots__ = ('_value', 'next_listener', '_set_by', '_reset') def __init__(self, value = None, discrete = False): self._value = value self._set_by = _sentinel stm.AbstractSubject.__init__(self) self._reset = (_sentinel, value)[bool(discrete)] if ctrl.newcells is not None: ctrl.new_cell(self) def get_value(self): if ctrl.active: used(self) return self._value value = property(get_value) def _finish(self): if self._set_by is not _sentinel: change_attr(self, '_set_by', _sentinel) if self._reset is not _sentinel and self._value != self._reset: change_attr(self, '_value', self._reset) changed(self) def was_set(self): if ctrl.current_listener is None: raise RuntimeError('was_set can only be accessed by a rule') ctrl.current_listener is None used(self) who = self._set_by if who is not _sentinel: pass return who is not self was_set = property(was_set) class Value(_ReadValue): __slots__ = '__weakref__' def set_value(self, value): if not ctrl.active: return atomically(self.set_value, value) lock(self) if self._set_by is _sentinel: change_attr(self, '_set_by', ctrl.current_listener) on_commit(self._finish) if value is self._value: return None if value != self._value: if self._set_by not in (ctrl.current_listener, self): raise InputConflict(self._value, value) self._set_by not in (ctrl.current_listener, self) changed(self) change_attr(self, '_value', value) value = property(_ReadValue.get_value.im_func, set_value) def install_controller(controller): global ctrl stm.ctrl = ctrl = controller for name in [ 'on_commit', 'on_undo', 'atomically', 'manage', 'savepoint', 'rollback_to', 'schedule', 'cancel', 'lock', 'used', 'changed', 'initialize', 'change_attr']: globals()[name] = getattr(ctrl, name) if name not in __all__: __all__.append(name) continue install_controller(stm.LocalController()) class ReadOnlyCell(_ReadValue, stm.AbstractListener): __slots__ = ('rule', '_needs_init', 'next_subject', '__weakref__', 'layer') def __init__(self, rule, value = None, discrete = False): super(ReadOnlyCell, self).__init__(value, discrete) stm.AbstractListener.__init__(self) self._needs_init = True self.rule = rule self.layer = 0 def get_value(self): if self._needs_init: if not ctrl.active: atomically(schedule, self) return self._value cancel(self) initialize(self) if ctrl.current_listener is not None: used(self) return self._value value = property(get_value) def run(self): if self._needs_init: change_attr(self, '_needs_init', False) change_attr(self, '_set_by', self) change_attr(self, '_value', self.rule()) on_commit(self._finish) else: value = self.rule() if value != self._value: if self._set_by is _sentinel: change_attr(self, '_set_by', self) on_commit(self._finish) change_attr(self, '_value', value) changed(self) if not ctrl.reads: on_commit(self._check_const) def _check_const(self): if self.next_subject is None: if self._reset is _sentinel or self._value == self._reset: change_attr(self, '_set_by', _sentinel) change_attr(self, 'rule', None) change_attr(self, 'next_listener', None) change_attr(self, '__class__', self._const_class()) def _const_class(self): return ConstantRule class ConstantMixin(AbstractCell): __slots__ = () def __setattr__(self, name, value): if name == '__class__': object.__setattr__(self, name, value) else: raise AttributeError("Constants can't be changed") return name == '__class__' def __repr__(self): return 'Constant(%r)' % (self.value,) class Constant(ConstantMixin): __slots__ = 'value' def __init__(self, value): Constant.value.__set__(self, value) def from_attr(cls, rule, value, discrete): return cls(value) from_attr = classmethod(from_attr) class ConstantRule(ConstantMixin, ReadOnlyCell): __slots__ = () value = ReadOnlyCell._value def dirty(self): return False def run(self): pass class Performer(stm.AbstractListener, AbstractCell): __slots__ = ('run', 'next_subject', '__weakref__') layer = Max def __init__(self, rule): self.run = rule super(Performer, self).__init__() atomically(schedule, self) def from_attr(cls, rule, value, discrete): return cls(rule) from_attr = classmethod(from_attr) Performer.rule = Performer.run def modifier(func): def wrap(__func, __module): return '\n if not __module.ctrl.active:\n return __module.atomically(__func, $args)\n elif __module.ctrl.current_listener is None:\n return __func($args)\n else:\n # Prevent any reads from counting against the current rule\n old_reads, __module.ctrl.reads = __module.ctrl.reads, {}\n try:\n return __func($args)\n finally:\n __module.ctrl.reads = old_reads\n ' return decorators.template_function(wrap)(func, sys.modules[__name__]) set_next_listener = ReadOnlyCell.next_listener.__set__ get_next_listener = ReadOnlyCell.next_listener.__get__ class SensorBase(ReadOnlyCell): __slots__ = () def __init__(self, rule, value = None, discrete = False): if isinstance(rule, AbstractConnector): self.connector = rule rule = rule.read else: self.connector = None self.listening = NOT_GIVEN set_next_listener(self, None) super(SensorBase, self).__init__(rule, value, discrete) def _set_listener(self, listener): was_seen = get_next_listener(self) is not None set_next_listener(self, listener) if was_seen != (listener is not None) and self.connector is not None: atomically(on_commit, schedule, self.update_connection) next_listener = property(get_next_listener, _set_listener) _set_value = Value.set_value.im_func def receive(self, value): if not ctrl.active: return atomically(self.receive, value) lock(self) self._set_value(value) change_attr(self, '_set_by', self) receive = modifier(receive) def _check_const(self): pass def update_connection(): old_listener = ctrl.current_listener ctrl.current_listener = None try: self = old_listener.im_self descr = type(self).listening listening = descr.__get__(self) if self.next_listener is not None: if listening is NOT_GIVEN: descr.__set__(self, self.connector.connect(self)) elif listening is not NOT_GIVEN: self.connector.disconnect(self, listening) descr.__set__(self, NOT_GIVEN) finally: ctrl.current_listener = old_listener update_connection.run = update_connection update_connection.next_subject = None update_connection.next_listener = None update_connection.layer = -1 class Sensor(SensorBase): __slots__ = ('connector', 'listening') class AbstractConnector(object): __slots__ = () def read(self): return ctrl.current_listener._value def connect(self, sensor): pass def disconnect(self, sensor, key): pass class Connector(AbstractConnector): __slots__ = ('read', 'connect', 'disconnect') def __init__(self, connect, disconnect, read = None): if read is None: read = noop self.read = read self.connect = connect self.disconnect = disconnect def noop(): return ctrl.current_listener._value class LazyConnector(AbstractConnector): def connect(sensor): pass connect = staticmethod(connect) def disconnect(sensor, key): link = sensor.next_subject if link is not None: change_attr(sensor, '_needs_init', True) while link is not None: nxt = link.next_subject on_undo(stm.Link, link.subject, sensor) link.unlink() link = nxt disconnect = staticmethod(disconnect) class LazyCell(Sensor): __slots__ = () _uninit_repr = ' [inactive]' def __init__(self, rule, value = None, discrete = False): super(LazyCell, self).__init__(rule, value, discrete) self.connector = LazyConnector _check_const = ReadOnlyCell._check_const def run(self): run = super(LazyCell, self).run if not ctrl.readonly: ctrl.with_readonly(run) else: run() if self.listening is NOT_GIVEN: self.listening = None on_commit(schedule, self.update_connection) def _const_class(self): return LazyConstant def get_value(self): if ctrl.current_listener is self: raise RuntimeError('@compute rules cannot use their own value') ctrl.current_listener is self return super(LazyCell, self).get_value() value = property(get_value) class LazyConstant(ConstantRule, LazyCell): __slots__ = () class Cell(ReadOnlyCell, Value): __slots__ = () def __new__(cls, rule = None, value = _sentinel, discrete = False): v = [ value, None][value is _sentinel] return ReadOnlyCell.__new__(cls, rule, value, discrete) def _check_const(self): pass def get_value(self): if self._needs_init: if not ctrl.active: atomically(schedule, self) return self._value if self._set_by is _sentinel: cancel(self) initialize(self) if ctrl.current_listener is not None: used(self) return self._value def set_value(self, value): if not ctrl.active: return atomically(self.set_value, value) super(Cell, self).set_value(value) if self._needs_init: schedule(self) else: cancel(self) value = property(get_value, set_value) def dirty(self): who = self._set_by if not who is _sentinel: pass return who is self def run(self): if self.dirty(): super(Cell, self).run() elif self._needs_init: change_attr(self, '_needs_init', False) self.rule() else: raise AssertionError('This should never happen!') return self.dirty() class Effector(SensorBase, Cell): __slots__ = ('connector', 'listening') class _Defaulting(addons.Registry): def __init__(self, subject): self.defaults = { } return super(_Defaulting, self).__init__(subject) def created_for(self, cls): for k, v in self.defaults.items(): self.setdefault(k, v) return super(_Defaulting, self).created_for(cls) class CellFactories(_Defaulting): pass class IsOptional(_Defaulting): pass class Cells(addons.AddOn): __slots__ = () addon_key = classmethod((lambda cls: '__cells__')) def __new__(cls, subject): return { } class Component(decorators.classy): __slots__ = () def __class_call__(cls, *args, **kw): if ctrl.readonly and ctrl.newcells is None: return ctrl.with_new(Component.__class_call__.im_func, cls, *args, **kw) optional = IsOptional(cls) rv = super(Component, cls).__class_call__(*args, **kw) if isinstance(rv, cls): cells = Cells(rv) for k, v in optional.iteritems(): if not v and k not in cells: c = cells.setdefault(k, CellFactories(cls)[k](cls, rv, k)) c.value continue ctrl.newcells is None return rv __class_call__ = classmethod(modifier(__class_call__)) __init__ = init_attrs def __sa_instrumentation_manager__(cls): SAInstrument = SAInstrument import peak.events.sa_support return SAInstrument(cls) __sa_instrumentation_manager__ = staticmethod(__sa_instrumentation_manager__) def __class_init__(cls, name, bases, cdict, supr): supr()(cls, name, bases, cdict, supr) try: Component except NameError: return None optional = IsOptional(cls) factories = CellFactories(cls) for k, descr in cdict.items(): if isinstance(descr, CellAttribute): if descr.__name__ is None: descr.__name__ = k optional[k] = descr.optional factories[k] = descr.make_cell continue if k in optional: optional[k] = True continue def repeat(): if ctrl.current_listener is not None: on_commit(schedule, ctrl.current_listener) else: raise RuntimeError('repeat() must be called from a rule') return ctrl.current_listener is not None def poll(): listener = ctrl.current_listener if listener is None or not hasattr(listener, '_needs_init'): raise RuntimeError('poll() must be called from a rule') not hasattr(listener, '_needs_init') return ctrl.pulse.value def mark_dirty(): changed(ctrl.current_listener) def bind(rule, ob, typ = None): if hasattr(rule, '__get__'): return rule.__get__(ob, typ) return rule class CellAttribute(object): value = NO_VALUE rule = None connect = None disconnect = None make = None factory = Cell discrete = False optional = False __name__ = None __init__ = init_attrs def initial_value(self, ob): return self.value def make_cell(self, typ, ob, name): rule = bind(self.rule, ob, typ) if self.connect is not None or self.disconnect is not None: connect = bind(self.connect, ob, typ) disconnect = bind(self.disconnect, ob, typ) missing = 'disconnect' if connect is None: missing = 'connect' if connect is None or disconnect is None: raise TypeError('%r is missing a .%sor' % (self, missing)) disconnect is None rule = Connector(connect, disconnect, rule) return self.factory(rule, self.initial_value(ob), self.discrete) def connector(self, func = None): return self._hook_method('connect', func) def disconnector(self, func = None): return self._hook_method('disconnect', func) def __get__(self, ob, typ = None): if ob is None: return self try: cells = ob.__cells__ except AttributeError: ob is None ob is None cells = Cells(ob) except: ob is None try: cell = cells[self.__name__] except KeyError: ob is None ob is None name = self.__name__ cell = cells.setdefault(name, self.make_cell(typ, ob, name)) except: ob is None return cell.value def __repr__(self): return '%s(%r)' % (self.__class__.__name__, self.__name__) def __set__(self, ob, value): try: cells = ob.__cells__ except AttributeError: cells = Cells(ob) def mkattr(cls, initially = NO_VALUE, resetting_to = NO_VALUE, **kw): if initially is not NO_VALUE and resetting_to is not NO_VALUE: raise TypeError("Can't specify both 'initially' and 'resetting_to'") resetting_to is not NO_VALUE value = initially discrete = False if resetting_to is not NO_VALUE: value = resetting_to discrete = True if value is not NO_VALUE and kw.get('make') is not None: raise TypeError("Can't specify both a value and 'make'") kw.get('make') is not None return cls(value = value, discrete = discrete, **kw) mkattr = classmethod(mkattr) def can_connect(self): if self.factory is LazyCell: self.factory = Sensor elif not self.factory is Cell: pass return self.factory is Sensor return True def _hook_method(self, methodname, func = None, frame = None): if not self.can_connect(): raise TypeError('%r cannot have a .%sor' % (self, methodname)) self.can_connect() if isinstance(self.rule, AbstractConnector): raise TypeError('The rule for %r is itself a Connector' % (self,)) isinstance(self.rule, AbstractConnector) if getattr(self, methodname) is not None: raise TypeError('%r already has a .%sor' % (self, methodname)) getattr(self, methodname) is not None if func is not None: setattr(self, methodname, func) if getattr(func, '__name__', None) == self.__name__: if not frame: pass frame = sys._getframe(2) if frame.f_locals.get(self.__name__) is self: return self return func if not frame: pass frame = sys._getframe(2) def callback(frame, name, func, locals): setattr(self, methodname, func) if name == self.__name__ and locals.get(name) is self: return self return func return decorators.decorate_assignment(callback, frame = frame) def attr(initially = NO_VALUE, resetting_to = NO_VALUE): return CellAttribute.mkattr(initially, resetting_to) def compute(rule = None, resetting_to = NO_VALUE, name = None): return _build_descriptor(rule = rule, resetting_to = resetting_to, factory = LazyCell, optional = True, __name = name) def maintain(rule = None, make = None, initially = NO_VALUE, resetting_to = NO_VALUE, optional = False, name = None): return _build_descriptor(rule = rule, initially = initially, resetting_to = resetting_to, make = make, optional = optional, __name = name) def perform(rule = None, optional = False, name = None): return _build_descriptor(rule = rule, factory = Performer.from_attr, optional = optional, __name = name) def compute_attrs(**attrs): _make_multi(sys._getframe(1), attrs, factory = LazyCell, optional = True) compute.attrs = compute_attrs def maintain_attrs(**attrs): _make_multi(sys._getframe(1), attrs) maintain.attrs = maintain_attrs def attrs(**attrs): _make_multi(sys._getframe(1), attrs, arg = 'initially') def attrs_resetting_to(**attrs): _make_multi(sys._getframe(1), attrs, arg = 'resetting_to') attrs.resetting_to = attrs_resetting_to def _make_multi(frame, kw, wrap = CellAttribute.mkattr, arg = 'rule', **opts): for k, v in kw.items(): if k in frame.f_locals: raise TypeError('%s is already defined in this class' % (k,)) k in frame.f_locals opts[arg] = named_lambda(v, k) frame.f_locals[k] = wrap(__name__ = k, **opts) def _build_descriptor(rule = None, __frame = None, __name = None, __proptype = CellAttribute.mkattr, __ruleattr = 'rule', **kw): if not __frame: pass frame = sys._getframe(2) name = __name if isinstance(rule, types.FunctionType): if frame.f_locals.get(rule.__name__) is rule: if not name: pass name = rule.__name__ def callback(frame, name, rule, locals): kw[__ruleattr] = named_lambda(rule, name) return __proptype(__name__ = name, **kw) if name: return callback(frame, name, rule, None) if rule is not None: try: name = rule.__name__ if name == '<lambda>': decorators.decorate_assignment(callback, frame = frame) return rule except: name (None, None, None) decorators.decorate_assignment(callback, frame = frame) return callback(frame, name, rule, None) return rule is not None name return decorators.decorate_assignment(callback, frame = frame) def todos(**attrs): _make_multi(sys._getframe(1), attrs, TodoProperty.mkattr) def todo(rule = None, name = None): return _build_descriptor(rule = rule, __proptype = TodoProperty.mkattr, __name = name) class TodoProperty(CellAttribute): def future(self): name = self.__name__ def get(ob): try: cells = ob.__cells__ except AttributeError: cells = Cells(ob) try: cell = cells[name] except KeyError: typ = type(ob) cell = cells.setdefault(name, self.make_cell(typ, ob, name)) return cell.get_future() return property(get, doc = 'The future value of the %r attribute' % name) future = property(future) def factory(self, rule, value, discrete): return TodoValue(rule) def build_value(make, ob, name): if hasattr(make, '__get__'): make = make.__get__(ob, type(ob)) return make() def make(rule = None, writable = False, optional = True, name = None): return _build_descriptor(rule, optional = optional, __ruleattr = 'make', factory = [ Constant.from_attr, Cell][bool(writable)], __name = name) def make_attrs(**attrs): _make_multi(sys._getframe(1), attrs, factory = Constant.from_attr, arg = 'make', optional = True) make.attrs = make_attrs class TodoValue(Value): __slots__ = ('rule', '_copy', '_last_reader') def __new__(cls, rule, copy = copy.copy): return Value.__new__(cls) def __init__(self, rule, copy = copy.copy): self.rule = rule self._copy = copy self._last_reader = NOT_GIVEN Value.__init__(self, rule(), True) def get_future(self): if not ctrl.active: raise RuntimeError('future can only be accessed from a @modifier') ctrl.active lock(self) if ctrl.current_listener is not self._last_reader: if self._last_reader is NOT_GIVEN: self.value = value = self.rule() changed(self) else: value = self._copy(self._value) change_attr(self, '_value', value) change_attr(self, '_last_reader', ctrl.current_listener) return self._value def _finish(self): change_attr(self, '_last_reader', NOT_GIVEN) super(TodoValue, self)._finish() class Pipe(Component): output = todo(list, name = 'output') input = output.future def append(self, value): self.input.append(value) append = modifier(append) def extend(self, sequence): self.input.extend(sequence) extend = modifier(extend) def __iter__(self): return iter(self.output) def __contains__(self, value): return value in self.output def __len__(self): return len(self.output) def __repr__(self): return repr(self.output) class WeakDefaultDict(weakref.WeakValueDictionary): def __init__(self, missing): weakref.WeakValueDictionary.__init__(self) self.__missing__ = missing def __getitem__(self, key): try: return weakref.WeakValueDictionary.__getitem__(self, key) except KeyError: value = self.__missing__(key) self[key] = value return value class CacheAttr(CellAttribute): optional = True def can_connect(self): return True def factory(self, rule, value, discrete): conn = rule.connect disc = rule.disconnect rule = rule.read def make_cell(key): r = new.instancemethod(rule, key, type(key)) return None(None(((Sensor, Connector), (lambda s: conn(key))), (lambda s, m: disc(key)), r), value, discrete) return Constant(WeakDefaultDict(make_cell)) def cellcache(rule = None, make = None, initially = NO_VALUE, resetting_to = NO_VALUE, name = None): return _build_descriptor(rule = rule, initially = initially, resetting_to = resetting_to, make = make, __proptype = CacheAttr.mkattr, __name = name) class Dict(UserDict.IterableUserDict, Component): added = todo(dict, name = 'added') deleted = todo(dict, name = 'deleted') changed = todo(dict, name = 'changed') to_add = added.future to_change = changed.future to_delete = deleted.future def __init__(self, other = (), **kw): Component.__init__(self) if other: self.data.update(other) if kw: self.data.update(kw) def copy(self): return self.__class__(self.data) def get(self, key, failobj = None): return self.data.get(key, failobj) def __hash__(self): raise TypeError def data(self): data = self.data pop = data.pop if self.added: for key in self.added: on_undo(pop, key, None) mark_dirty() data.update(self.added) if self.changed: mark_dirty() data.update(self.changed) return data data = maintain(data, make = dict, name = 'data') def __setitem__(self, key, item): if key in self.to_delete: del self.to_delete[key] if key in self.data: self.to_change[key] = item else: self.to_add[key] = item __setitem__ = modifier(__setitem__) def __delitem__(self, key): if key in self.to_add: del self.to_add[key] elif key in self.data and key not in self.to_delete: self.to_delete[key] = self.data[key] if key in self.to_change: del self.to_change[key] else: raise KeyError, key return key not in self.to_delete __delitem__ = modifier(__delitem__) def clear(self): self.to_add.clear() self.to_change.clear() self.to_delete.update(self.data) clear = modifier(clear) def update(self, d = (), **kw): if d: if kw: d = dict(d) d.update(kw) elif not hasattr(d, 'iteritems'): d = dict(d) else: d = kw to_change = self.to_change to_add = self.to_add to_delete = self.to_delete data = self.data for k, v in d.iteritems(): if k in to_delete: del to_delete[k] if k in data: to_change[k] = d[k] continue to_add[k] = d[k] update = modifier(update) def setdefault(self, key, failobj = None): raise InputConflict("Can't read and write in the same operation") def pop(self, key, *args): raise InputConflict("Can't read and write in the same operation") def popitem(self): raise InputConflict("Can't read and write in the same operation") class List(UserList.UserList, Component): updated = todo((lambda self: self.data[:]), name = 'updated') future = updated.future changed = todo(bool, name = 'changed') def __init__(self, other = (), **kw): Component.__init__(self, **kw) self.data[:] = other def data(self): if self.changed: mark_dirty() return self.updated return self.data data = maintain(data, make = list, name = 'data') def __setitem__(self, i, item): self.changed = True self.future[i] = item __setitem__ = modifier(__setitem__) def __delitem__(self, i): self.changed = True del self.future[i] __delitem__ = modifier(__delitem__) def __setslice__(self, i, j, other): self.changed = True self.future[i:j] = other __setslice__ = modifier(__setslice__) def __delslice__(self, i, j): self.changed = True del self.future[i:j] __delslice__ = modifier(__delslice__) def __iadd__(self, other): self.changed = True self.future.extend(other) return self __iadd__ = modifier(__iadd__) def append(self, item): self.changed = True self.future.append(item) append = modifier(append) def insert(self, i, item): self.changed = True self.future.insert(i, item) insert = modifier(insert) def extend(self, other): self.changed = True self.future.extend(other) extend = modifier(extend) def __imul__(self, n): self.changed = True self.future[:] = self.future * n return self __imul__ = modifier(__imul__) def remove(self, item): self.changed = True self.future.remove(item) remove = modifier(remove) def reverse(self): self.changed = True self.future.reverse() reverse = modifier(reverse) def sort(self, *args, **kw): self.changed = True self.future.sort(*args, **kw) sort = modifier(sort) def pop(self, i = -1): raise InputConflict("Can't read and write in the same operation") def __hash__(self): raise TypeError class Set(sets.Set, Component): _added = todo(set, name = '_added') _removed = todo(set, name = '_removed') added = _added removed = _removed to_add = _added.future to_remove = _removed.future def __init__(self, iterable = None, **kw): Component.__init__(self, **kw) if iterable is not None: sets.Set._update(self, iterable) def _data(self): data = self._data pop = data.pop if self.removed: mark_dirty() for item in self.removed: pop(item, None) on_undo(data.update, dict.fromkeys(self.removed, True)) if self.added: mark_dirty() data.update(dict.fromkeys(self.added, True)) for item in self.added: on_undo(pop, item, None) return data _data = maintain(_data, make = dict, name = '_data') def __setstate__(self, data): self.__init__(data[0]) def _binary_sanity_check(self, other): if not isinstance(other, set_like): raise TypeError, 'Binary operation only permitted between sets' isinstance(other, set_like) def pop(self): raise InputConflict("Can't read and write in the same operation") def _update(self, iterable): to_remove = self.to_remove add = self.to_add.add for item in iterable: if item in to_remove: to_remove.remove(item) continue add(item) _update = modifier(_update) def add(self, item): if item in self.to_remove: self.to_remove.remove(item) elif item not in self._data: self.to_add.add(item) add = modifier(add) def remove(self, item): if item in self.to_add: self.to_add.remove(item) elif item in self._data and item not in self.to_remove: self.to_remove.add(item) else: raise KeyError(item) return item not in self.to_remove remove = modifier(remove) def clear(self): self.to_remove.update(self) self.to_add.clear() clear = modifier(clear) def __ior__(self, other): self._binary_sanity_check(other) self._update(other) return self def __iand__(self, other): self._binary_sanity_check(other) self.intersection_update(other) return self def difference_update(self, other): data = self._data to_add = self.to_add to_remove = self.to_remove for item in other: if item in to_add: to_add.remove(item) continue if item in data: to_remove.add(item) continue difference_update = modifier(difference_update) def intersection_update(self, other): to_remove = self.to_remove to_add = self.to_add self.to_add.intersection_update(other) other = to_dict_or_set(other) for item in self._data: if item not in other: to_remove.add(item) continue return self intersection_update = modifier(intersection_update) def symmetric_difference_update(self, other): data = self._data to_add = self.to_add to_remove = self.to_remove for elt in to_dict_or_set(other): if elt in to_add: to_add.remove(elt) continue if elt in to_remove: to_remove.remove(elt) continue if elt in data: to_remove.add(elt) continue to_add.add(elt) symmetric_difference_update = modifier(symmetric_difference_update) def to_dict_or_set(ob): if isinstance(ob, sets.BaseSet): return ob._data if not isinstance(ob, dictlike): return dict.fromkeys(ob) return ob