Exemple #1
0
    def _execute(self, transforms, *args, **kwargs):
        """Executes this request with the given output transforms.

        This is basically a copy of tornado's `_execute()` method. The only
        difference is the expected result. Tornado expects the result to be
        `None`, where we want this to be a :py:class:Model."""
        verb = self.request.method.lower()
        headers = self.request.headers
        self._transforms = transforms
        try:
            if self.request.method not in self.SUPPORTED_METHODS:
                raise HTTPError(405)
            self.path_args = [self.decode_argument(arg) for arg in args]
            self.path_kwargs = dict((k, self.decode_argument(v, name=k))
                                    for (k, v) in kwargs.items())
            # If XSRF cookies are turned on, reject form submissions without
            # the proper cookie
            if self.request.method not in ("GET", "HEAD", "OPTIONS") and \
                    self.application.settings.get("xsrf_cookies"):
                self.check_xsrf_cookie()

            result = self.prepare()
            if is_future(result):
                result = yield result
            if result is not None:
                raise TypeError("Expected None, got %r" % result)
            if self._prepared_future is not None:
                # Tell the Application we've finished with prepare()
                # and are ready for the body to arrive.
                self._prepared_future.set_result(None)
            if self._finished:
                return

            if _has_stream_request_body(self.__class__):
                # In streaming mode request.body is a Future that signals
                # the body has been completely received.  The Future has no
                # result; the data has been passed to self.data_received
                # instead.
                try:
                    yield self.request.body
                except iostream.StreamClosedError:
                    return

            method = getattr(self, self.request.method.lower())
            result = method(*self.path_args, **self.path_kwargs)
            if is_future(result):
                result = yield result
            if result is not None:
                self._provide_result(verb, headers, result)
            if self._auto_finish and not self._finished:
                self.finish()
        except Exception as e:
            self._handle_request_exception(e)
            if (self._prepared_future is not None and
                    not self._prepared_future.done()):
                # In case we failed before setting _prepared_future, do it
                # now (to unblock the HTTP server).  Note that this is not
                # in a finally block to avoid GC issues prior to Python 3.4.
                self._prepared_future.set_result(None)
Exemple #2
0
    def handle_yield(self, yielded):
        if isinstance(yielded, list):
            if all(is_future(f) for f in yielded):
                yielded = multi_future(yielded)
            else:
                yielded = Multi(yielded)
        elif isinstance(yielded, dict):
            if all(is_future(f) for f in yielded.values()):
                yielded = multi_future(yielded)
            else:
                yielded = Multi(yielded)

        if isinstance(yielded, YieldPoint):
            self.future = TracebackFuture()
            def start_yield_point():
                try:
                    yielded.start(self)
                    if yielded.is_ready():
                        self.future.set_result(
                            yielded.get_result())
                    else:
                        self.yield_point = yielded
                except Exception:
                    self.future = TracebackFuture()
                    self.future.set_exc_info(sys.exc_info())
            if self.stack_context_deactivate is None:
                # Start a stack context if this is the first
                # YieldPoint we've seen.
                with stack_context.ExceptionStackContext(
                        self.handle_exception) as deactivate:
                    self.stack_context_deactivate = deactivate
                    def cb():
                        start_yield_point()
                        self.run()
                    self.io_loop.add_callback(cb)
                    return False
            else:
                start_yield_point()
        elif is_future(yielded):
            self.future = yielded
            if not self.future.done() or self.future is moment:
                self.io_loop.add_future(
                    self.future, lambda f: self.run())
                return False
        else:
            self.future = TracebackFuture()
            self.future.set_exception(BadYieldError(
                "yielded unknown object %r" % (yielded,)))
        return True
Exemple #3
0
    def on_channel_closed(self, channel, reply_code, reply_text):
        """Invoked by pika when RabbitMQ unexpectedly closes the channel.
        Channels are usually closed if you attempt to do something that
        violates the protocol, such as re-declare an exchange or queue with
        different parameters. In this case, we'll close the connection
        to shutdown the object.

        :param pika.channel.Channel channel: The AMQP Channel
        :param int reply_code: The AMQP reply code
        :param str reply_text: The AMQP reply text

        """
        LOGGER.warning('Channel %i closed: (%s) %s',
                       channel.channel_number, reply_code, reply_text)
        self.statsd_incr('amqp.channel_closed')
        if concurrent.is_future(self.event_processed):
            self.set_state(self.STATE_RECONNECTING)

            def on_open(new_channel):
                self.on_channel_open(new_channel)
                self.set_state(self.STATE_PROCESSING)
                exc = EventError(self.current_event, reply_text)
                self.event_processed.set_exception(exc)

            return self.connection.channel(on_open)

        del self.channel
        self.on_ready_to_stop()
Exemple #4
0
def maybe_future(x):
    if is_future(x):
        return x
    else:
        fut = Future()
        fut.set_result(x)
        return fut
Exemple #5
0
    def add_future(
        self,
        future: "Union[Future[_T], concurrent.futures.Future[_T]]",
        callback: Callable[["Future[_T]"], None],
    ) -> None:
        """Schedules a callback on the ``IOLoop`` when the given
        `.Future` is finished.

        The callback is invoked with one argument, the
        `.Future`.

        This method only accepts `.Future` objects and not other
        awaitables (unlike most of Tornado where the two are
        interchangeable).
        """
        if isinstance(future, Future):
            # Note that we specifically do not want the inline behavior of
            # tornado.concurrent.future_add_done_callback. We always want
            # this callback scheduled on the next IOLoop iteration (which
            # asyncio.Future always does).
            #
            # Wrap the callback in self._run_callback so we control
            # the error logging (i.e. it goes to tornado.log.app_log
            # instead of asyncio's log).
            future.add_done_callback(
                lambda f: self._run_callback(functools.partial(callback, future))
            )
        else:
            assert is_future(future)
            # For concurrent futures, we use self.add_callback, so
            # it's fine if future_add_done_callback inlines that call.
            future_add_done_callback(
                future, lambda f: self.add_callback(callback, future)
            )
Exemple #6
0
 def on_message(self, message):
     try:
         message = json.loads(message)
         dev = message["dev"]
         circuit = message["circuit"]
         try:
             value = message["value"]
         except:
             value = None
         try:
             cmd = message["cmd"]
         except:
             cmd = "set"
         try:
             device = Devices.by_name(dev, circuit)
             # result = device.set(value)
             func = getattr(device, cmd)
             if value is not None:
                 result = func(value)
             else:
                 result = func()
             if is_future(result):
                 result = yield result
             print result
         except Exception, E:
             print E
     except:
         print "Skipping WS message: " + message
         # skip it since we do not understand this message....
         pass
Exemple #7
0
    def refresh(self):
        """Load dynamic credentials from the AWS Instance Metadata and user
        data HTTP API.

        :raises: tornado_aws.exceptions.NoCredentialsError

        """
        LOGGER.debug('Refreshing EC2 IAM Credentials')
        async = isinstance(self._client, httpclient.AsyncHTTPClient)
        future = concurrent.TracebackFuture() if async else None
        try:
            result = self._fetch_credentials(async)
            if concurrent.is_future(result):

                def on_complete(response):
                    exception = response.exception()
                    if exception:
                        if isinstance(exception, httpclient.HTTPError) and \
                                exception.code == 599:
                            future.set_exception(
                                exceptions.NoCredentialsError())
                        else:
                            future.set_exception(exception)
                        return
                    self._assign_credentials(response.result())
                    future.set_result(True)

                self._ioloop.add_future(result, on_complete)
            else:
                self._assign_credentials(result)
        except (httpclient.HTTPError,
                OSError) as error:
            LOGGER.error('Error Fetching Credentials: %s', error)
            raise exceptions.NoCredentialsError()
        return future
Exemple #8
0
    def new_fn(self, *args, **kwargs):
        result = fn(self, *args, **kwargs)
        if not is_future(result):
            # If the function doesn't return a future, its exeption or result
            # is available to the caller right away. No need to switch control
            # with greenlets.
            return result

        current = greenlet.getcurrent()
        assert current.parent is not None, "TornadoAction can only be used from inside a child greenlet."

        def callback(future):
            if future.exception():
                self.io_loop.add_callback(current.throw, *future.exc_info())
            else:
                self.io_loop.add_callback(current.switch, future.result())

        # Otherwise, switch to parent and schedule to switch back when the
        # result is available.

        # A note about add_done_callback: It executes the callback right away
        # if the future has already finished executing. That's a problem
        # because we don't want the greenlet switch back to current to happen
        # until we've switched to parent first. So, io_loop.add_callback is
        # used to schedule the future callback. This ensures that we switch to
        # parent first.
        self.io_loop.add_callback(result.add_done_callback, callback)
        return current.parent.switch()
Exemple #9
0
def convert_yielded(yielded):
    """Convert a yielded object into a `.Future`.

    The default implementation accepts lists, dictionaries, and Futures.

    If the `~functools.singledispatch` library is available, this function
    may be extended to support additional types. For example::

        @convert_yielded.register(asyncio.Future)
        def _(asyncio_future):
            return tornado.platform.asyncio.to_tornado_future(asyncio_future)

    .. versionadded:: 4.1
    """
    # Lists and dicts containing YieldPoints were handled earlier.
    if yielded is None:
        return moment
    elif isinstance(yielded, (list, dict)):
        return multi(yielded)
    elif is_future(yielded):
        return yielded
    elif isawaitable(yielded):
        return _wrap_awaitable(yielded)
    else:
        raise BadYieldError("yielded unknown object %r" % (yielded,))
Exemple #10
0
    def stop(self, io_loop):
        """
        Asynchronously stop the application.

        :param tornado.ioloop.IOLoop io_loop: loop to run until all
            callbacks, timeouts, and queued calls are complete

        Call this method to start the application shutdown process.
        The IOLoop will be stopped once the application is completely
        shut down.

        """
        running_async = False
        shutdown = _ShutdownHandler(io_loop)
        for callback in self.on_shutdown_callbacks:
            try:
                maybe_future = callback(self.tornado_application)

                if asyncio.iscoroutine(maybe_future):
                    maybe_future = asyncio.create_task(maybe_future)

                if concurrent.is_future(maybe_future):
                    shutdown.add_future(maybe_future)
                    running_async = True
            except Exception as error:
                self.logger.warning('exception raised from shutdown '
                                    'callback %r, ignored: %s',
                                    callback, error, exc_info=1)

        if not running_async:
            shutdown.on_shutdown_ready()
Exemple #11
0
    def handle_request(self, topic, message):
        if topic == self.subtopic:
            # event from proxy received
            try:
                data = etree.fromstring(message, PluginRegistry.getEventParser())
                event_type = stripNs(data.xpath('/g:Event/*', namespaces={'g': "http://www.gonicus.de/Events"})[0].tag)
                if event_type == "ClientLeave":
                    proxy_id = str(data.ClientLeave.Id)
                    registry = PluginRegistry.getInstance("BackendRegistry")
                    registry.unregisterBackend(proxy_id)

            except etree.XMLSyntaxError as e:
                self.log.error("Event parsing error: %s" % e)

        elif topic.startswith(self.subtopic):
            response_topic = "%s/response" % "/".join(topic.split("/")[0:4])

            try:
                id_, res = self.process(topic, message)
                if is_future(res):
                    res = yield res
                response = dumps({"result": res, "id": id_})
                self.log.debug("MQTT-RPC response: %s on topic %s" % (response, topic))

            except Exception as e:
                err = str(e)
                self.log.error("MQTT RPC call error: %s" % err)
                response = dumps({'id': topic.split("/")[-2], 'error': err})

            # Get rid of it...
            self.mqtt.send_message(response, topic=response_topic, qos=2)

        else:
            self.log.warning("unhandled topic request received: %s" % topic)
Exemple #12
0
    def handle(self, endpoint, *args, **kwargs):
        """
        almost identical to Resource.handle, except
        the way we handle the return value of view_method.
        """
        method = self.request_method()

        try:
            if not method in self.http_methods.get(endpoint, {}):
                raise MethodNotImplemented(
                    "Unsupported method '{0}' for {1} endpoint.".format(
                        method,
                        endpoint
                    )
                )

            if not self.is_authenticated():
                raise Unauthorized()

            self.data = self.deserialize(method, endpoint, self.request_body())
            view_method = getattr(self, self.http_methods[endpoint][method])
            data = view_method(*args, **kwargs)
            if is_future(data):
                # need to check if the view_method is a generator or not
                data = yield data
            serialized = self.serialize(method, endpoint, data)
        except Exception as err:
            raise gen.Return(self.handle_error(err))

        status = self.status_map.get(self.http_methods[endpoint][method], OK)
        raise gen.Return(self.build_response(serialized, status=status))
Exemple #13
0
def convert_yielded(yielded: _Yieldable) -> Future:
    """Convert a yielded object into a `.Future`.

    The default implementation accepts lists, dictionaries, and Futures.

    If the `~functools.singledispatch` library is available, this function
    may be extended to support additional types. For example::

        @convert_yielded.register(asyncio.Future)
        def _(asyncio_future):
            return tornado.platform.asyncio.to_tornado_future(asyncio_future)

    .. versionadded:: 4.1
    """
    if yielded is None or yielded is moment:
        return moment
    elif yielded is _null_future:
        return _null_future
    elif isinstance(yielded, (list, dict)):
        return multi(yielded)  # type: ignore
    elif is_future(yielded):
        return typing.cast(Future, yielded)
    elif isawaitable(yielded):
        return _wrap_awaitable(yielded)  # type: ignore
    else:
        raise BadYieldError("yielded unknown object %r" % (yielded,))
 def on_message(self, message):
     ''' handle an rpc calls '''
     data = json_decode(message)
     for id_, action, kwargs in data.get("requests"):
         context = self.micro_context(
             self._client_id, id_, action, self._cookies_, self)
         try:
             LOGGER.info(
                 "%s %s %s %r", id(self),
                 context.action_id,
                 context.action,
                 kwargs)
             service = self.settings["services"].get(context.action)
             if service is None:
                 raise Exception("No such service {}".format(context.action))
             result = service.perform(context, ** kwargs)
             if concurrent.is_future(result):
                 result.add_done_callback(
                     functools.partial(self.handle_future,
                                       service,
                                       context,
                                       False))
             else:
                 self.handle_result(service, context, result)
         except Exception as ex:
             self.write_err(context, ex)
 def _run_callback(self, callback):
     try:
         ret = callback()
         if ret is not None and is_future(ret):
             self.add_future(ret, lambda f: f.result())
     except Exception:
         self.handle_callback_exception(callback)
Exemple #16
0
    def onRecvStream(self, stream, msg):
        # If the handler triggers an exception, pyzmq will disable it
        # Here we catch any exception and just log it, so that processing
        # can continue
        try:
            cname = stream.channel_name
            self.counters[cname] += 1
            #buf_len = self.counters[cname] - self.counters[output_cname]
            #self.logger.debug('Received on %s: %d', cname, buf_len)
            handler = self.get_recv_handler(cname)
            fut = handler(msg)
            if is_future(fut):
                self.loop.add_future(fut, self.onFuture)

            output_cname = self.channels[cname].drained_by
            if output_cname:
                buf_len = self.streams[output_cname]._send_queue.qsize()
                hwm = self.channels[cname].hwm
                if buf_len >= (hwm - (hwm * 0.2)):
                    msg = "Pausing receive on: %s (Buffered: %d, HWM: %d)"
                    hwm = self.channels[cname].hwm
                    self.logger.info(msg, cname, buf_len, hwm)
                    stream.stop_on_recv()
        except Error as err:
            self.logger.exception(err)
            self.init_db()
        except Exception as err:
            self.logger.exception(err)
Exemple #17
0
            def _wrapper(self, *args, **kwargs):
                try:
                    # 因为这段代码是在 @gen.coroutine 装饰器中,
                    # 如果这段代码发生异常,没有用 except 捕获的话就无法自动调用 write_error
                    validate_success = True
                    errors = None
                    if input_schema is not None:
                        v = cerberus.Validator(input_schema)
                        # 允许提交未知的数据
                        v.allow_unknown = True
                        if not v.validate(self.post_data):
                            validate_success = False
                            errors = v.errors

                    if not validate_success:
                        logger.warning(errors)
                        # 验证失败,返回错误
                        self.fail(msg='提交的数据格式不正确')
                    else:
                        # Call the request_handler method
                        ret = func(self, *args, **kwargs)
                        if is_future(ret):
                            yield ret
                            # 如果 rh_method 用了 coroutine,并且这个函数中抛出了异常,
                            # 但是这里没有用 yield 的话,就无法捕获到异常,从而调用 write_error
                            logger.debug('yield')
                except gen.Return:
                    pass
                except Exception as e:
                    logger.debug(traceback.format_exc())
                    logger.debug(e)
                    self.write_error(GATEWAY_ERROR_STATUS_CODE, exc_info=sys.exc_info())
Exemple #18
0
    def execute_next(self, request, types, process_object, *args, **kwargs):
        midd = None

        if types == _TCALL:
            midd = ('call_midds', 'process_call',)
        elif types == _TREQ:
            midd = ('request_midds', 'process_request',)
        elif types == _TREN:
            midd = ('render_midds', 'process_render',)
        elif types == _TRES:
            midd = ('response_midds', 'process_response',)
        elif types == _TEND:
            midd = ('end_midds', 'process_endcall',)
        elif types == _TEXC:
            midd = ('exc_midds', 'process_exception',)
        if midd:
            while 1:
                method = self._get_func(request, midd[0], midd[1])
                if method and callable(method):

                    clear = partial(self.clear_all, request)
                    result = method(process_object, clear, *args, **kwargs)
                    if is_future(result):
                        result = yield result
                        if result:
                            break
                else:
                    break
Exemple #19
0
    def _do_all_execute_forasync(self, handler, clear, method_name, **kwargs):

        for c_module in self.common_modules:
            result = self._execute_module(handler, clear, c_module, getattr(c_module, method_name), **kwargs)
            if is_future(result):
                result = yield result
            if result:
                raise gen.Return(1)

        for name, r_module in self.route_modules.items():
            for md in r_module:
                result = self._execute_module(handler, clear, md, getattr(md, method_name), name, **kwargs)
                if is_future(result):
                    result = yield result
                if result:
                    raise gen.Return(1)
Exemple #20
0
def convert_yielded(yielded):
    if isinstance(yielded, (list, dict)):
        return multi_future(yielded)
    elif is_future(yielded):
        return yielded
    else:
        raise BadYieldError("yielded unknown object %r" % (yielded,))
    def prepare(self):
        maybe_future = super(SimpleHandler, self).prepare()
        if concurrent.is_future(maybe_future):
            yield maybe_future

        if 'Correlation-ID' in self.request.headers:
            self.set_metric_tag('correlation_id',
                                self.request.headers['Correlation-ID'])
Exemple #22
0
    def capture(self, fn_ret):
        """
        """

        result = fn_ret
        if is_future(result): # import is_future
            result = yield result
        return result
Exemple #23
0
        def _wrapper(self, *args, **kwargs):
            # In case the specified input_schema is ``None``, we
            #   don't json.loads the input, but just set it to ``None``
            #   instead.
            if input_schema is not None:
                # Attempt to json.loads the input
                try:
                    # TODO: Assuming UTF-8 encoding for all requests,
                    #   find a nice way of determining this from charset
                    #   in headers if provided
                    encoding = "UTF-8"
                    input_ = json.loads(self.request.body.decode(encoding))
                except ValueError as e:
                    raise jsonschema.ValidationError(
                        "Input is malformed; could not decode JSON object."
                    )
                # Validate the received input
                jsonschema.validate(
                    input_,
                    input_schema
                )
            else:
                input_ = None

            # A json.loads'd version of self.request["body"] is now available
            #   as self.body
            setattr(self, "body", input_)
            # Call the requesthandler method
            output = rh_method(self, *args, **kwargs)
            # If the rh_method returned a Future a la `raise Return(value)`
            #   we grab the output.
            if is_future(output):
                output = yield output

            if output_schema is not None:
                # We wrap output in an object before validating in case
                #  output is a string (and ergo not a validatable JSON object)
                try:
                    jsonschema.validate(
                        {"result": output},
                        {
                            "type": "object",
                            "properties": {
                                "result": output_schema
                            },
                            "required": ["result"]
                        }
                    )
                except jsonschema.ValidationError as e:
                    # We essentially re-raise this as a TypeError because
                    #  we don't want this error data passed back to the client
                    #  because it's a fault on our end. The client should
                    #  only see a 500 - Internal Server Error.
                    raise TypeError(str(e))

            # If no ValidationError has been raised up until here, we write
            #  back output
            self.success(output)
Exemple #24
0
 def run(child_gr, *args, **kwargs):
     try:
         result = func(*args, **kwargs)
         if not is_future(result):
             return child_gr.switch(result)
     except Exception as e:
         result = Future()
         result.set_exception(e)
     return ioloop.add_future(result, child_gr.switch)
Exemple #25
0
def multi_future(children, quiet_exceptions=()):
    """Wait for multiple asynchronous futures in parallel.

    This function is similar to `multi`, but does not support
    `YieldPoints <YieldPoint>`.

    .. versionadded:: 4.0

    .. versionchanged:: 4.2
       If multiple ``Futures`` fail, any exceptions after the first (which is
       raised) will be logged. Added the ``quiet_exceptions``
       argument to suppress this logging for selected exception types.

    .. deprecated:: 4.3
       Use `multi` instead.
    """
    if isinstance(children, dict):
        keys = list(children.keys())
        children = children.values()
    else:
        keys = None
    children = list(map(convert_yielded, children))
    assert all(is_future(i) for i in children)
    unfinished_children = set(children)

    future = _create_future()
    if not children:
        future_set_result_unless_cancelled(future,
                                           {} if keys is not None else [])

    def callback(f):
        unfinished_children.remove(f)
        if not unfinished_children:
            result_list = []
            for f in children:
                try:
                    result_list.append(f.result())
                except Exception as e:
                    if future.done():
                        if not isinstance(e, quiet_exceptions):
                            app_log.error("Multiple exceptions in yield list",
                                          exc_info=True)
                    else:
                        future_set_exc_info(future, sys.exc_info())
            if not future.done():
                if keys is not None:
                    future_set_result_unless_cancelled(future,
                                                       dict(zip(keys, result_list)))
                else:
                    future_set_result_unless_cancelled(future, result_list)

    listening = set()
    for f in children:
        if f not in listening:
            listening.add(f)
            future_add_done_callback(f, callback)
    return future
Exemple #26
0
    def add_future(self, future, callback):
        """Schedules a callback on the ``IOLoop`` when the given
        `.Future` is finished.

        The callback is invoked with one argument, the
        `.Future`.
        """
        assert is_future(future)
        callback = stack_context.wrap(callback)
        future.add_done_callback(lambda future: self.add_callback(callback, future))
Exemple #27
0
    def _execute(self):
        """Invoke the lifecycle methods for a message
        (prepare, process, on_finish), yielding if any are coroutines.

        """
        for call in (self.prepare, self.process, self.on_finish):
            self.logger.debug('Invoking %r', call)
            result = call()
            if concurrent.is_future(result):
                yield result
Exemple #28
0
    def execute_next_for_async(self, request, call_list, process_object, *args, **kwargs):

        while call_list and len(call_list):
            try:
                result = self._execute(request, call_list, process_object, *args, **kwargs)
                if is_future(result):
                    result = yield result
                if result:
                    break
            except NotCallableError:
                break
Exemple #29
0
    def do_call_request_method(self):
        """
        """

        method = getattr(self, self.request.method.lower())
        result = method(*self.path_args, **self.path_kwargs)
        if is_future(result):
            result = yield result
        if result is not None:
            raise TypeError("Expected None, got %r" % result)
        if self._auto_finish and not self._finished:
            self.finish()
Exemple #30
0
 def __init__(self, children):
     self.keys = None
     if isinstance(children, dict):
         self.keys = list(children.keys())
         children = children.values()
     self.children = []
     for i in children:
         if is_future(i):
             i = YieldFuture(i)
         self.children.append(i)
     assert all(isinstance(i, YieldPoint) for i in self.children)
     self.unfinished_children = set(self.children)
Exemple #31
0
    def _poll(self):
        """Infinite coroutine for draining the queue.
        """
        while True:
            try:
                incoming_msg = self._queue.get_nowait()
            except QueueEmpty:
                self.logger.debug('Source queue empty, waiting...')
                incoming_msg = yield self._queue.get()

            outgoing_msg_future = self.transducer(incoming_msg)
            if is_future(outgoing_msg_future):
                outgoing_msg = yield outgoing_msg_future
            yield self._maybe_send(outgoing_msg)
Exemple #32
0
 def patch(self, id_):
     '''
     PATCH method, see
     `spec <http://jsonapi.org/format/1.0/#crud-updating>`__.
     Decorate with :py:func:`tornado.gen.coroutine` when subclassing.
     '''
     if not id_:
         raise APIError(status.HTTP_400_BAD_REQUEST, 'Missing ID')
     data = self._get_request_data(_schemas.patchDataSchema())
     if data['id'] != id_:
         raise APIError(status.HTTP_400_BAD_REQUEST, 'ID mismatch')
     exists = self._resource.exists(id_)
     while is_future(exists):
         exists = yield exists
     if not exists:
         raise APIError(status.HTTP_404_NOT_FOUND, 'No such resource')
     res = self._get_resource(data, validate=False)
     resource = self._resource.update(id_, res)
     while is_future(resource):
         resource = yield resource
     if not resource:
         raise APIError()
     self.render(resource)
def maybe_future(x):
    """Converts ``x`` into a `.Future`.

    If ``x`` is already a `.Future`, it is simply returned; otherwise
    it is wrapped in a new `.Future`.  This is suitable for use as
    ``result = yield gen.maybe_future(f())`` when you don't know whether
    ``f()`` returns a `.Future` or not.
    """
    if is_future(x):
        return x
    else:
        fut = Future()
        fut.set_result(x)
        return fut
Exemple #34
0
    def add_future(self, future, callback):
        """Schedules a callback on the ``IOLoop`` when the given
        `.Future` is finished.

        The callback is invoked with one argument, the
        `.Future`.

        This method only accepts `.Future` objects and not other
        awaitables (unlike most of Tornado where the two are
        interchangeable).
        """
        assert is_future(future)
        future_add_done_callback(
            future, lambda future: self.add_callback(callback, future))
 def method(*args, **kwds):
     client = yield self.get_client()
     api = getattr(client, name, None)
     will_put_back = True
     try:
         if api and (callable(api) or is_future(api)):
             raise gen.Return((yield api(*args, **kwds)))
         raise AttributeError("%s not found in %s" % (name, client))
     except client.TTransportException:
         will_put_back = False
         client.close()
         raise
     finally:
         if will_put_back:
             self.put_back_connection(client)
Exemple #36
0
    def wrapper(self, *args, **kwargs):
        self._auto_finish = False
        with stack_context.ExceptionStackContext(
                self._stack_context_handle_exception):
            result = method(self, *args, **kwargs)
            if is_future(result):

                def future_complete(f):
                    f.result()
                    if not self._finished:
                        self.finish()

                IOLoop.current().add_future(result, future_complete)
                return None
            return result
Exemple #37
0
 def read(self, id_):
     with (yield self.cursor(self.connection)) as cursor:
         cur = dbapiext.execute_f(
             cursor,
             "select %s from %s where id = %X",
             self.columns + ["id"],
             self._tablename,
             id_,
         )
         if is_future(cur):
             cur = yield cur
         row = cur.fetchone()
         if not row:
             return None
         return DBAPI2Resource.ResourceObject(self, row)
Exemple #38
0
    def _run_callback(self, callback):
        """Runs a callback with error handling.

        For use in subclasses.
        """
        try:
            ret = callback()
            if ret is not None and is_future(ret):
                # Functions that return Futures typically swallow all
                # exceptions and store them in the Future.  If a Future
                # makes it out to the IOLoop, ensure its exception (if any)
                # gets logged too.
                self.add_future(ret, lambda f: f.result())
        except Exception:
            self.handle_callback_exception(callback)
Exemple #39
0
 def __init__(self, children, quiet_exceptions=()):
     self.keys = None
     if isinstance(children, dict):
         self.keys = list(children.keys())
         children = children.values()
     self.children = []
     for i in children:
         if not isinstance(i, YieldPoint):
             i = convert_yielded(i)
         if is_future(i):
             i = YieldFuture(i)
         self.children.append(i)
     assert all(isinstance(i, YieldPoint) for i in self.children)
     self.unfinished_children = set(self.children)
     self.quiet_exceptions = quiet_exceptions
Exemple #40
0
        def _(*args, **kwargs):
            self._server.handing_count += 1
            try:
                child_gr = greenlet.getcurrent()
                main = child_gr.parent
                if main is None:
                    return func(*args, **kwargs)

                ioloop.add_callback(run, child_gr, *args, **kwargs)
                result = main.switch()
                if is_future(result):
                    result = result.result()
                return result
            finally:
                self._server.handing_count -= 1
Exemple #41
0
    def on_message(self, message):
        try:
            message = json.loads(message)
            try:
                cmd = message["cmd"]
            except:
                cmd = None
            #get FULL state of each IO
            if cmd == "all":
                result = {}
                devices = [INPUT, RELAY, AI, AO, SENSOR]
                for dev in devices:
                    result += map(lambda dev: dev.full(), Devices.by_int(dev))
                self.write_message(json.dumps(result))
            #set device state
            elif cmd is not None:
                dev = message["dev"]
                circuit = message["circuit"]
                try:
                    value = message["value"]
                except:
                    value = None
                try:
                    device = Devices.by_name(dev, circuit)
                    # result = device.set(value)
                    func = getattr(device, cmd)
                    #print type(value), value
                    if value is not None:
                        if type(value) == dict:
                            result = func(**value)
                        else:
                            result = func(value)
                    else:
                        result = func()
                    if is_future(result):
                        result = yield result
                    #send response only to the client requesting full info
                    if cmd == "full":
                        self.write_message(result)
                #nebo except Exception as e:
                except Exception, E:
                    logger.error("Exc: %s", str(E))
                    #self.write_message({"error_msg":"Couldn't process this request"})

        except:
            logger.debug("Skipping WS message: %s", message)
            # skip it since we do not understand this message....
            pass
Exemple #42
0
def multi_future(children):
    """Wait for multiple asynchronous futures in parallel.

    Takes a list of ``Futures`` (but *not* other ``YieldPoints``) and returns
    a new Future that resolves when all the other Futures are done.
    If all the ``Futures`` succeeded, the returned Future's result is a list
    of their results.  If any failed, the returned Future raises the exception
    of the first one to fail.

    Instead of a list, the argument may also be a dictionary whose values are
    Futures, in which case a parallel dictionary is returned mapping the same
    keys to their results.

    It is not necessary to call `multi_future` explcitly, since the engine will
    do so automatically when the generator yields a list of `Futures`.
    This function is faster than the `Multi` `YieldPoint` because it does not
    require the creation of a stack context.

    .. versionadded:: 4.0
    """
    if isinstance(children, dict):
        keys = list(children.keys())
        children = children.values()
    else:
        keys = None
    assert all(is_future(i) for i in children)
    unfinished_children = set(children)

    future = Future()
    if not children:
        future.set_result({} if keys is not None else [])

    def callback(f):
        unfinished_children.remove(f)
        if not unfinished_children:
            try:
                result_list = [i.result() for i in children]
            except Exception:
                future.set_exc_info(sys.exc_info())
            else:
                if keys is not None:
                    future.set_result(dict(zip(keys, result_list)))
                else:
                    future.set_result(result_list)

    for f in children:
        f.add_done_callback(callback)
    return future
Exemple #43
0
        def _wrapper(self, *args, **kwargs):
            validation_ruleset = getattr(self, "validation_ruleset")
            input_schema = create_object_schema_from_validation_ruleset(validation_ruleset)
            if input_schema is not None:
                try:
                    encoding = "UTF-8"
                    input_ = json.loads(self.request.body.decode(encoding))
                except ValueError:
                    raise jsonschema.ValidationError(
                        "Input is malformed; could not decode JSON object."
                    )

                if use_defaults:
                    input_ = input_schema_clean(input_, input_schema)

                jsonschema.validate(
                    input_,
                    input_schema,
                    cls=validator_cls,
                    format_checker=format_checker
                )
            else:
                input_ = None

            setattr(self, "body", input_)
            output = rh_method(self, *args, **kwargs)
            if is_future(output):
                output = yield output

            if not output and on_empty_404:
                raise APIError(404, "Resource not found.")

            if output_schema is not None:
                try:
                    jsonschema.validate(
                        {"result": output},
                        {
                            "type": "object",
                            "properties": {
                                "result": output_schema
                            },
                            "required": ["result"]
                        }
                    )
                except jsonschema.ValidationError as error:
                    raise TypeError(str(error))

            self.success(output)
 def _write_body(self, start_read):
     if self.request.body is not None:
         self.connection.write(self.request.body)
     elif self.request.body_producer is not None:
         fut = self.request.body_producer(self.connection.write)
         if is_future(fut):
             def on_body_written(fut):
                 fut.result()
                 self.connection.finish()
                 if start_read:
                     self._read_response()
             self.io_loop.add_future(fut, on_body_written)
             return
     self.connection.finish()
     if start_read:
         self._read_response()
Exemple #45
0
 def run():
     try:
         result = func()
         if result is not None:
             from tornado.gen import convert_yielded
             result = convert_yielded(result)
     except Exception:
         future_cell[0] = Future()
         future_set_exc_info(future_cell[0], sys.exc_info())
     else:
         if is_future(result):
             future_cell[0] = result
         else:
             future_cell[0] = Future()
             future_cell[0].set_result(result)
     self.add_future(future_cell[0], lambda future: self.stop())
Exemple #46
0
        def _wrapper(self, *args, **kwargs):
            result = rh_method(self, *args, **kwargs)
            if is_future(result):
                result = yield result

            if result is not None:
                try:
                    jsonschema.validate(result,
                                        schema,
                                        format_checker=format_checker)
                except jsonschema.ValidationError:
                    log.exception("Invalid response")
                    raise APIError(500, "Invalid response")

                self.write_json(result)
                self.finish()
Exemple #47
0
    def execute_next(self, request, types, process_object, *args, **kwargs):
        midd = None

        if types == _TCALL:
            midd = (
                'call_midds',
                'process_call',
            )
        elif types == _TREQ:
            midd = (
                'request_midds',
                'process_request',
            )
        elif types == _TREN:
            midd = (
                'render_midds',
                'process_render',
            )
        elif types == _TRES:
            midd = (
                'response_midds',
                'process_response',
            )
        elif types == _TEND:
            midd = (
                'end_midds',
                'process_endcall',
            )
        elif types == _TEXC:
            midd = (
                'exc_midds',
                'process_exception',
            )
        if midd:
            while 1:
                method = self._get_func(request, midd[0], midd[1])
                if method and callable(method):

                    clear = partial(self.clear_all, request)
                    result = method(process_object, clear, *args, **kwargs)
                    if is_future(result):
                        result = yield result
                        if result:
                            break
                else:
                    break
Exemple #48
0
    def execute_next_for_async(self, request, types, process_object, *args,
                               **kwargs):
        midd = self._call_mapper.get(types, None)

        if midd:
            while 1:
                method = self._get_func(request, midd[0], midd[1])

                if method and callable(method):
                    clear = partial(self.clear_all, request)
                    result = method(process_object, clear, *args, **kwargs)
                    if is_future(result):
                        result = yield result
                    if result:
                        break
                else:
                    break
Exemple #49
0
 def run():
     """execute dest func"""
     try:
         result = func(*args, **kwargs)
         if result is not None:
             result = convert_yielded(result)
     except Exception:
         future_cell[0] = Future()
         future_set_exc_info(future_cell[0], sys.exc_info())
     else:
         if is_future(result):
             future_cell[0] = result
         else:
             future_cell[0] = Future()
             future_cell[0].set_result(result)
     IOLoop.current().add_future(future_cell[0],
                                 lambda future: check_stop())
Exemple #50
0
 def _create_table(self):
     types = [
         self._types_mapping[self._schema.propinfo(c)["type"]] +
         (" not null" if c in self._schema.__required__ else "")
         for c in self.columns
     ]
     column_defs = [self._create_primary_key()] + [
         "{} {}".format(c, t) for c, t in zip(self.columns, types)
     ]
     with (yield self.cursor(self.connection, transaction=True)) as cursor:
         cur = dbapiext.execute_f(
             cursor,
             "create table if not exists %s (%s)",
             self._tablename,
             column_defs,
         )
         if is_future(cur):
             yield cur
Exemple #51
0
            def validate_output(output):
                # in case output is a future, we can be sure it is finished
                if is_future(output):
                    output = output.result()

                json_data = validate_json(json_data=output,
                                          json_schema=output_schema,
                                          json_example=output_example,
                                          validator_cls=validator_cls,
                                          format_checker=format_checker,
                                          on_empty_404=on_empty_404)

                if json_data and write_json and \
                   not self._finished:
                    if isinstance(self, JSendMixin):
                        self.success(json_data)
                    else:
                        self.write(json_data)
Exemple #52
0
    def apply_future(cls, func, *args, **kwargs):
        """Execute coroutine in a standalone tornado ioloop.

        :param func: coroutine function or regular function.
        :param kwargs: if `callback` in kwargs dict,
            the value will be treated as a function and called when coroutine
            finishs.
        """
        hub = cls.get_hub()
        callback = kwargs.pop('callback', None)
        ret = func(*args, **kwargs)
        if concurrent.is_future(ret):
            if ret.done():
                return ret.result()

            return hub.execute_future(ret, callback)
        else:
            return ret
Exemple #53
0
 def run() -> None:
     try:
         result = func()
         if result is not None:
             from tornado.gen import convert_yielded
             result = convert_yielded(result)
     except Exception:
         fut = Future()  # type: Future[Any]
         future_cell[0] = fut
         future_set_exc_info(fut, sys.exc_info())
     else:
         if is_future(result):
             future_cell[0] = result
         else:
             fut = Future()
             future_cell[0] = fut
             fut.set_result(result)
     assert future_cell[0] is not None
     self.add_future(future_cell[0], lambda future: self.stop())
Exemple #54
0
 def post(self, dev, circuit, prop):
     try:
         #print "%s-%s-%s" %(dev,circuit,prop)
         device = Devices.by_name(dev, circuit)
         kw = dict([(k, v[0])
                    for (k, v) in self.request.body_arguments.iteritems()])
         result = device.set(**kw)
         if is_future(result):
             result = yield result
         #print result
         self.write(json.dumps({'success': True, 'result': result}))
     except Exception, E:
         self.write(
             json.dumps({
                 'success': False,
                 'errors': {
                     '__all__': str(E)
                 }
             }))
Exemple #55
0
def maybe_future(x):
    """Converts ``x`` into a `.Future`.

    If ``x`` is already a `.Future`, it is simply returned; otherwise
    it is wrapped in a new `.Future`.  This is suitable for use as
    ``result = yield gen.maybe_future(f())`` when you don't know whether
    ``f()`` returns a `.Future` or not.

    .. deprecated:: 4.3
       This function only handles ``Futures``, not other yieldable objects.
       Instead of `maybe_future`, check for the non-future result types
       you expect (often just ``None``), and ``yield`` anything unknown.
    """
    if is_future(x):
        return x
    else:
        fut = _create_future()
        fut.set_result(x)
        return fut
Exemple #56
0
    def handle_yield(self, yielded):
        if isinstance(yielded, (list, dict)):
            yielded = Multi(yielded)
        if isinstance(yielded, YieldPoint):
            self.future = TracebackFuture()

            def start_yield_point():
                try:
                    yielded.start(self)
                    if yielded.is_ready():
                        self.future.set_result(yielded.get_result())
                    else:
                        self.yield_point = yielded
                except Exception:
                    self.future = TracebackFuture()
                    self.future.set_exc_info(sys.exc_info())

            if self.stack_context_deactivate is None:
                # Start a stack context if this is the first
                # YieldPoint we've seen.
                with stack_context.ExceptionStackContext(
                        self.handle_exception) as deactivate:
                    self.stack_context_deactivate = deactivate

                    def cb():
                        start_yield_point()
                        self.run()

                    self.io_loop.add_callback(cb)
                    return False
            else:
                start_yield_point()
        elif is_future(yielded):
            self.future = yielded
            if not self.future.done() or self.future is moment:
                self.io_loop.add_future(self.future, lambda f: self.run())
                return False
        else:
            self.future = TracebackFuture()
            self.future.set_exception(
                BadYieldError("yielded unknown object %r" % (yielded, )))
        return True
 def test_write_measurements_while_already_processing(self):
     database = str(uuid.uuid4())
     name = str(uuid.uuid4())
     test_value = random.randint(1000, 2000)
     measurement = influxdb.Measurement(database, name)
     measurement.set_field('test', test_value)
     influxdb.add_measurement(measurement)
     self.assertEqual(influxdb._pending_measurements(), 1)
     future = influxdb._on_timeout()
     second_write = influxdb._write_measurements()
     self.assertTrue(concurrent.is_future(second_write))
     self.assertTrue(second_write.done())
     self.assertFalse(second_write.result())
     self.assertEqual(influxdb._pending_measurements(), 0)
     self.io_loop.add_future(future, self.stop)
     self.wait()
     result = self.get_measurement()
     self.assertEqual(result.db, database)
     self.assertEqual(result.name, name)
     self.assertEqual(result.fields['test'], test_value)
Exemple #58
0
 def execute_next(self, request, mv_type, handler, *args, **kwargs):
     method_name = self._call_mapper.get(mv_type)
     if method_name == 'process_request':
         middleware_list = self.middleware_list
     elif method_name in ['process_response', 'process_finished']:
         # 这两个方法的处理顺序是反序
         middleware_list = self.middleware_list[-1::-1]
     else:
         return
     try:
         for mv_class in middleware_list:
             instance = mv_class(handler)
             # 如果不提供 default, 不存在时会出现异常
             m = getattr(instance, method_name, None)
             logger.debug('%s, %s, %s' % (mv_class, m, method_name))
             if m and callable(m):
                 try:
                     result = m(*args, **kwargs)
                     if is_future(result):
                         yield result
                 except Exception as e:
                     logger.error(e)
                     logger.error(traceback.format_exc())
                     # 在某一层的中间件出现异常,下一级的都不执行
                     self.clear_nested_middleware(mv_class)
                     # 如果在 request 阶段就出现了异常,直接进入 finish
                     if mv_type == _REQUEST and not self._finished:
                         status_code = getattr(e, 'status_code',
                                               GATEWAY_ERROR_STATUS_CODE)
                         logger.debug('exception write error')
                         self.write_error(status_code,
                                          exc_info=sys.exc_info())
                     # 不再往下执行
                     break
     except Exception as e:
         logger.error(e)
         logger.error(traceback.format_exc())
         # 出现了预料之外的错误, 清理所有中间件, 结束
         self.middleware_list = []
         status_code = getattr(e, 'status_code', GATEWAY_ERROR_STATUS_CODE)
         self.write_error(status_code, exc_info=sys.exc_info())
Exemple #59
0
    def message_receive(self, _comm, msg):
        intent = msg[process_comms.INTENT_KEY]

        if intent == process_comms.Intent.PLAY:
            result = self.play()
        elif intent == process_comms.Intent.PAUSE:
            result = self.pause(msg=msg.get(process_comms.MESSAGE_KEY, None))
        elif intent == process_comms.Intent.KILL:
            result = self.kill(msg=msg.get(process_comms.MESSAGE_KEY, None))
        elif intent == process_comms.Intent.STATUS:
            status_info = {}
            self.get_status_info(status_info)
            result = status_info
        else:
            raise RuntimeError("Unknown intent")

        if concurrent.is_future(result):
            # Wait for the process to actually finish
            result = yield result

        raise gen.Return(result)
Exemple #60
0
def convert_yielded(yielded):
    """Convert a yielded object into a `.Future`.

    The default implementation accepts lists, dictionaries, and Futures.

    If the `~functools.singledispatch` library is available, this function
    may be extended to support additional types. For example::

        @convert_yielded.register(asyncio.Future)
        def _(asyncio_future):
            return tornado.platform.asyncio.to_tornado_future(asyncio_future)

    .. versionadded:: 4.1
    """
    # Lists and dicts containing YieldPoints were handled separately
    # via Multi().
    if isinstance(yielded, (list, dict)):
        return multi_future(yielded)
    elif is_future(yielded):
        return yielded
    else:
        raise BadYieldError("yielded unknown object %r" % (yielded, ))