11# encoding: utf-8
22import hashlib
3- import json
43import logging
54from copy import copy
65from slimurl import URL
1716log = logging .getLogger (__name__ )
1817
1918
20- def async_retrying (number , exceptions = (Exception ,)):
21- def decorator (func ):
22- @coroutine
23- def wrap (* args , ** kwargs ):
24- last_exc = None
25- for i in range (number ):
26- try :
27- raise Return ((yield func (* args , ** kwargs )))
28- except Return :
29- raise
30- except exceptions as e :
31- log .exception ("Error on attempt: %r" , i )
32- last_exc = e
33-
34- if last_exc :
35- raise last_exc
36- return wrap
37- return decorator
38-
39-
4019def normalize_package_name (name ):
4120 return name .lower ().replace ("_" , "-" ).replace ("." , "-" )
4221
@@ -47,20 +26,19 @@ class PYPIClient(object):
4726 THREAD_POOL = None
4827 INDEX = None
4928 XMLRPC = None
50- RPC_URL = None
5129 LOCK = None
5230
5331 @classmethod
5432 def configure (cls , backend , thread_pool ):
5533 cls .CLIENT = AsyncHTTPClient (io_loop = IOLoop .current ())
5634 cls .BACKEND = backend
5735 cls .THREAD_POOL = thread_pool
58- cls .RPC_URL = copy (backend )(path = "/pypi" )
59- cls .XMLRPC = ServerProxy (str (cls .RPC_URL ))
36+ cls .XMLRPC = ServerProxy (
37+ str (copy (backend )(path = "/pypi" )),
38+ )
6039 cls .LOCK = Lock ()
6140
6241 @classmethod
63- @async_retrying (5 )
6442 @coroutine
6543 @Cache (HOUR , files_cache = True , ignore_self = True )
6644 def packages (cls ):
@@ -76,7 +54,6 @@ def packages(cls):
7654 raise Return (index )
7755
7856 @classmethod
79- @async_retrying (5 )
8057 @coroutine
8158 @Cache (4 * HOUR , files_cache = True , ignore_self = True )
8259 def search (cls , names , descriptions , operator = "or" ):
@@ -85,7 +62,6 @@ def search(cls, names, descriptions, operator="or"):
8562 raise Return (result )
8663
8764 @classmethod
88- @async_retrying (5 )
8965 @coroutine
9066 def exists (cls , name ):
9167 try :
@@ -100,7 +76,6 @@ def exists(cls, name):
10076 raise Return (True )
10177
10278 @classmethod
103- @async_retrying (5 )
10479 @coroutine
10580 def find_real_name (cls , name ):
10681 if not options .pypi_proxy :
@@ -117,7 +92,6 @@ def find_real_name(cls, name):
11792 raise Return (real_name )
11893
11994 @classmethod
120- @async_retrying (5 )
12195 @coroutine
12296 @Cache (4 * HOUR , files_cache = True , ignore_self = True )
12397 def releases (cls , name ):
@@ -145,20 +119,15 @@ def releases(cls, name):
145119 raise Return (set (res ))
146120
147121 @classmethod
148- @async_retrying (5 )
149122 @coroutine
150123 @Cache (MONTH , files_cache = True , ignore_self = True )
151124 def release_data (cls , name , version ):
152- url = copy (cls .RPC_URL )
153- url .path_append (str (name ), str (version ), 'json' )
154- log .info ("Gathering info %s" , url )
155-
156- response = json .loads ((yield cls .CLIENT .fetch (str (url ))).body )
157- info = response ['info' ]
158- files = response ['urls' ]
125+ info , files = yield [
126+ cls .XMLRPC .release_data (str (name ), str (version )),
127+ cls .XMLRPC .release_urls (str (name ), str (version ))
128+ ]
159129
160130 download_url = info .get ('download_url' )
161-
162131 if download_url and not files :
163132 try :
164133 url = URL (download_url )
0 commit comments