1717 version ,
1818)
1919
20- logger = logging .getLogger (' payjp' )
20+ logger = logging .getLogger (" payjp" )
2121
2222
2323class APIRequestor (object ):
24-
2524 def __init__ (self , key = None , client = None , api_base = None , account = None ):
2625 if api_base :
2726 self .api_base = api_base
@@ -38,142 +37,158 @@ def _get_retry_delay(self, retry_count):
3837 Based on "Exponential backoff with equal jitter" algorithm.
3938 https://aws.amazon.com/jp/blogs/architecture/exponential-backoff-and-jitter/
4039 """
41- wait = min (payjp .retry_max_delay , payjp .retry_initial_delay * 2 ** retry_count )
42- return ( wait / 2 + random .uniform (0 , wait / 2 ) )
40+ wait = min (payjp .retry_max_delay , payjp .retry_initial_delay * 2 ** retry_count )
41+ return wait / 2 + random .uniform (0 , wait / 2 )
4342
4443 def request (self , method , url , params = None , headers = None ):
4544 max_retry = payjp .max_retry or 0
4645 for i in range (max_retry + 1 ):
4746 body , code , my_api_key = self .request_raw (
48- method .lower (), url , params , headers )
47+ method .lower (), url , params , headers
48+ )
4949 if code != 429 :
5050 break
5151 elif i != max_retry :
5252 wait = self ._get_retry_delay (i )
53- logger .debug (' Retry after %s seconds.' % wait )
53+ logger .debug (" Retry after %s seconds." % wait )
5454 time .sleep (wait )
5555
5656 response = self .interpret_response (body , code )
5757 return response , my_api_key
5858
5959 def handle_api_error (self , body , code , response ):
6060 try :
61- err = response [' error' ]
61+ err = response [" error" ]
6262 except (KeyError , TypeError ):
6363 raise error .APIError (
6464 "Invalid response object from API: %r (HTTP response code "
6565 "was %d)" % (body , code ),
66- body , code , response )
66+ body ,
67+ code ,
68+ response ,
69+ )
6770
6871 if code in [400 , 404 ]:
6972 raise error .InvalidRequestError (
70- err .get ('message' ), err .get ('param' ), body , code , response )
73+ err .get ("message" ), err .get ("param" ), body , code , response
74+ )
7175 elif code == 401 :
72- raise error .AuthenticationError (
73- err .get ('message' ), body , code , response )
76+ raise error .AuthenticationError (err .get ("message" ), body , code , response )
7477 elif code == 402 :
75- raise error .CardError (err .get ('message' ), err .get ('param' ),
76- err .get ('code' ), body , code , response )
78+ raise error .CardError (
79+ err .get ("message" ),
80+ err .get ("param" ),
81+ err .get ("code" ),
82+ body ,
83+ code ,
84+ response ,
85+ )
7786 else :
78- raise error .APIError (err .get (' message' ), body , code , response )
87+ raise error .APIError (err .get (" message" ), body , code , response )
7988
8089 def request_raw (self , method , url , params = None , supplied_headers = None ):
81-
8290 from payjp import api_version
8391
8492 if self .api_key :
8593 my_api_key = self .api_key
8694 else :
8795 from payjp import api_key
96+
8897 my_api_key = api_key
8998
9099 if my_api_key is None :
91100 raise error .AuthenticationError (
92- ' No API key provided. (HINT: set your API key using '
101+ " No API key provided. (HINT: set your API key using "
93102 '"payjp.api_key = <API-KEY>"). You can generate API keys '
94- 'from the Payjp web interface. See https://docs.pay.jp'
95- 'for details, or email support@pay.jp if you have any '
96- 'questions.' )
103+ "from the Payjp web interface. See https://docs.pay.jp"
104+ "for details, or email support@pay.jp if you have any "
105+ "questions."
106+ )
97107
98- abs_url = ' %s%s' % (self .api_base , url )
108+ abs_url = " %s%s" % (self .api_base , url )
99109
100110 encoded_params = urlencode (list (_api_encode (params or {})))
101111
102- if method in (' get' , ' delete' ):
112+ if method in (" get" , " delete" ):
103113 if params :
104114 abs_url = _build_api_url (abs_url , encoded_params )
105115 post_data = None
106- elif method == ' post' :
116+ elif method == " post" :
107117 post_data = encoded_params
108118 else :
109- raise error .APIConnectionError (
110- 'Unrecognized HTTP method %r.' % (method ,))
119+ raise error .APIConnectionError ("Unrecognized HTTP method %r." % (method ,))
111120
112121 ua = {
113- ' bindings_version' : version .VERSION ,
114- ' lang' : ' python' ,
115- ' publisher' : ' payjp' ,
116- ' httplib' : self ._client .name ,
122+ " bindings_version" : version .VERSION ,
123+ " lang" : " python" ,
124+ " publisher" : " payjp" ,
125+ " httplib" : self ._client .name ,
117126 }
118127
119- for attr , func in [['lang_version' , platform .python_version ],
120- ['platform' , platform .platform ],
121- ['uname' , lambda : ' ' .join (platform .uname ())]]:
128+ for attr , func in [
129+ ["lang_version" , platform .python_version ],
130+ ["platform" , platform .platform ],
131+ ["uname" , lambda : " " .join (platform .uname ())],
132+ ]:
122133 try :
123134 val = func ()
124135 except Exception as e :
125- val = ' !! %s' % (e ,)
136+ val = " !! %s" % (e ,)
126137 ua [attr ] = val
127138
128139 encoded_api_key = str (
129- base64 .b64encode (
130- bytes ( '' . join ([ my_api_key , ':' ]), 'utf-8' )), 'utf-8' )
140+ base64 .b64encode (bytes ( "" . join ([ my_api_key , ":" ]), "utf-8" )), "utf-8"
141+ )
131142
132143 headers = {
133- ' X-Payjp-Client-User-Agent' : json .dumps (ua ),
134- ' User-Agent' : ' Payjp/v1 PythonBindings/%s' % (version .VERSION ,),
135- ' Authorization' : ' Basic %s' % encoded_api_key
144+ " X-Payjp-Client-User-Agent" : json .dumps (ua ),
145+ " User-Agent" : " Payjp/v1 PythonBindings/%s" % (version .VERSION ,),
146+ " Authorization" : " Basic %s" % encoded_api_key ,
136147 }
137148
138149 if self .payjp_account :
139- headers [' Payjp-Account' ] = self .payjp_account
150+ headers [" Payjp-Account" ] = self .payjp_account
140151
141- if method == ' post' :
142- headers [' Content-Type' ] = ' application/x-www-form-urlencoded'
152+ if method == " post" :
153+ headers [" Content-Type" ] = " application/x-www-form-urlencoded"
143154
144155 if api_version is not None :
145- headers [' Payjp-Version' ] = api_version
156+ headers [" Payjp-Version" ] = api_version
146157
147158 if supplied_headers is not None :
148159 for key , value in supplied_headers .items ():
149160 headers [key ] = value
150161
151- body , code = self ._client .request (
152- method , abs_url , headers , post_data )
162+ body , code = self ._client .request (method , abs_url , headers , post_data )
153163
154- logger .info (' %s %s %d' , method .upper (), abs_url , code )
164+ logger .info (" %s %s %d" , method .upper (), abs_url , code )
155165 logger .debug (
156- 'API request to %s returned (response code, response body) of '
157- '(%d, %r)' ,
158- abs_url , code , body )
166+ "API request to %s returned (response code, response body) of (%d, %r)" ,
167+ abs_url ,
168+ code ,
169+ body ,
170+ )
159171
160172 return body , code , my_api_key
161173
162174 def interpret_response (self , body , code ):
163175 try :
164- if hasattr (body , ' decode' ):
165- body = body .decode (' utf-8' )
176+ if hasattr (body , " decode" ):
177+ body = body .decode (" utf-8" )
166178 response = json .loads (body )
167179 except Exception :
168180 raise error .APIError (
169181 "Invalid response body from API: %s "
170182 "(HTTP response code was %d)" % (body , code ),
171- body , code )
183+ body ,
184+ code ,
185+ )
172186 if not (200 <= code < 300 ):
173187 self .handle_api_error (body , code , response )
174188
175189 return response
176190
191+
177192def _encode_datetime (dttime ):
178193 if dttime .tzinfo and dttime .tzinfo .utcoffset (dttime ) is not None :
179194 utc_timestamp = calendar .timegm (dttime .utctimetuple ())
@@ -182,29 +197,33 @@ def _encode_datetime(dttime):
182197
183198 return int (utc_timestamp )
184199
200+
185201def _api_encode (data ):
186202 for key , value in data .items ():
187203 if value is None :
188204 continue
189- elif hasattr (value , ' payjp_id' ):
205+ elif hasattr (value , " payjp_id" ):
190206 yield (key , value .payjp_id )
191207 elif isinstance (value , list ) or isinstance (value , tuple ):
192208 for subvalue in value :
193209 yield ("%s[]" % (key ,), subvalue )
194210 elif isinstance (value , dict ):
195- subdict = dict (('%s[%s]' % (key , subkey ), subvalue ) for
196- subkey , subvalue in value .items ())
211+ subdict = dict (
212+ ("%s[%s]" % (key , subkey ), subvalue )
213+ for subkey , subvalue in value .items ()
214+ )
197215 for subkey , subvalue in _api_encode (subdict ):
198216 yield (subkey , subvalue )
199217 elif isinstance (value , datetime .datetime ):
200218 yield (key , _encode_datetime (value ))
201219 else :
202220 yield (key , value )
203221
222+
204223def _build_api_url (url , query ):
205224 scheme , netloc , path , base_query , fragment = urlsplit (url )
206225
207226 if base_query :
208- query = ' %s&%s' % (base_query , query )
227+ query = " %s&%s" % (base_query , query )
209228
210229 return urlunsplit ((scheme , netloc , path , query , fragment ))
0 commit comments