예제 #1
0
def defer_to_thread(f, *args, **kwargs):
    """
    Run a function in a thread and return the result as a Deferred.
    @param f: The function to call.
    @param *args: positional arguments to pass to f.
    @param **kwargs: keyword arguments to pass to f.
    @return: A Deferred which fires a callback with the result of f,
    or an errback with a L{twisted.python.failure.Failure} if f throws
    an exception.
    """
    def run_thread(df, func, *f_args, **f_kwargs):
        try:
            logger.debug("Calling function {0} in thread.".format(func))
            result = func(*f_args, **f_kwargs)
            logger.debug(
                "Thread deferred function returned {0}".format(result))
            df.callback(result)
        except Exception as e:
            logger.error("Got error in thread: {0}".format(e))
            df.errback(e)

    logger.info("Deferring function {0} to thread.".format(f))
    if "canceller" in kwargs:
        d = defer.Deferred(kwargs["canceller"])
    else:
        d = defer.Deferred()
    rt_args = (d, f) + args
    t = threading.Thread(target=run_thread, args=rt_args, kwargs=kwargs)
    t.start()
    return d
예제 #2
0
    def start(self, interval, now=True):
        """
        Start running function every interval seconds.
        @param interval: The number of seconds between calls.  May be
        less than one.  Precision will depend on the underlying
        platform, the available hardware, and the load on the system.
        @param now: If True, run this call right now.  Otherwise, wait
        until the interval has elapsed before beginning.
        @return: A Deferred whose callback will be invoked with
        C{self} when C{self.stop} is called, or whose errback will be
        invoked when the function raises an exception or returned a
        deferred that has its errback invoked.
        """
        if self.running is True:
            self.stop()

        self.logger.debug(
            "Starting looping call at interval {0} s".format(interval))
        if interval < 0:
            raise ValueError("interval must be >= 0")
        self.running = True
        # Loop might fail to start and then self._deferred will be cleared.
        # This why the local C{deferred} variable is used.
        deferred = self._deferred = defer.Deferred()
        self.starttime = time.time()
        self.interval = interval
        self._runAtStart = now
        if now:
            self()
        else:
            self._schedule_from(self.starttime)
        return deferred
예제 #3
0
 def defer_to_queue(self, f, *args, **kwargs):
     print("Defer to queue: {0}. Args: {1}, kwargs: {2}".format(f, args, kwargs))
     d = defer.Deferred(canceller=self.cancel_queue_cmd_from_deferred)
     cmd = d
     d.addCallback(self.queue_cb, f, *args, **kwargs)
     with self.lock:
         self.q.put(cmd)
     return d
예제 #4
0
    def write_parameter(self, name, value, process_now=True, readback=True):
        """
        Write a single named parameter to the Patara. If readback is True the same parameter is scheduled
        to be read after the write. The retured deferred fires when the result is ready.

        :param name: Name of the parameter according the eDrive User Manual
        :param value: Value to write
        :param process_now: True if the queue should be processes immediately
        :param readback: True if the value should be read back from the Patara
        :return: Deferred that fires when the result is ready
        """
        p = self.get_parameter(name)
        if p is None:
            err = "Name {0} not in parameter dictionary".format(name)
            self.logger.error(err)
            d = defer.Deferred()
            fail = failure.Failure(AttributeError(err))
            d.errback(fail)
            return d
        addr = p.get_address()
        func = p.get_function_code()
        (factor, offset) = p.get_conversion()
        w_val = np.uint16((value - offset) / factor)
        self.logger.info(
            "Writing to {0}. Addr: {1}, func {2}, value {3}".format(
                name, addr, func, w_val))
        if func == 1:
            f = self.client.write_coil
        elif func == 3:
            f = self.client.write_register
        else:
            err = "Wrong function code {0}, should be 1, or 3".format(func)
            self.logger.error(err)
            d = defer.Deferred()
            fail = failure.Failure(AttributeError(err))
            d.errback(fail)
            return d

        d = self.defer_to_queue(f, addr, w_val, unit=self.slave_id)
        # d = defer.Deferred()
        d.addErrback(self.client_error)
        if readback is True:
            d = self.read_parameter(name, process_now)
        if process_now is True:
            self.process_queue()
        return d
예제 #5
0
 def add_task(self, f, *args, **kwargs):
     d = defer.Deferred()
     self.logger.debug("Putting task in queue. Args: {0}".format(args))
     with self.id_lock:
         id = self.next_process_id
         self.next_process_id += 1
     self.in_queue.put((f, args, kwargs, id))
     self.deferred_dict[id] = d
     return d
예제 #6
0
    def read_parameter(self, name, process_now=True):
        """
        Read a single named parameter from the Patara and store the result in the parameter
        dictionary. The retured deferred fires when the result is ready.

        :param name: Name of the parameter according the eDrive User Manual
        :param process_now: True if the queue should be processes immediately
        :return: Deferred that fires when the result is ready
        """
        p = self.get_parameter(name)
        if p is None:
            err = "Name {0} not in parameter dictionary".format(name)
            self.logger.error(err)
            d = defer.Deferred()
            fail = failure.Failure(AttributeError(err))
            d.errback(fail)
            return d
        addr = p.get_address()
        func = p.get_function_code()
        self.logger.debug("Reading {0}. Addr: {1}, func {2}".format(
            name, addr, func))
        if func == 1:
            f = self.client.read_coils
        elif func == 2:
            f = self.client.read_discrete_inputs
        elif func == 3:
            f = self.client.read_holding_registers
        elif func == 4:
            f = self.client.read_input_registers
        else:
            err = "Wrong function code {0}, should be 1, 2, 3, or 4".format(
                func)
            self.logger.error(err)
            d = defer.Deferred()
            fail = failure.Failure(AttributeError(err))
            d.errback(fail)
            return d

        d = self.defer_to_queue(f, addr, 1, unit=self.slave_id)
        d.addCallback(self.process_parameters, min_addr=addr)
        d.addErrback(self.client_error)
        if process_now is True:
            self.process_queue()
        return d
예제 #7
0
def defer_later(delay, delayed_callable, *a, **kw):
    # logger.info("Calling {0} in {1} seconds".format(delayed_callable, delay))

    def defer_later_cancel(deferred):
        delayed_call.cancel()

    d = defer.Deferred(defer_later_cancel)
    d.addCallback(lambda ignored: delayed_callable(*a, **kw))
    delayed_call = threading.Timer(delay, d.callback, [None])
    delayed_call.start()
    return d
예제 #8
0
 def cb(result):
     if self.running:
         self._schedule_from(time.time())
         new_loop_deferred = defer.Deferred()
         for callback in self.loop_deferred.callbacks:
             new_loop_deferred.callbacks.append(callback)
         self.loop_deferred.callback(result)
         self.loop_deferred = new_loop_deferred
     else:
         df, self._deferred = self._deferred, None
         df.callback(self)
예제 #9
0
 def get_attribute(self, name):
     if name in self.attribute_dict:
         self.logger.debug(
             "Attribute {0} already read. Retrieve from dictionary.".format(
                 name))
         d = defer.Deferred()
         d.callback(self.attribute_dict[name])
     else:
         self.logger.debug(
             "Attribute {0} not in dictionary, retrieve it from device".
             format(name))
         d = self.buildProtocol("read", name)
     return d
예제 #10
0
def deferred_from_future(future):
    d = defer.Deferred()

    def callback(future):
        e = future.exception()
        if e:
            d.errback(e)
            return

        d.callback(future.result())

    future.add_done_callback(callback)
    return d
예제 #11
0
    def __init__(self, loop_callable, *args, **kw):
        self.f = loop_callable
        self.args = args
        self.kw = kw
        self.running = False
        self.interval = 0.0
        self.starttime = None
        self._deferred = None
        self._runAtStart = False
        self.call = None

        self.loop_deferred = defer.Deferred()

        self.logger = logging.getLogger("TangoTwisted.LoopingCall")
        self.logger.setLevel(logging.WARNING)
예제 #12
0
 def defer_to_queue(self, f, *args, **kwargs):
     self.logger.debug(
         "Deferring {0} with args {1}, kwargs {2} to queue".format(
             f, args, kwargs))
     d = defer.Deferred(canceller=self.cancel_queue_cmd_from_deferred)
     # cmd = (d, f, args, kwargs)
     # cmd = d
     # d.addCallback(f, args, kwargs)
     # with self.lock:
     #     self.command_queue.put(cmd)
     # return d
     #
     d.addCallback(self.queue_cb, f, *args, **kwargs)
     with self.lock:
         self.command_queue.put(d)
     return d
예제 #13
0
def defer_to_pool(pool, f, *args, **kwargs):
    df = defer.Deferred()

    def pool_callback(result):
        if isinstance(result, Exception):
            df.errback(result)
        else:
            df.callback(result)

    logger.info("Deferring function {0} to process pool.".format(f))
    args_wrapper = (f, ) + args
    pool.apply_async(f_wrapper,
                     args=args_wrapper,
                     kwds=kwargs,
                     callback=pool_callback)
    # pool.apply_async(f, args=args, kwds=kwargs, callback=pool_callback)
    return df
예제 #14
0
    def start(self, interval, timeout=None):
        if self.running is True:
            self.stop()

        self.logger.debug("Starting checking condition {0}".format(
            self.condition))
        if interval < 0:
            raise ValueError("interval must be >= 0")
        self.running = True
        # Loop might fail to start and then self._deferred will be cleared.
        # This why the local C{deferred} variable is used.
        deferred = self._deferred = defer.Deferred()
        if timeout is not None:
            self.clock = ClockReactorless()
            deferred.addTimeout(timeout, self.clock)
            deferred.addErrback(self.cond_error)
        self.starttime = time.time()
        self.interval = interval
        self._run_callable()
        return deferred
예제 #15
0
def defer_to_thread(f, *args, **kwargs):
    """
    Run a function in a thread and return the result as a Deferred.
    @param f: The function to call.
    @param *args: positional arguments to pass to f.
    @param **kwargs: keyword arguments to pass to f.
    @return: A Deferred which fires a callback with the result of f,
    or an errback with a L{twisted.python.failure.Failure} if f throws
    an exception.
    """
    def run_thread(df, func, *f_args, **f_kwargs):
        print("Run thread {0}. Args: {1}, kwargs: {2}".format(func, f_args, f_kwargs))
        try:
            result = func(*f_args, **f_kwargs)
            df.callback(result)
        except Exception as e:
            df.errback(e)

    print("Defer to thread: {0}. Args: {1}, kwargs: {2}".format(f, args, kwargs))
    d = defer.Deferred()
    rt_args = (d, f) + args
    t = threading.Thread(target=run_thread, args=rt_args, kwargs=kwargs)
    t.start()
    return d
예제 #16
0
    def check_attribute(self):
        """
        Check an attribute to see if it reaches a target value. Returns a deferred for the result of the
        check.
        Upon calling the function the target is written to the attribute if the "write" parameter is True.
        Then reading the attribute is polled with the period "period" for a maximum time of "timeout".
        If the read value is within tolerance, the callback deferred is fired.
        If the read value is outside tolerance after "timeout" time, the errback is fired.
        The maximum time to check is "timeout"

        :param attr_name: Tango name of the attribute to check, e.g. "position"
        :param dev_name: Tango device name to use, e.g. "gunlaser/motors/zaber01"
        :param target_value: Attribute value to wait for
        :param period: Polling period when checking the value
        :param timeout: Time to wait for the attribute to reach target value
        :param tolerance: Absolute tolerance for the value to be accepted
        :param write: Set to True if the target value should be written initially
        :return: Deferred that will fire depending on the result of the check
        """
        self.logger.info("Entering check_attribute")
        self.d = defer.Deferred()

        try:
            write = self.kw["write"]
        except KeyError:
            write = True
        try:
            self._check_timeout = self.kw["timeout"]
        except KeyError:
            self.logger.debug("No timeout specified, using 1.0 s")
            self._check_timeout = 1.0
        try:
            self._check_tolerance = self.kw["tolerance"]
        except KeyError:
            self._check_tolerance = None
            self.logger.debug("No tolerance specified, using None")
        try:
            self._check_period = self.kw["period"]
        except KeyError:
            self._check_period = 0.3
            self.logger.debug("No period specified, using 0.3 s")
        try:
            self._check_target_value = self.kw["target_value"]
        except KeyError:
            self._check_target_value = None
            self.logger.error("No target value specified")
            self.d.errback("Target value required")
            return self.d

        self._check_starttime = time.time()
        self._check_lastreadtime = self._check_starttime
        self._check_timeout_deferred = defer_later(
            self._check_timeout, self.d.errback,
            RuntimeError("Check {0} timeout".format(self.name)))

        if write is True:
            self.logger.debug("Issuing initial write")
            dw = deferred_from_future(
                self.factory.device.write_attribute(self.name,
                                                    self._check_target_value,
                                                    wait=False))
            # Add a callback that starts the reading after write completes
            dw.addCallbacks(self._check_do_read, self._check_fail)
        else:
            self.logger.debug("Issuing initial read")
            dw = deferred_from_future(
                self.factory.device.read_attribute(self.name, wait=False))
            dw.addCallbacks(self._check_read_done, self._check_fail)

        # Return the deferred that will fire with the result of the check
        return self.d