From ffe2ed52cf369a070fa3ccb11775689d65f30f6b Mon Sep 17 00:00:00 2001 From: Felix Yan Date: Wed, 23 Sep 2020 17:56:46 +0800 Subject: [PATCH] pypi: Use xmlrpc instead of json api It makes the transfer much smaller as the xmlrpc method returns only exactly what we need here. --- nvchecker/httpclient/aiohttp_httpclient.py | 3 +++ nvchecker/httpclient/base.py | 2 ++ nvchecker/httpclient/httpx_httpclient.py | 2 ++ nvchecker/httpclient/tornado_httpclient.py | 3 +++ nvchecker_source/pypi.py | 23 ++++++++++++++++------ 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/nvchecker/httpclient/aiohttp_httpclient.py b/nvchecker/httpclient/aiohttp_httpclient.py index 3aa8a45..5dbfde1 100644 --- a/nvchecker/httpclient/aiohttp_httpclient.py +++ b/nvchecker/httpclient/aiohttp_httpclient.py @@ -30,6 +30,7 @@ class AiohttpSession(BaseSession): headers: Dict[str, str] = {}, params = (), json = None, + body = None, ) -> Response: kwargs = { 'headers': headers, @@ -40,6 +41,8 @@ class AiohttpSession(BaseSession): kwargs['proxy'] = proxy if json is not None: kwargs['json'] = json + if body is not None: + kwargs['body'] = body try: logger.debug('send request', method=method, url=url, kwargs=kwargs) diff --git a/nvchecker/httpclient/base.py b/nvchecker/httpclient/base.py index 9876a06..7cbe554 100644 --- a/nvchecker/httpclient/base.py +++ b/nvchecker/httpclient/base.py @@ -40,6 +40,7 @@ class BaseSession: headers: Dict[str, str] = {}, params = (), json = None, + body = None, ) -> Response: t = tries.get() p = proxy.get() @@ -56,6 +57,7 @@ class BaseSession: headers = headers, params = params, json = json, + body = body, proxy = p or None, ) except TemporaryError as e: diff --git a/nvchecker/httpclient/httpx_httpclient.py b/nvchecker/httpclient/httpx_httpclient.py index 7c78b1d..24a076d 100644 --- a/nvchecker/httpclient/httpx_httpclient.py +++ b/nvchecker/httpclient/httpx_httpclient.py @@ -21,6 +21,7 @@ class HttpxSession(BaseSession): headers: Dict[str, str] = {}, params = (), json = None, + body = None, ) -> Response: client = self.clients.get(proxy) if not client: @@ -36,6 +37,7 @@ class HttpxSession(BaseSession): method, url, json = json, headers = headers, params = params, + content = body, ) if r.status_code >= 500: raise TemporaryError( diff --git a/nvchecker/httpclient/tornado_httpclient.py b/nvchecker/httpclient/tornado_httpclient.py index 8b51080..dccb07d 100644 --- a/nvchecker/httpclient/tornado_httpclient.py +++ b/nvchecker/httpclient/tornado_httpclient.py @@ -38,6 +38,7 @@ class TornadoSession(BaseSession): headers: Dict[str, str] = {}, params = (), json = None, + body = None, ) -> Response: kwargs: Dict[str, Any] = { 'method': method, @@ -46,6 +47,8 @@ class TornadoSession(BaseSession): if json: kwargs['body'] = _json.dumps(json) + if body: + kwargs['body'] = body kwargs['prepare_curl_callback'] = try_use_http2 if proxy: diff --git a/nvchecker_source/pypi.py b/nvchecker_source/pypi.py index 2c29858..2b9bba7 100644 --- a/nvchecker_source/pypi.py +++ b/nvchecker_source/pypi.py @@ -1,21 +1,32 @@ # MIT licensed # Copyright (c) 2013-2020 lilydjwg , et al. +import xmlrpc.client +from typing import List, Tuple, Union from pkg_resources import parse_version +from nvchecker.api import session + +async def pypi_xmlrpc_request(key: Tuple[str, str, bool]) -> Union[str, List[str]]: + url, package, use_pre_release = key + payload = xmlrpc.client.dumps((package, use_pre_release), "package_releases") + + res = await session.post(url, headers={"Content-Type": "text/xml"}, body=payload) + params, methodname = xmlrpc.client.loads(res.body) + return params[0] # type: ignore + async def get_version(name, conf, *, cache, **kwargs): package = conf.get('pypi') or name - use_pre_release = conf.get('use_pre_release', False) + use_pre_release = bool(conf.get('use_pre_release', False)) - url = 'https://pypi.org/pypi/{}/json'.format(package) - - data = await cache.get_json(url) + url = 'https://pypi.org/pypi' + data = await cache.get((url, package, use_pre_release), pypi_xmlrpc_request) if use_pre_release: version = sorted( - data['releases'].keys(), + data, key = parse_version, )[-1] else: - version = data['info']['version'] + version = data return version