18
18
# currently usable by the CLI.
19
19
20
20
# TODO: Extend kapigen to add a boolean to these requests indicating that they use forms.
21
- REQUESTS_REQUIRING_FORMS = ['ApiUploadDatasetFileRequest' , 'ApiCreateSubmissionRequest' , 'ApiCreateCodeSubmissionRequest' , 'ApiStartSubmissionUploadRequest' , 'ApiUploadModelFileRequest' ]
21
+ REQUESTS_REQUIRING_FORMS = [
22
+ 'ApiUploadDatasetFileRequest' ,
23
+ 'ApiCreateSubmissionRequest' ,
24
+ 'ApiCreateCodeSubmissionRequest' ,
25
+ 'ApiStartSubmissionUploadRequest' ,
26
+ 'ApiUploadModelFileRequest' ,
27
+ ]
28
+
22
29
23
30
def _headers_to_str (headers ):
24
31
return '\n ' .join (f'{ k } : { v } ' for k , v in headers .items ())
@@ -44,7 +51,9 @@ def _get_apikey_creds():
44
51
45
52
def clean_data (data ):
46
53
if isinstance (data , dict ):
47
- return {to_lower_camel_case (k ): clean_data (v ) for k , v in data .items () if v is not None }
54
+ return {
55
+ to_lower_camel_case (k ): clean_data (v ) for k , v in data .items () if v is not None
56
+ }
48
57
if isinstance (data , list ):
49
58
return [clean_data (v ) for v in data if v is not None ]
50
59
if data is True :
@@ -53,6 +62,7 @@ def clean_data(data):
53
62
return 'false'
54
63
return data
55
64
65
+
56
66
def find_words (source , left = '{' , right = '}' ):
57
67
words = []
58
68
split_str = source .split (left )
@@ -64,8 +74,10 @@ def find_words(source, left='{', right='}'):
64
74
65
75
return words
66
76
77
+
67
78
def to_camel_case (snake_str ):
68
- return "" .join (x .capitalize () for x in snake_str .lower ().split ("_" ))
79
+ return '' .join (x .capitalize () for x in snake_str .lower ().split ('_' ))
80
+
69
81
70
82
def to_lower_camel_case (snake_str ):
71
83
# https://stackoverflow.com/questions/19053707/converting-snake-case-to-lower-camel-case-lowercamelcase
@@ -74,18 +86,21 @@ def to_lower_camel_case(snake_str):
74
86
camel_string = to_camel_case (snake_str )
75
87
return snake_str [0 ].lower () + camel_string [1 :]
76
88
89
+
77
90
class KaggleHttpClient (object ):
78
91
_xsrf_cookie_name = 'XSRF-TOKEN'
79
- _csrf_cookie_name = " CSRF-TOKEN"
92
+ _csrf_cookie_name = ' CSRF-TOKEN'
80
93
_xsrf_cookies = (_xsrf_cookie_name , _csrf_cookie_name )
81
94
_xsrf_header_name = 'X-XSRF-TOKEN'
82
95
83
- def __init__ (self ,
84
- env : KaggleEnv = None ,
85
- verbose : bool = False ,
86
- renew_iap_token = None ,
87
- username = None ,
88
- password = None ):
96
+ def __init__ (
97
+ self ,
98
+ env : KaggleEnv = None ,
99
+ verbose : bool = False ,
100
+ renew_iap_token = None ,
101
+ username = None ,
102
+ password = None ,
103
+ ):
89
104
self ._env = env or get_env ()
90
105
self ._signed_in = None
91
106
self ._endpoint = get_endpoint (self ._env )
@@ -94,8 +109,13 @@ def __init__(self,
94
109
self ._username = username
95
110
self ._password = password
96
111
97
- def call (self , service_name : str , request_name : str , request : KaggleObject ,
98
- response_type : Type [KaggleObject ]):
112
+ def call (
113
+ self ,
114
+ service_name : str ,
115
+ request_name : str ,
116
+ request : KaggleObject ,
117
+ response_type : Type [KaggleObject ],
118
+ ):
99
119
self ._init_session ()
100
120
http_request = self ._prepare_request (service_name , request_name , request )
101
121
@@ -104,11 +124,12 @@ def call(self, service_name: str, request_name: str, request: KaggleObject,
104
124
response = self ._prepare_response (response_type , http_response )
105
125
return response
106
126
107
- def _prepare_request (self , service_name : str , request_name : str ,
108
- request : KaggleObject ):
127
+ def _prepare_request (
128
+ self , service_name : str , request_name : str , request : KaggleObject
129
+ ):
109
130
request_url = self ._get_request_url (request )
110
131
method = request .method ()
111
- data = ''
132
+ data = ''
112
133
if method == 'GET' :
113
134
data = request .__class__ .to_dict (request , ignore_defaults = False )
114
135
if request .endpoint_path ():
@@ -119,10 +140,12 @@ def _prepare_request(self, service_name: str, request_name: str,
119
140
if data :
120
141
request_url = f'{ request_url } ?{ urllib .parse .urlencode (clean_data (data ))} '
121
142
data = ''
122
- self ._session .headers .update ({
123
- 'Accept' : 'application/json' ,
124
- 'Content-Type' : 'text/plain' ,
125
- })
143
+ self ._session .headers .update (
144
+ {
145
+ 'Accept' : 'application/json' ,
146
+ 'Content-Type' : 'text/plain' ,
147
+ }
148
+ )
126
149
elif method == 'POST' :
127
150
data = request .to_field_map (request , ignore_defaults = True )
128
151
if isinstance (data , dict ):
@@ -136,17 +159,20 @@ def _prepare_request(self, service_name: str, request_name: str,
136
159
else :
137
160
content_type = 'application/json'
138
161
data = json .dumps (data )
139
- self ._session .headers .update ({
140
- 'Accept' : 'application/json' ,
141
- 'Content-Type' : content_type ,
142
- })
162
+ self ._session .headers .update (
163
+ {
164
+ 'Accept' : 'application/json' ,
165
+ 'Content-Type' : content_type ,
166
+ }
167
+ )
143
168
http_request = requests .Request (
144
- method = method ,
145
- url = request_url ,
146
- data = data ,
147
- headers = self ._session .headers ,
148
- # cookies=self._get_xsrf_cookies(),
149
- auth = self ._session .auth )
169
+ method = method ,
170
+ url = request_url ,
171
+ data = data ,
172
+ headers = self ._session .headers ,
173
+ # cookies=self._get_xsrf_cookies(),
174
+ auth = self ._session .auth ,
175
+ )
150
176
prepared_request = http_request .prepare ()
151
177
self ._print_request (prepared_request )
152
178
return prepared_request
@@ -164,8 +190,7 @@ def _prepare_response(self, response_type, http_response):
164
190
if 'application/json' in http_response .headers ['Content-Type' ]:
165
191
resp = http_response .json ()
166
192
if 'code' in resp and resp ['code' ] >= 400 :
167
- raise requests .exceptions .HTTPError (
168
- resp ['message' ], response = http_response )
193
+ raise requests .exceptions .HTTPError (resp ['message' ], response = http_response )
169
194
if response_type is None : # Method doesn't have a return type
170
195
return None
171
196
return response_type .prepare_from (http_response )
@@ -175,8 +200,8 @@ def _print_request(self, request):
175
200
return
176
201
self ._print ('---------------------Request----------------------' )
177
202
self ._print (
178
- f'{ request .method } { request .url } \n { _headers_to_str (request .headers )} \n \n { request .body } '
179
- )
203
+ f'{ request .method } { request .url } \n { _headers_to_str (request .headers )} \n \n { request .body } '
204
+ )
180
205
self ._print ('--------------------------------------------------' )
181
206
182
207
def _print_response (self , response , body = True ):
@@ -205,17 +230,21 @@ def _init_session(self):
205
230
return self ._session
206
231
207
232
self ._session = requests .Session ()
208
- self ._session .headers .update ({
209
- 'User-Agent' : 'kaggle-api/v1.7.0' , # Was: V2
210
- 'Content-Type' : 'application/x-www-form-urlencoded' , # Was: /json
211
- })
233
+ self ._session .headers .update (
234
+ {
235
+ 'User-Agent' : 'kaggle-api/v1.7.0' , # Was: V2
236
+ 'Content-Type' : 'application/x-www-form-urlencoded' , # Was: /json
237
+ }
238
+ )
212
239
213
240
iap_token = self ._get_iap_token_if_required ()
214
241
if iap_token is not None :
215
- self ._session .headers .update ({
216
- # https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_proxy-authorization_header
217
- 'Proxy-Authorization' : f'Bearer { iap_token } ' ,
218
- })
242
+ self ._session .headers .update (
243
+ {
244
+ # https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_proxy-authorization_header
245
+ 'Proxy-Authorization' : f'Bearer { iap_token } ' ,
246
+ }
247
+ )
219
248
220
249
self ._try_fill_auth ()
221
250
# self._fill_xsrf_token(iap_token) # TODO Make this align with original handler.
@@ -230,10 +259,11 @@ def _get_iap_token_if_required(self):
230
259
231
260
def _fill_xsrf_token (self , iap_token ):
232
261
initial_get_request = requests .Request (
233
- method = 'GET' ,
234
- url = self ._endpoint ,
235
- headers = self ._session .headers ,
236
- auth = self ._session .auth )
262
+ method = 'GET' ,
263
+ url = self ._endpoint ,
264
+ headers = self ._session .headers ,
265
+ auth = self ._session .auth ,
266
+ )
237
267
prepared_request = initial_get_request .prepare ()
238
268
self ._print_request (prepared_request )
239
269
@@ -244,18 +274,21 @@ def _fill_xsrf_token(self, iap_token):
244
274
raise requests .exceptions .HTTPError ('IAP token invalid or expired' )
245
275
http_response .raise_for_status ()
246
276
247
- self ._session .headers .update ({
248
- KaggleHttpClient ._xsrf_header_name :
249
- self ._session .cookies [KaggleHttpClient ._xsrf_cookie_name ],
250
- })
277
+ self ._session .headers .update (
278
+ {
279
+ KaggleHttpClient ._xsrf_header_name : self ._session .cookies [
280
+ KaggleHttpClient ._xsrf_cookie_name
281
+ ],
282
+ }
283
+ )
251
284
252
285
class BearerAuth (requests .auth .AuthBase ):
253
286
254
287
def __init__ (self , token ):
255
288
self .token = token
256
289
257
290
def __call__ (self , r ):
258
- r .headers [" Authorization" ] = f" Bearer { self .token } "
291
+ r .headers [' Authorization' ] = f' Bearer { self .token } '
259
292
return r
260
293
261
294
def _try_fill_auth (self ):
@@ -286,11 +319,11 @@ def _get_request_url(self, request):
286
319
def make_form (fields ):
287
320
body = BytesIO ()
288
321
boundary = binascii .hexlify (os .urandom (16 )).decode ()
289
- writer = codecs .lookup (" utf-8" )[3 ]
322
+ writer = codecs .lookup (' utf-8' )[3 ]
290
323
291
324
for field in fields .items ():
292
325
field = RequestField .from_tuples (* field )
293
- body .write (f" --{ boundary } \r \n " .encode (" latin-1" ))
326
+ body .write (f' --{ boundary } \r \n ' .encode (' latin-1' ))
294
327
295
328
writer (body ).write (field .render_headers ())
296
329
data = field .data
@@ -303,11 +336,11 @@ def make_form(fields):
303
336
else :
304
337
body .write (data )
305
338
306
- body .write (b" \r \n " )
339
+ body .write (b' \r \n ' )
307
340
308
- body .write (f" --{ boundary } --\r \n " .encode (" latin-1" ))
341
+ body .write (f' --{ boundary } --\r \n ' .encode (' latin-1' ))
309
342
310
- content_type = f" multipart/form-data; boundary={ boundary } "
343
+ content_type = f' multipart/form-data; boundary={ boundary } '
311
344
312
345
return body .getvalue (), content_type
313
346
0 commit comments