'Cell', 'Constant', 'rule', 'rules', 'value', 'values', 'optional', |
'Cell', 'Constant', 'rule', 'rules', 'value', 'values', 'optional', |
'todo', 'todos', 'modifier', 'receiver', 'receivers', 'Component', |
'todo', 'todos', 'modifier', 'receiver', 'receivers', 'Component', |
'discrete', 'repeat', 'poll', 'InputConflict', 'observer', 'ObserverCell', |
'discrete', 'repeat', 'poll', 'InputConflict', 'observer', 'ObserverCell', |
'Dict', 'List', 'Set', 'mark_dirty', 'ctrl', |
'Dict', 'List', 'Set', 'mark_dirty', 'ctrl', 'ConstantMixin' |
] |
] |
|
|
NO_VALUE = symbols.Symbol('NO_VALUE', __name__) |
NO_VALUE = symbols.Symbol('NO_VALUE', __name__) |
for name in [ |
for name in [ |
'on_commit', 'on_undo', 'atomically', 'manage', 'savepoint', |
'on_commit', 'on_undo', 'atomically', 'manage', 'savepoint', |
'rollback_to', 'schedule', 'cancel', 'lock', 'used', 'changed', |
'rollback_to', 'schedule', 'cancel', 'lock', 'used', 'changed', |
'run_rule', 'change_attr', |
'initialize', 'change_attr', |
]: |
]: |
globals()[name] = getattr(ctrl, name) |
globals()[name] = getattr(ctrl, name) |
if name not in __all__: __all__.append(name) |
if name not in __all__: __all__.append(name) |
atomically(schedule, self) |
atomically(schedule, self) |
return self._value |
return self._value |
else: |
else: |
cancel(self); run_rule(self, False) |
cancel(self); initialize(self) |
if ctrl.current_listener is not None: |
if ctrl.current_listener is not None: |
used(self) |
used(self) |
return self._value |
return self._value |
change_attr(self, '__class__', ConstantRule) |
change_attr(self, '__class__', ConstantRule) |
|
|
|
|
class _ConstantMixin(AbstractCell): |
class ConstantMixin(AbstractCell): |
"""A read-only abstract cell""" |
"""A read-only abstract cell""" |
|
|
__slots__ = () |
__slots__ = () |
|
|
def __setattr__(self, name, value): |
def __setattr__(self, name, value): |
"""Constants can't be changed""" |
"""Constants can't be changed""" |
|
if name == '__class__': |
|
object.__setattr__(self, name, value) |
|
else: |
raise AttributeError("Constants can't be changed") |
raise AttributeError("Constants can't be changed") |
|
|
def __repr__(self): |
def __repr__(self): |
return "Constant(%r)" % (self.value,) |
return "Constant(%r)" % (self.value,) |
|
|
|
|
class Constant(_ConstantMixin): |
class Constant(ConstantMixin): |
"""A pure read-only value""" |
"""A pure read-only value""" |
|
|
__slots__ = 'value' |
__slots__ = 'value' |
|
|
|
|
|
|
|
class ConstantRule(ConstantMixin, ReadOnlyCell): |
|
|
|
|
class ConstantRule(_ConstantMixin, ReadOnlyCell): |
|
"""A read-only cell that no longer depends on anything else""" |
"""A read-only cell that no longer depends on anything else""" |
|
|
__slots__ = () |
__slots__ = () |
def run(self): |
def run(self): |
"""Constants don't run""" |
"""Constants don't run""" |
|
|
def __setattr__(self, name, value): |
|
"""Constants can't be changed""" |
|
if name == '__class__': |
|
object.__setattr__(self, name, value) |
|
else: |
|
super(ConstantRule, self).__setattr__(name, value) |
|
|
|
|
|
class ObserverCell(stm.AbstractListener, AbstractCell): |
class ObserverCell(stm.AbstractListener, AbstractCell): |
"""Rule that performs non-undoable actions""" |
"""Rule that performs non-undoable actions""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Cell(ReadOnlyCell, Value): |
class Cell(ReadOnlyCell, Value): |
"""Spreadsheet-like cell with automatic updating""" |
"""Spreadsheet-like cell with automatic updating""" |
|
|
return self._value |
return self._value |
if self._set_by is _sentinel: |
if self._set_by is _sentinel: |
# No value set yet, so we have to run() first |
# No value set yet, so we have to run() first |
cancel(self); run_rule(self, False) |
cancel(self); initialize(self) |
if ctrl.current_listener is not None: |
if ctrl.current_listener is not None: |
used(self) |
used(self) |
return self._value |
return self._value |
except AttributeError: cells = Cells(ob) |
except AttributeError: cells = Cells(ob) |
if isinstance(value, AbstractCell): |
if isinstance(value, AbstractCell): |
name = self.__name__ |
name = self.__name__ |
if name in cells and isinstance(cells[name], _ConstantMixin): |
if name in cells and isinstance(cells[name], ConstantMixin): |
raise AttributeError("Can't change a constant") |
raise AttributeError("Can't change a constant") |
cells[name] = value |
cells[name] = value |
else: |
else: |