Exemple #1
0
    def moya_render(self, archive, context, target, options):
        template = [options.get('template', None)]
        style = options.get('style', None) or self.style
        template.append(self.get_template_path(style, self.fieldname))
        if style is not 'simple':
            template.append(self.get_template_path('simple', self.fieldname))

        r = RenderContainer.create(archive.find_app('moya.forms'),
                                   template=template)
        r['self'] = self
        r['field'] = self
        if self.data is not None:
            r.update(self.data)
        return r.moya_render(archive, context, target, options)
Exemple #2
0
    def moya_render(self, archive, context, target, options):
        template = [options.get('template', None)]
        style = options.get('style', None) or self.style
        template.append(self.get_template_path(style, self.fieldname))
        if style is not 'simple':
            template.append(self.get_template_path('simple', self.fieldname))

        r = RenderContainer.create(archive.find_app('moya.forms'),
                                   template=template)
        r['self'] = self
        r['field'] = self
        if self.data is not None:
            r.update(self.data)
        return r.moya_render(archive, context, target, options)
Exemple #3
0
    def run(self, context):
        """Generate a response for either a GET or a POST"""
        request = context['.request']
        app = context.get('.app', None)
        interface_id = "<interface {}#{}>".format(app.name, self.libname)

        if request.method == "GET":
            render_container = RenderContainer.create(app,
                                                      template="moya.jsonrpc/interface.html")
            render_container['interface'] = self
            context['_return'] = render_container
            return
        if request.method != "POST":
            return
        context['.jsonrpc'] = {"request": {}}

        try:
            req = json.loads(request.body.decode('utf-8'))
        except Exception as e:
            log.debug("%s badly formatted JSONRPC request: %s", interface_id, e)
            response = self.make_error(None,
                                       False,
                                       code=ErrorCode.parse_error,
                                       message=text_type(e))
            raise logic.EndLogic(response)

        batch = isinstance(req, list)
        responses = []

        for response in self.process_request(context, req):
            if response is None:
                # Notification
                continue
            elif isinstance(response, ErrorResponse):
                # Problem with request
                responses.append(response)
            elif isinstance(response, CallMethod):
                # Request good, do call
                method, params, req_id, notification = response

                log.debug("%s %s '%s' with %s",
                          interface_id,
                          'notify' if notification else 'call',
                          method.name,
                          lazystr(to_expression, context, params, 80))

                try:
                    params = response.method.process_params(params)
                except ParamError as e:
                    response = ErrorResponse(ErrorCode.invalid_params,
                                             text_type(e),
                                             id=req_id)
                    self.log_result(context, response)
                    responses.append(response)
                    continue

                def do_call(element, app, params):
                    try:
                        return_value = self.archive.call(element.libid, context, app, **params)
                    except Exception as e:
                        if isinstance(e.original, MoyaException):
                            moya_exc = e.original
                            if moya_exc.type == "jsonrpc.error":
                                return RPCErrorReturn(moya_exc.info['code'],
                                                      moya_exc.info['message'],
                                                      moya_exc.info['data'])
                        error_message = "exception '{}' in rpc call to {}".format(e, method)
                        if hasattr(e, 'moya_trace'):
                            log.error(error_message)
                            if context['.debug'] and context['.console']:
                                context['.console'].obj(context, e)
                            else:
                                error_message = "{}\n{}".format(error_message, e.moya_trace)
                                log.error(error_message)
                        else:
                            context['.console'].obj(context, e)
                            log.exception(error_message)
                        response = ErrorResponse(ErrorCode.internal_error,
                                                 'internal error -- this error has been logged',
                                                 id=req_id)
                        return response
                    else:
                        return return_value

                return_value = do_call(method.element, app, params)

                if method.macro is not None and not isinstance(return_value, (RPCResponse, RPCErrorReturn)):
                    try:
                        macro_app, macro_element = self.get_element(method.macro, app)
                    except Exception as e:
                        log.error("%s no macro called '%s'", interface_id, method.macro)
                        return_value = ErrorResponse(ErrorCode.internal_error,
                                                     "internal error -- this error has been logged",
                                                     id=req_id)
                    else:
                        return_value = do_call(macro_element, app, params)

                if isinstance(return_value, RPCResponse):
                    self.log_result(context, return_value)
                    responses.append(return_value)
                    continue

                if notification:
                    continue

                if isinstance(return_value, RPCErrorReturn):
                    code, message, data = return_value
                    if code.isdigit():
                        code = int(code)
                    else:
                        try:
                            code = int(self.errors[code])
                            if not message:
                                message = self.errors[code].description
                        except Exception as e:
                            log.error("invalid error code '{}' -- defaulting to 'internal_error'".format(code))
                            code = ErrorCode.internal_error
                            message = ErrorCode.to_str[code]

                        return_value = RPCErrorReturn(code, message, data)
                    response = ErrorResponse(code, message, data=data, id=req_id)
                    self.log_result(context, response)
                else:
                    # Check the response is serializable
                    try:
                        moyajson.dumps(return_value)
                    except Exception as e:
                        log.error(text_type(e))
                        response = ErrorResponse(ErrorCode.internal_error,
                                                 'internal error -- server was unable to serialize the response',
                                                 id=req_id)
                        self.log_result(context, response)
                    else:
                        response = SuccessResponse(return_value, req_id)
                        self.log_result(context, return_value)

                responses.append(response)

        if not responses:
            raise logic.EndLogic(Response(content_type=b'application/json' if PY2 else 'application/json'))

        try:
            if batch:
                response_json = moyajson.dumps(responses, indent=4)
            else:
                response_json = moyajson.dumps(responses[0], indent=4)
        except Exception as e:
            log.exception("error serializing response")
            error_response = ErrorResponse(ErrorCode.internal_error,
                                           "server was unable to generate a response -- this error has been logged",
                                           id=None)
            response_json = moyajson.dumps(error_response)

        response = Response(content_type=b'application/json' if PY2 else 'application/json',
                            body=response_json)

        raise logic.EndLogic(response)
        yield  # Because this method should be a generator
Exemple #4
0
    def run(self, context):
        """Generate a response for either a GET or a POST"""
        request = context[".request"]
        app = context.get(".app", None)
        interface_id = "<interface {}#{}>".format(app.name, self.libname)

        if request.method == "GET":
            render_container = RenderContainer.create(
                app, template="moya.jsonrpc/interface.html")
            render_container["interface"] = self
            context["_return"] = render_container
            return
        if request.method != "POST":
            return
        context[".jsonrpc"] = {"request": {}}

        try:
            req = json.loads(request.body.decode("utf-8"))
        except Exception as e:
            log.debug("%s badly formatted JSONRPC request: %s", interface_id,
                      e)
            response = self.make_error(None,
                                       False,
                                       code=ErrorCode.parse_error,
                                       message=text_type(e))
            raise logic.EndLogic(response)

        batch = isinstance(req, list)
        responses = []

        for response in self.process_request(context, req):
            if response is None:
                # Notification
                continue
            elif isinstance(response, ErrorResponse):
                # Problem with request
                responses.append(response)
            elif isinstance(response, CallMethod):
                # Request good, do call
                method, params, req_id, notification = response

                log.debug(
                    "%s %s '%s' with %s",
                    interface_id,
                    "notify" if notification else "call",
                    method.name,
                    lazystr(to_expression, context, params, 80),
                )

                try:
                    params = response.method.process_params(context, params)
                except ParamError as e:
                    response = ErrorResponse(ErrorCode.invalid_params,
                                             text_type(e),
                                             id=req_id)
                    self.log_result(context, response)
                    responses.append(response)
                    continue

                def do_call(element, app, params):
                    try:
                        return_value = self.archive.call(
                            element.libid, context, app, **params)
                    except Exception as e:
                        if isinstance(getattr(e, "original", None),
                                      MoyaException):
                            moya_exc = e.original
                            if moya_exc.type == "jsonrpc.error":
                                return RPCErrorReturn(
                                    moya_exc.info["code"],
                                    moya_exc.info["message"],
                                    moya_exc.info["data"],
                                )
                        error_message = "exception '{}' in rpc call to {}".format(
                            e, method)
                        if hasattr(e, "moya_trace"):
                            log.error(error_message)
                            if context[".debug"] and context[".console"]:
                                context[".console"].obj(context, e)
                            else:
                                error_message = "{}\n{}".format(
                                    error_message, e.moya_trace)
                                log.error(error_message)
                        else:
                            context[".console"].obj(context, e)
                            log.exception(error_message)
                        response = ErrorResponse(
                            ErrorCode.internal_error,
                            "internal error -- this error has been logged",
                            id=req_id,
                        )
                        return response
                    else:
                        return return_value

                return_value = do_call(method.element, app, params)

                if method.macro is not None and not isinstance(
                        return_value, (RPCResponse, RPCErrorReturn)):
                    try:
                        macro_app, macro_element = self.get_element(
                            method.macro, app)
                    except Exception as e:
                        log.error("%s no macro called '%s'", interface_id,
                                  method.macro)
                        return_value = ErrorResponse(
                            ErrorCode.internal_error,
                            "internal error -- this error has been logged",
                            id=req_id,
                        )
                    else:
                        return_value = do_call(macro_element, app, params)

                if isinstance(return_value, RPCResponse):
                    self.log_result(context, return_value)
                    responses.append(return_value)
                    continue

                if notification:
                    continue

                if isinstance(return_value, RPCErrorReturn):
                    code, message, data = return_value
                    if code.isdigit():
                        code = int(code)
                    else:
                        try:
                            code = int(self.errors[code])
                            if not message:
                                message = self.errors[code].description
                        except Exception as e:
                            log.error(
                                "invalid error code '{}' -- defaulting to 'internal_error'"
                                .format(code))
                            code = ErrorCode.internal_error
                            message = ErrorCode.to_str[code]

                        return_value = RPCErrorReturn(code, message, data)
                    response = ErrorResponse(code,
                                             message,
                                             data=data,
                                             id=req_id)
                    self.log_result(context, response)
                else:
                    # Check the response is serializable
                    try:
                        moyajson.dumps(return_value)
                    except Exception as e:
                        log.error(text_type(e))
                        response = ErrorResponse(
                            ErrorCode.internal_error,
                            "internal error -- server was unable to serialize the response",
                            id=req_id,
                        )
                        self.log_result(context, response)
                    else:
                        response = SuccessResponse(return_value, req_id)
                        self.log_result(context, return_value)

                responses.append(response)

        if not responses:
            raise logic.EndLogic(
                Response(content_type=b"application/json"
                         if PY2 else "application/json"))

        try:
            if batch:
                response_json = moyajson.dumps(responses, indent=4)
            else:
                response_json = moyajson.dumps(responses[0], indent=4)
        except Exception as e:
            log.exception("error serializing response")
            error_response = ErrorResponse(
                ErrorCode.internal_error,
                "server was unable to generate a response -- this error has been logged",
                id=None,
            )
            response_json = moyajson.dumps(error_response)

        response = Response(
            content_type=b"application/json" if PY2 else "application/json",
            body=response_json,
        )

        raise logic.EndLogic(response)
        yield  # Because this method should be a generator