Esempio n. 1
0
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))
Esempio n. 2
0
    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"
Esempio n. 3
0
    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()
Esempio n. 4
0
    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
Esempio n. 5
0
 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
Esempio n. 6
0
    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
Esempio n. 7
0
 def _getPromotable(self, op):
     return adapt(op, IConditional).conjuncts()
Esempio n. 8
0
 def __init__(self, formula, *values):
     self._formula = formula
     super(DerivedValue, self).__init__()
     subscribe(AnyOf(*[adapt(v, IValue) for v in values]), self._set)  #
Esempio n. 9
0
 def CALL(self, iterator):
     self.stack.append(adapt(iterator, IProcedure))