コード例 #1
0
    def add_entity_field(self, parent_node: MultiDict, path: [str, None],
                         param_name: str, field: str):
        if not path:
            # we reached the leaf. It's time to save param
            parent_node.setdefault(param_name, []).append(field)
            return

        # it is not the leaf, continue
        current_include_name, rest_path = self.split_path_to_current_and_rest(
            path)
        current_node = parent_node['include'].get(current_include_name)

        if current_node is None:
            # entity is not included. Ignore this param and do not save anywhere
            return

        self.add_entity_field(current_node, rest_path, param_name, field)
コード例 #2
0
    def add_entity(self, parent_node: MultiDict, path: [str, None]):
        if not path:
            # The end, we reached the leaf. All the includes have been initialized with empty dicts
            return

        current_include_name, rest_path = self.split_path_to_current_and_rest(
            path)
        current_node = parent_node.setdefault('include',
                                              MultiDict()).setdefault(
                                                  current_include_name,
                                                  MultiDict())

        self.add_entity(current_node, rest_path)
コード例 #3
0
ファイル: client.py プロジェクト: aghasi/aiohttp-xmlrpc
class ServerProxy(object):
    __slots__ = 'client', 'url', 'loop', 'headers', 'encoding'

    USER_AGENT = u'aiohttp XML-RPC client (Python: {0}, version: {1})'.format(__pyversion__, __version__)

    def __init__(self, url, client=None, headers=None, encoding=None, **kwargs):
        self.headers = MultiDict(headers or {})

        self.headers.setdefault('Content-Type', 'text/xml')
        self.headers.setdefault('User-Agent', self.USER_AGENT)

        self.encoding = encoding

        self.url = str(url)
        self.client = client or aiohttp.client.ClientSession(**kwargs)

    @staticmethod
    def _make_request(method_name, *args, **kwargs):
        root = etree.Element('methodCall')
        method_el = etree.Element('methodName')
        method_el.text = method_name

        root.append(method_el)

        params_el = etree.Element('params')
        root.append(params_el)

        for arg in args:
            param = etree.Element('param')
            val = etree.Element('value')
            param.append(val)
            params_el.append(param)
            val.append(py2xml(arg))

        if kwargs:
            param = etree.Element('param')
            val = etree.Element('value')
            param.append(val)
            params_el.append(param)
            val.append(py2xml(kwargs))

        return root

    @staticmethod
    def _parse_response(body, method_name):
        try:
            if log.getEffectiveLevel() <= logging.DEBUG:
                log.debug("Server response: \n%s", body.decode())

            response = etree.fromstring(body)
            schema.assertValid(response)
        except etree.DocumentInvalid:
            raise ValueError("Invalid body")

        result = response.xpath('//params/param/value/*')
        if result:
            return xml2py(result[0])

        fault = response.xpath('//fault/value/*')
        if fault:
            err = xml2py(fault[0])

            raise xml2py_exception(
                err.get('faultCode', exceptions.SystemError.code),
                err.get('faultString', 'Unknown error'),
                default_exc_class=exceptions.ServerError
            )

        raise exceptions.ParseError('Respond body for method "%s" '
                                    'not contains any response.', method_name)

    async def __remote_call(self, method_name, *args, **kwargs):
        async with self.client.post(
            str(self.url),
            data=etree.tostring(
                self._make_request(method_name, *args, **kwargs),
                xml_declaration=True,
                encoding=self.encoding
            ),
            headers=self.headers,
        ) as response:
            response.raise_for_status()

            return self._parse_response((await response.read()), method_name)

    def __getattr__(self, method_name):
        return self[method_name]

    def __getitem__(self, method_name):
        def method(*args, **kwargs):
            return self.__remote_call(method_name, *args, **kwargs)

        return method

    def close(self):
        return self.client.close()
コード例 #4
0
class ServerProxy(object):
    __slots__ = (
        "client",
        "url",
        "loop",
        "headers",
        "loads",
        "dumps",
        "client_owner",
    )

    USER_AGENT = "aiohttp JSON-RPC client (Python: {0}, version: {1})".format(
        __pyversion__,
        __version__,
    )

    def __init__(self,
                 url: typing.Union[str, yarl.URL],
                 client: ClientSessionType = None,
                 loop: asyncio.AbstractEventLoop = None,
                 headers: HeadersType = None,
                 client_owner: bool = True,
                 loads=json.loads,
                 dumps=json.dumps,
                 **kwargs):

        self.headers = MultiDict(headers or {})

        self.headers.setdefault("Content-Type", "application/json")
        self.headers.setdefault("User-Agent", self.USER_AGENT)

        self.url = str(url)
        self.loop = loop or asyncio.get_event_loop()
        self.client = client or aiohttp.client.ClientSession(loop=self.loop,
                                                             **kwargs)
        self.client_owner = bool(client_owner)

        self.loads = loads
        self.dumps = dumps

    @staticmethod
    def _parse_response(response):
        log.debug("Server response: \n%r", response)

        if "error" in response:
            error = response["error"]

            if not isinstance(error, dict):
                raise Exception
            else:
                raise json2py_exception(
                    error.get("code", exceptions.SystemError.code),
                    error.get("message", "Unknown error"),
                    default_exc_class=exceptions.ServerError,
                )
        return response.get("result")

    async def __remote_call(self, json_request):
        request = py2json(json_request)
        response = await self.client.post(
            str(self.url),
            headers=self.headers,
            data=self.dumps(request),
        )

        response.raise_for_status()

        if "id" not in request:
            # Notification
            return

        return self._parse_response(
            self.loads((await response.read()).decode()), )

    async def __call__(self, *prepared_methods, return_exceptions=True):
        request = []
        request_indecies = []

        for req in prepared_methods:
            if isinstance(req, Method):
                req = req.prepare()

            if isinstance(req, Notification):
                req = req.prepare()

            request_indecies.append(req.get("id"))
            request.append(req)

        response = await self.client.post(
            str(self.url),
            headers=self.headers,
            data=self.dumps(py2json(request)),
        )

        response.raise_for_status()

        responses = {}
        data = self.loads((await response.read()).decode())

        for response in data:
            req_id = response.get("id")
            if not req_id:
                continue

            try:
                responses[req_id] = self._parse_response(response)
            except Exception as e:
                if return_exceptions:
                    responses[req_id] = e
                    continue
                raise

        result = []
        for req_id in request_indecies:
            if req_id is None:
                result.append(None)
                continue

            result.append(responses[req_id])
        return result

    def __getattr__(self, method_name) -> Method:
        return self[method_name]

    def __getitem__(self, method_name) -> Method:
        return Method(method_name, self.__remote_call)

    def create_notification(self, method):
        return Notification(method, self.__remote_call)

    async def close(self, force=False):
        if not self.client_owner and not force:
            return
        return await self.client.close()

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        if self.client.closed:
            return

        await self.close()
コード例 #5
0
class ServerProxy(object):
    __slots__ = "client", "url", "loop", "headers", "encoding", "huge_tree"

    USER_AGENT = ("aiohttp XML-RPC client "
                  "(Python: {0}, version: {1})").format(
                      __pyversion__, __version__)

    def __init__(self,
                 url,
                 client=None,
                 headers=None,
                 encoding=None,
                 huge_tree=False,
                 **kwargs):
        self.headers = MultiDict(headers or {})

        self.headers.setdefault("Content-Type", "text/xml")
        self.headers.setdefault("User-Agent", self.USER_AGENT)

        self.encoding = encoding
        self.huge_tree = huge_tree

        self.url = str(url)
        self.client = client or aiohttp.client.ClientSession(**kwargs)

    @staticmethod
    def _make_request(method_name, *args, **kwargs):
        root = etree.Element("methodCall")
        method_el = etree.Element("methodName")
        method_el.text = method_name

        root.append(method_el)

        params_el = etree.Element("params")
        root.append(params_el)

        for arg in args:
            param = etree.Element("param")
            val = etree.Element("value")
            param.append(val)
            params_el.append(param)
            val.append(py2xml(arg))

        if kwargs:
            param = etree.Element("param")
            val = etree.Element("value")
            param.append(val)
            params_el.append(param)
            val.append(py2xml(kwargs))

        return root

    def _parse_response(self, body, method_name):
        try:
            if log.getEffectiveLevel() <= logging.DEBUG:
                log.debug("Server response: \n%s", body.decode())

            parser = etree.XMLParser(huge_tree=self.huge_tree)
            response = etree.fromstring(body, parser)
            schema.assertValid(response)
        except etree.DocumentInvalid:
            raise ValueError("Invalid body")

        result = response.xpath("//params/param/value")
        if result:
            if len(result) < 2:
                return xml2py(result[0])

            return [xml2py(item) for item in result]

        fault = response.xpath("//fault/value")
        if fault:
            err = xml2py(fault[0])

            raise xml2py_exception(
                err.get("faultCode", exceptions.SystemError.code),
                err.get("faultString", "Unknown error"),
                default_exc_class=exceptions.ServerError,
            )

        raise exceptions.ParseError(
            'Respond body for method "%s" '
            "not contains any response.",
            method_name,
        )

    async def __remote_call(self, method_name, *args, **kwargs):
        async with self.client.post(
                str(self.url),
                data=etree.tostring(
                    self._make_request(method_name, *args, **kwargs),
                    xml_declaration=True,
                    encoding=self.encoding,
                ),
                headers=self.headers,
        ) as response:
            response.raise_for_status()

            return self._parse_response((await response.read()), method_name)

    def __getattr__(self, method_name):
        # Trick to keep the "close" method available
        if method_name == "close":
            return self.__close
        else:
            # Magic method dispatcher
            return _Method(self.__remote_call, method_name)

    def __aenter__(self):
        return self.client.__aenter__()

    def __aexit__(self, exc_type, exc_val, exc_tb):
        return self.client.__aexit__(exc_type, exc_val, exc_tb)

    def __close(self):
        return self.client.close()
コード例 #6
0
class ServerProxy(object):
    __slots__ = 'client', 'url', 'loop', 'headers', 'loads', 'dumps'

    USER_AGENT = u'aiohttp JSON-RPC client (Python: {0}, version: {1})'.format(__pyversion__, __version__)

    def __init__(self, url, client=None, loop=None, headers=None,
                 loads=json.loads, dumps=json.dumps, **kwargs):

        self.headers = MultiDict(headers or {})

        self.headers.setdefault('Content-Type', 'application/json')
        self.headers.setdefault('User-Agent', self.USER_AGENT)

        self.url = str(url)
        self.loop = loop or asyncio.get_event_loop()
        self.client = client or aiohttp.client.ClientSession(loop=self.loop, **kwargs)

        self.loads = loads
        self.dumps = dumps

    @staticmethod
    def _parse_response(response):
        log.debug("Server response: \n%r", response)

        if 'error' in response:
            error = response['error']

            if not isinstance(error, dict):
                raise Exception
            else:
                raise json2py_exception(
                    error.get('code', exceptions.SystemError.code),
                    error.get('message', 'Unknown error'),
                    default_exc_class=exceptions.ServerError
                )
        return response.get('result')

    @asyncio.coroutine
    def __remote_call(self, json_request):
        response = yield from self.client.post(
            str(self.url),
            headers=self.headers,
            data=self.dumps(py2json(json_request)),
        )

        response.raise_for_status()

        return self._parse_response(
            self.loads((yield from response.read()).decode())
        )

    @asyncio.coroutine
    def _batch_call(self, prepared_methods):

        request = []

        for idx, req in enumerate(prepared_methods):
            if isinstance(req, Method):
                req = req.prepare()

            req['id'] = idx + 1
            request.append(req)

        response = yield from self.client.post(
            str(self.url),
            headers=self.headers,
            data=self.dumps(py2json(request)),
        )

        response.raise_for_status()

        responses = []
        data = self.loads((yield from response.read()).decode())

        for response in data:
            try:
                responses.append(self._parse_response(response))
            except Exception as e:
                responses.append(e)

        return responses

    def __getattr__(self, method_name) -> Method:
        return self[method_name]

    def __getitem__(self, method_name) -> Method:
        return Method(method_name, self.__remote_call)

    def close(self):
        return self.client.close()