class Value(Writable): """Broadcast changes in a variable to all observers 'events.Value()' instances implement a near-trivial version of the 'Observer' pattern: callbacks can be informed that a change has been made to the 'Value'. Example:: aValue = events.Value(42) assert aValue()==42 aValue.set(78) # fires any registered callbacks aValue.set(78) # doesn't fire, value hasn't changed aValue.set(78,force=True) # force firing even though value's the same Events are broadcast to all callbacks, whether they "accept" or "reject" the event, and tasks yielding to a 'Value' are suspended until the next event is broadcast. The current value of the 'Value' is supplied to callbacks and tasks via the 'event' parameter, and the 'Value' itself is supplied as the 'source'. (See 'events.IEventSink'.) """ __slots__ = () protocols.advise(instancesProvide=[IValue]) defaultValue = NOT_GIVEN def __init__(self, value=NOT_GIVEN): if value is NOT_GIVEN: value = self.defaultValue self._value = value super(Value, self).__init__() isTrue = property(lambda self: adapt(self, IConditional)) isFalse = property(lambda self: ~adapt(self, IConditional))
def __new__(klass, *sources): if sources: # Flatten sources srclist = [] for src in adapt(sources, protocols.sequenceOf(IEventSource)): if isinstance(src, AnyOf): srclist.extend(src._sources) else: srclist.append(src) # Eliminate duplicates srcids = {} sources = tuple([ src for src in srclist if src not in srcids and srcids.setdefault(src, True) ]) # Return the result if len(sources) == 1: return adapt(sources[0], IEventSource) else: self = object.__new__(klass) self._sources = sources return self raise ValueError, "AnyOf must be called with one or more IEventSources"
def runUntil(self, eventSource, suppressErrors=False, idle=sleep): running = [True] exit = [] tick = self.tick time_available = self.time_available adapt(eventSource, IEventSource).addCallback( lambda s, e: [running.pop(), exit.append(e)]) if suppressErrors: def tick(exit, doTick=tick): try: doTick(exit) except: self.log.exception("Unexpected error in event loop:") while running: tick(exit) if running: delay = time_available() if delay is None: raise StopIteration("Nothing scheduled to execute") if delay > 0: idle(delay) return exit.pop()
def __init__(self, iterator, eventSource, errorType=Interruption): """'Interrupt(iterator,eventSource,errorType=Interruption)' Wrap execution of 'iterator' so that it will raise 'errorType' if 'eventSource' fires before 'iterator' exits (or aborts), assuming that the 'Interrupt' is yielded to a task.""" self.iterator = adapt(iterator, IProcedure) self.source = adapt(eventSource, IEventSource) self.errorType = errorType
def __init__(self, baseCondition): baseCondition = adapt(baseCondition, IConditional) self.baseCondition = baseCondition super(Not, self).__init__( lambda: not baseCondition.value(), baseCondition, ) self.cmpval = self.__class__, baseCondition
def step(self, source=None, event=NOT_GIVEN): """See 'events.ITask.step'""" state = self._state state.YIELD(event) while state.stack: switch = event = None # avoid holding previous references try: for event in state.stack[-1]: state.CATCH() break else: state.RETURN() # No switch; topmost iterator is finished! state.YIELD(NOT_GIVEN) # don't return a value state.CATCH() continue # resume the next iterator down, or exit except: # Remove the current iterator, since it can't be resumed state.RETURN() state.THROW() if state.stack: continue # delegate the error to the next iterator else: # nobody to delegate to, pass the buck to our caller return self._uncaughtError() # Perform the task switch, if any try: switch = adapt(event, ITaskSwitch, None) if switch is not None: if not switch.nextAction(self, state): state.YIELD(switch) # save reference until we resume return True else: state.YIELD(event) if len(state.stack) == 1: self._fire(event) else: state.RETURN() # pass the yielded value back to caller except: state.THROW() continue # push the error back into the current iterator self.isFinished.set(True) return True
def _getPromotable(self, op): return adapt(op, IConditional).conjuncts()
def __init__(self, formula, *values): self._formula = formula super(DerivedValue, self).__init__() subscribe(AnyOf(*[adapt(v, IValue) for v in values]), self._set) #
def CALL(self, iterator): self.stack.append(adapt(iterator, IProcedure))