kaggle 1.7.4.2__py3-none-any.whl → 1.7.4.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kaggle/api/kaggle_api.py +92 -79
- kaggle/api/kaggle_api_extended.py +907 -876
- kaggle/configuration.py +3 -3
- kaggle/models/dataset_column.py +58 -49
- kaggle/models/dataset_new_request.py +47 -31
- kaggle/models/dataset_new_version_request.py +56 -31
- kaggle/models/dataset_update_settings_request.py +58 -32
- kaggle/models/kernel_push_request.py +86 -51
- kaggle/models/model_instance_new_version_request.py +20 -12
- kaggle/models/model_instance_update_request.py +68 -37
- kaggle/models/model_new_instance_request.py +85 -47
- kaggle/models/model_new_request.py +26 -19
- kaggle/models/model_update_request.py +34 -23
- kaggle/models/start_blob_upload_request.py +60 -49
- kaggle/models/start_blob_upload_response.py +27 -22
- kaggle/models/upload_file.py +33 -31
- {kaggle-1.7.4.2.dist-info → kaggle-1.7.4.5.dist-info}/METADATA +1 -1
- {kaggle-1.7.4.2.dist-info → kaggle-1.7.4.5.dist-info}/RECORD +40 -31
- kagglesdk/__init__.py +1 -1
- kagglesdk/datasets/types/dataset_api_service.py +16 -0
- kagglesdk/kaggle_client.py +12 -0
- kagglesdk/kaggle_env.py +9 -11
- kagglesdk/kaggle_http_client.py +91 -56
- kagglesdk/kaggle_object.py +97 -42
- kagglesdk/kernels/types/kernels_api_service.py +24 -0
- kagglesdk/models/services/model_api_service.py +7 -6
- kagglesdk/models/types/model_api_service.py +31 -15
- kagglesdk/security/__init__.py +0 -0
- kagglesdk/security/services/__init__.py +0 -0
- kagglesdk/security/services/oauth_service.py +32 -0
- kagglesdk/security/types/__init__.py +0 -0
- kagglesdk/security/types/authentication.py +171 -0
- kagglesdk/security/types/oauth_service.py +394 -0
- kagglesdk/test/test_client.py +4 -6
- kagglesdk/users/services/__init__.py +0 -0
- kagglesdk/users/services/account_service.py +19 -0
- kagglesdk/users/types/account_service.py +204 -0
- {kaggle-1.7.4.2.dist-info → kaggle-1.7.4.5.dist-info}/WHEEL +0 -0
- {kaggle-1.7.4.2.dist-info → kaggle-1.7.4.5.dist-info}/entry_points.txt +0 -0
- {kaggle-1.7.4.2.dist-info → kaggle-1.7.4.5.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
from kagglesdk.kaggle_object import *
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
class ExchangeOAuthTokenRequest(KaggleObject):
|
|
5
|
+
r"""
|
|
6
|
+
Attributes:
|
|
7
|
+
code (str)
|
|
8
|
+
Temporary OAuth code that was generated by the backend based on OAuth
|
|
9
|
+
parameters passed to the '/api/v1/oauth2/authorize' (StartOAuthFlowRequest)
|
|
10
|
+
endpoint. This is also known as OAuth flow token. It is sent to the flow
|
|
11
|
+
initiator as a query string parameter to their redirect_uri
|
|
12
|
+
(https://dataverse.org?code=808f9afcabb3489a8b30353a8ae4dc4b)
|
|
13
|
+
code_verifier (str)
|
|
14
|
+
Original code_verifier (hash of code_challenge) for PKCE protection.
|
|
15
|
+
grant_type (str)
|
|
16
|
+
Must be set to 'authorization_code'.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
self._code = ""
|
|
21
|
+
self._code_verifier = None
|
|
22
|
+
self._grant_type = ""
|
|
23
|
+
self._freeze()
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def code(self) -> str:
|
|
27
|
+
r"""
|
|
28
|
+
Temporary OAuth code that was generated by the backend based on OAuth
|
|
29
|
+
parameters passed to the '/api/v1/oauth2/authorize' (StartOAuthFlowRequest)
|
|
30
|
+
endpoint. This is also known as OAuth flow token. It is sent to the flow
|
|
31
|
+
initiator as a query string parameter to their redirect_uri
|
|
32
|
+
(https://dataverse.org?code=808f9afcabb3489a8b30353a8ae4dc4b)
|
|
33
|
+
"""
|
|
34
|
+
return self._code
|
|
35
|
+
|
|
36
|
+
@code.setter
|
|
37
|
+
def code(self, code: str):
|
|
38
|
+
if code is None:
|
|
39
|
+
del self.code
|
|
40
|
+
return
|
|
41
|
+
if not isinstance(code, str):
|
|
42
|
+
raise TypeError('code must be of type str')
|
|
43
|
+
self._code = code
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def code_verifier(self) -> str:
|
|
47
|
+
"""Original code_verifier (hash of code_challenge) for PKCE protection."""
|
|
48
|
+
return self._code_verifier or ""
|
|
49
|
+
|
|
50
|
+
@code_verifier.setter
|
|
51
|
+
def code_verifier(self, code_verifier: str):
|
|
52
|
+
if code_verifier is None:
|
|
53
|
+
del self.code_verifier
|
|
54
|
+
return
|
|
55
|
+
if not isinstance(code_verifier, str):
|
|
56
|
+
raise TypeError('code_verifier must be of type str')
|
|
57
|
+
self._code_verifier = code_verifier
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def grant_type(self) -> str:
|
|
61
|
+
"""Must be set to 'authorization_code'."""
|
|
62
|
+
return self._grant_type
|
|
63
|
+
|
|
64
|
+
@grant_type.setter
|
|
65
|
+
def grant_type(self, grant_type: str):
|
|
66
|
+
if grant_type is None:
|
|
67
|
+
del self.grant_type
|
|
68
|
+
return
|
|
69
|
+
if not isinstance(grant_type, str):
|
|
70
|
+
raise TypeError('grant_type must be of type str')
|
|
71
|
+
self._grant_type = grant_type
|
|
72
|
+
|
|
73
|
+
def endpoint(self):
|
|
74
|
+
path = '/api/v1/oauth2/token'
|
|
75
|
+
return path.format_map(self.to_field_map(self))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def method():
|
|
80
|
+
return 'POST'
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
def body_fields():
|
|
84
|
+
return '*'
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class ExchangeOAuthTokenResponse(KaggleObject):
|
|
88
|
+
r"""
|
|
89
|
+
Attributes:
|
|
90
|
+
access_token (str)
|
|
91
|
+
Short-lived access token.
|
|
92
|
+
refresh_token (str)
|
|
93
|
+
Long-lived refresh token that can be used to generate access tokens using
|
|
94
|
+
the '/api/v1/access-tokens/generate' (GenerateAccessTokenRequest) endpoint.
|
|
95
|
+
token_type (str)
|
|
96
|
+
Type of the token. Set to 'Bearer'.
|
|
97
|
+
expires_in (int)
|
|
98
|
+
Lifetime of the access token in seconds.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
def __init__(self):
|
|
102
|
+
self._access_token = ""
|
|
103
|
+
self._refresh_token = ""
|
|
104
|
+
self._token_type = ""
|
|
105
|
+
self._expires_in = 0
|
|
106
|
+
self._freeze()
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def access_token(self) -> str:
|
|
110
|
+
"""Short-lived access token."""
|
|
111
|
+
return self._access_token
|
|
112
|
+
|
|
113
|
+
@access_token.setter
|
|
114
|
+
def access_token(self, access_token: str):
|
|
115
|
+
if access_token is None:
|
|
116
|
+
del self.access_token
|
|
117
|
+
return
|
|
118
|
+
if not isinstance(access_token, str):
|
|
119
|
+
raise TypeError('access_token must be of type str')
|
|
120
|
+
self._access_token = access_token
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def refresh_token(self) -> str:
|
|
124
|
+
r"""
|
|
125
|
+
Long-lived refresh token that can be used to generate access tokens using
|
|
126
|
+
the '/api/v1/access-tokens/generate' (GenerateAccessTokenRequest) endpoint.
|
|
127
|
+
"""
|
|
128
|
+
return self._refresh_token
|
|
129
|
+
|
|
130
|
+
@refresh_token.setter
|
|
131
|
+
def refresh_token(self, refresh_token: str):
|
|
132
|
+
if refresh_token is None:
|
|
133
|
+
del self.refresh_token
|
|
134
|
+
return
|
|
135
|
+
if not isinstance(refresh_token, str):
|
|
136
|
+
raise TypeError('refresh_token must be of type str')
|
|
137
|
+
self._refresh_token = refresh_token
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def token_type(self) -> str:
|
|
141
|
+
"""Type of the token. Set to 'Bearer'."""
|
|
142
|
+
return self._token_type
|
|
143
|
+
|
|
144
|
+
@token_type.setter
|
|
145
|
+
def token_type(self, token_type: str):
|
|
146
|
+
if token_type is None:
|
|
147
|
+
del self.token_type
|
|
148
|
+
return
|
|
149
|
+
if not isinstance(token_type, str):
|
|
150
|
+
raise TypeError('token_type must be of type str')
|
|
151
|
+
self._token_type = token_type
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def expires_in(self) -> int:
|
|
155
|
+
"""Lifetime of the access token in seconds."""
|
|
156
|
+
return self._expires_in
|
|
157
|
+
|
|
158
|
+
@expires_in.setter
|
|
159
|
+
def expires_in(self, expires_in: int):
|
|
160
|
+
if expires_in is None:
|
|
161
|
+
del self.expires_in
|
|
162
|
+
return
|
|
163
|
+
if not isinstance(expires_in, int):
|
|
164
|
+
raise TypeError('expires_in must be of type int')
|
|
165
|
+
self._expires_in = expires_in
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def accessToken(self):
|
|
169
|
+
return self.access_token
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def refreshToken(self):
|
|
173
|
+
return self.refresh_token
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def tokenType(self):
|
|
177
|
+
return self.token_type
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def expiresIn(self):
|
|
181
|
+
return self.expires_in
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class StartOAuthFlowRequest(KaggleObject):
|
|
185
|
+
r"""
|
|
186
|
+
Attributes:
|
|
187
|
+
client_id (str)
|
|
188
|
+
Client id that is initiating this OAuth flow.
|
|
189
|
+
redirect_uri (str)
|
|
190
|
+
Url to redirect the user after the OAuth flow is complete. For example, if
|
|
191
|
+
you specify https://dataverse.org/auth/kaggle, you will receive a request
|
|
192
|
+
like
|
|
193
|
+
https://dataverse.org/auth/kaggle?code=808f9afcabb3489a8b30353a8ae4dc4b.
|
|
194
|
+
Note that this url must match the allowed urls defined for your OAuth
|
|
195
|
+
client. Also it must be a loopback url for public clients.
|
|
196
|
+
scope (str)
|
|
197
|
+
Set of authorization scopes to restrict the generated tokens. Must be
|
|
198
|
+
specified.
|
|
199
|
+
state (str)
|
|
200
|
+
Random string to protect against CSRF attacks.
|
|
201
|
+
code_challenge (str)
|
|
202
|
+
Hash of the random 'code_verifier' string generated by the caller. The
|
|
203
|
+
client will later send the 'code_verifier' to the backend, which will
|
|
204
|
+
verify its hash against this value (see the 'api/v1/oauth2/exchange'
|
|
205
|
+
(ExchangeOAuthTokenRequest) endpoint). Required for public clients.
|
|
206
|
+
code_challenge_method (str)
|
|
207
|
+
Code challenge method used to hash the 'code_challenge' above. Must be set
|
|
208
|
+
to 'S256', which means the SHA-256 hash of the 'code_verifier', Base64URL
|
|
209
|
+
encoded. Required for public clients.
|
|
210
|
+
response_type (str)
|
|
211
|
+
Type of the OAuth flow completed response. Must be set to 'code', which
|
|
212
|
+
means OAuth code will be sent instead of a refresh token.
|
|
213
|
+
response_mode (str)
|
|
214
|
+
Mode of the OAuth flow completed response. Must be set to 'query', which
|
|
215
|
+
means response will be sent as query string parameters.
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
def __init__(self):
|
|
219
|
+
self._client_id = ""
|
|
220
|
+
self._redirect_uri = ""
|
|
221
|
+
self._scope = ""
|
|
222
|
+
self._state = ""
|
|
223
|
+
self._code_challenge = None
|
|
224
|
+
self._code_challenge_method = None
|
|
225
|
+
self._response_type = ""
|
|
226
|
+
self._response_mode = ""
|
|
227
|
+
self._freeze()
|
|
228
|
+
|
|
229
|
+
@property
|
|
230
|
+
def client_id(self) -> str:
|
|
231
|
+
"""Client id that is initiating this OAuth flow."""
|
|
232
|
+
return self._client_id
|
|
233
|
+
|
|
234
|
+
@client_id.setter
|
|
235
|
+
def client_id(self, client_id: str):
|
|
236
|
+
if client_id is None:
|
|
237
|
+
del self.client_id
|
|
238
|
+
return
|
|
239
|
+
if not isinstance(client_id, str):
|
|
240
|
+
raise TypeError('client_id must be of type str')
|
|
241
|
+
self._client_id = client_id
|
|
242
|
+
|
|
243
|
+
@property
|
|
244
|
+
def redirect_uri(self) -> str:
|
|
245
|
+
r"""
|
|
246
|
+
Url to redirect the user after the OAuth flow is complete. For example, if
|
|
247
|
+
you specify https://dataverse.org/auth/kaggle, you will receive a request
|
|
248
|
+
like
|
|
249
|
+
https://dataverse.org/auth/kaggle?code=808f9afcabb3489a8b30353a8ae4dc4b.
|
|
250
|
+
Note that this url must match the allowed urls defined for your OAuth
|
|
251
|
+
client. Also it must be a loopback url for public clients.
|
|
252
|
+
"""
|
|
253
|
+
return self._redirect_uri
|
|
254
|
+
|
|
255
|
+
@redirect_uri.setter
|
|
256
|
+
def redirect_uri(self, redirect_uri: str):
|
|
257
|
+
if redirect_uri is None:
|
|
258
|
+
del self.redirect_uri
|
|
259
|
+
return
|
|
260
|
+
if not isinstance(redirect_uri, str):
|
|
261
|
+
raise TypeError('redirect_uri must be of type str')
|
|
262
|
+
self._redirect_uri = redirect_uri
|
|
263
|
+
|
|
264
|
+
@property
|
|
265
|
+
def scope(self) -> str:
|
|
266
|
+
r"""
|
|
267
|
+
Set of authorization scopes to restrict the generated tokens. Must be
|
|
268
|
+
specified.
|
|
269
|
+
"""
|
|
270
|
+
return self._scope
|
|
271
|
+
|
|
272
|
+
@scope.setter
|
|
273
|
+
def scope(self, scope: str):
|
|
274
|
+
if scope is None:
|
|
275
|
+
del self.scope
|
|
276
|
+
return
|
|
277
|
+
if not isinstance(scope, str):
|
|
278
|
+
raise TypeError('scope must be of type str')
|
|
279
|
+
self._scope = scope
|
|
280
|
+
|
|
281
|
+
@property
|
|
282
|
+
def state(self) -> str:
|
|
283
|
+
"""Random string to protect against CSRF attacks."""
|
|
284
|
+
return self._state
|
|
285
|
+
|
|
286
|
+
@state.setter
|
|
287
|
+
def state(self, state: str):
|
|
288
|
+
if state is None:
|
|
289
|
+
del self.state
|
|
290
|
+
return
|
|
291
|
+
if not isinstance(state, str):
|
|
292
|
+
raise TypeError('state must be of type str')
|
|
293
|
+
self._state = state
|
|
294
|
+
|
|
295
|
+
@property
|
|
296
|
+
def code_challenge(self) -> str:
|
|
297
|
+
r"""
|
|
298
|
+
Hash of the random 'code_verifier' string generated by the caller. The
|
|
299
|
+
client will later send the 'code_verifier' to the backend, which will
|
|
300
|
+
verify its hash against this value (see the 'api/v1/oauth2/exchange'
|
|
301
|
+
(ExchangeOAuthTokenRequest) endpoint). Required for public clients.
|
|
302
|
+
"""
|
|
303
|
+
return self._code_challenge or ""
|
|
304
|
+
|
|
305
|
+
@code_challenge.setter
|
|
306
|
+
def code_challenge(self, code_challenge: str):
|
|
307
|
+
if code_challenge is None:
|
|
308
|
+
del self.code_challenge
|
|
309
|
+
return
|
|
310
|
+
if not isinstance(code_challenge, str):
|
|
311
|
+
raise TypeError('code_challenge must be of type str')
|
|
312
|
+
self._code_challenge = code_challenge
|
|
313
|
+
|
|
314
|
+
@property
|
|
315
|
+
def code_challenge_method(self) -> str:
|
|
316
|
+
r"""
|
|
317
|
+
Code challenge method used to hash the 'code_challenge' above. Must be set
|
|
318
|
+
to 'S256', which means the SHA-256 hash of the 'code_verifier', Base64URL
|
|
319
|
+
encoded. Required for public clients.
|
|
320
|
+
"""
|
|
321
|
+
return self._code_challenge_method or ""
|
|
322
|
+
|
|
323
|
+
@code_challenge_method.setter
|
|
324
|
+
def code_challenge_method(self, code_challenge_method: str):
|
|
325
|
+
if code_challenge_method is None:
|
|
326
|
+
del self.code_challenge_method
|
|
327
|
+
return
|
|
328
|
+
if not isinstance(code_challenge_method, str):
|
|
329
|
+
raise TypeError('code_challenge_method must be of type str')
|
|
330
|
+
self._code_challenge_method = code_challenge_method
|
|
331
|
+
|
|
332
|
+
@property
|
|
333
|
+
def response_type(self) -> str:
|
|
334
|
+
r"""
|
|
335
|
+
Type of the OAuth flow completed response. Must be set to 'code', which
|
|
336
|
+
means OAuth code will be sent instead of a refresh token.
|
|
337
|
+
"""
|
|
338
|
+
return self._response_type
|
|
339
|
+
|
|
340
|
+
@response_type.setter
|
|
341
|
+
def response_type(self, response_type: str):
|
|
342
|
+
if response_type is None:
|
|
343
|
+
del self.response_type
|
|
344
|
+
return
|
|
345
|
+
if not isinstance(response_type, str):
|
|
346
|
+
raise TypeError('response_type must be of type str')
|
|
347
|
+
self._response_type = response_type
|
|
348
|
+
|
|
349
|
+
@property
|
|
350
|
+
def response_mode(self) -> str:
|
|
351
|
+
r"""
|
|
352
|
+
Mode of the OAuth flow completed response. Must be set to 'query', which
|
|
353
|
+
means response will be sent as query string parameters.
|
|
354
|
+
"""
|
|
355
|
+
return self._response_mode
|
|
356
|
+
|
|
357
|
+
@response_mode.setter
|
|
358
|
+
def response_mode(self, response_mode: str):
|
|
359
|
+
if response_mode is None:
|
|
360
|
+
del self.response_mode
|
|
361
|
+
return
|
|
362
|
+
if not isinstance(response_mode, str):
|
|
363
|
+
raise TypeError('response_mode must be of type str')
|
|
364
|
+
self._response_mode = response_mode
|
|
365
|
+
|
|
366
|
+
def endpoint(self):
|
|
367
|
+
path = '/api/v1/oauth2/authorize'
|
|
368
|
+
return path.format_map(self.to_field_map(self))
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
ExchangeOAuthTokenRequest._fields = [
|
|
372
|
+
FieldMetadata("code", "code", "_code", str, "", PredefinedSerializer()),
|
|
373
|
+
FieldMetadata("codeVerifier", "code_verifier", "_code_verifier", str, None, PredefinedSerializer(), optional=True),
|
|
374
|
+
FieldMetadata("grantType", "grant_type", "_grant_type", str, "", PredefinedSerializer()),
|
|
375
|
+
]
|
|
376
|
+
|
|
377
|
+
ExchangeOAuthTokenResponse._fields = [
|
|
378
|
+
FieldMetadata("accessToken", "access_token", "_access_token", str, "", PredefinedSerializer()),
|
|
379
|
+
FieldMetadata("refreshToken", "refresh_token", "_refresh_token", str, "", PredefinedSerializer()),
|
|
380
|
+
FieldMetadata("tokenType", "token_type", "_token_type", str, "", PredefinedSerializer()),
|
|
381
|
+
FieldMetadata("expiresIn", "expires_in", "_expires_in", int, 0, PredefinedSerializer()),
|
|
382
|
+
]
|
|
383
|
+
|
|
384
|
+
StartOAuthFlowRequest._fields = [
|
|
385
|
+
FieldMetadata("clientId", "client_id", "_client_id", str, "", PredefinedSerializer()),
|
|
386
|
+
FieldMetadata("redirectUri", "redirect_uri", "_redirect_uri", str, "", PredefinedSerializer()),
|
|
387
|
+
FieldMetadata("scope", "scope", "_scope", str, "", PredefinedSerializer()),
|
|
388
|
+
FieldMetadata("state", "state", "_state", str, "", PredefinedSerializer()),
|
|
389
|
+
FieldMetadata("codeChallenge", "code_challenge", "_code_challenge", str, None, PredefinedSerializer(), optional=True),
|
|
390
|
+
FieldMetadata("codeChallengeMethod", "code_challenge_method", "_code_challenge_method", str, None, PredefinedSerializer(), optional=True),
|
|
391
|
+
FieldMetadata("responseType", "response_type", "_response_type", str, "", PredefinedSerializer()),
|
|
392
|
+
FieldMetadata("responseMode", "response_mode", "_response_mode", str, "", PredefinedSerializer()),
|
|
393
|
+
]
|
|
394
|
+
|
kagglesdk/test/test_client.py
CHANGED
|
@@ -10,10 +10,10 @@ import unittest
|
|
|
10
10
|
class TestClient(unittest.TestCase):
|
|
11
11
|
|
|
12
12
|
def setUp(self):
|
|
13
|
-
print(
|
|
13
|
+
print('setup class:%s' % self)
|
|
14
14
|
|
|
15
15
|
def tearDown(self):
|
|
16
|
-
print(
|
|
16
|
+
print('teardown class:TestStuff')
|
|
17
17
|
|
|
18
18
|
# Environment
|
|
19
19
|
|
|
@@ -30,10 +30,8 @@ class TestClient(unittest.TestCase):
|
|
|
30
30
|
|
|
31
31
|
def test_kaggle_client(self):
|
|
32
32
|
client = KaggleClient(
|
|
33
|
-
env=KaggleEnv.PROD,
|
|
34
|
-
|
|
35
|
-
username='dinosaur',
|
|
36
|
-
password='xxxxxxxxxxxx')
|
|
33
|
+
env=KaggleEnv.PROD, verbose=False, username='dinosaur', password='xxxxxxxxxxxx'
|
|
34
|
+
)
|
|
37
35
|
|
|
38
36
|
self.assertEqual(client.username, 'dinosaur')
|
|
39
37
|
self.assertEqual(client.password, 'xxxxxxxxxxxx')
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from kagglesdk.kaggle_http_client import KaggleHttpClient
|
|
2
|
+
from kagglesdk.users.types.account_service import GenerateAccessTokenRequest, GenerateAccessTokenResponse
|
|
3
|
+
|
|
4
|
+
class AccountClient(object):
|
|
5
|
+
|
|
6
|
+
def __init__(self, client: KaggleHttpClient):
|
|
7
|
+
self._client = client
|
|
8
|
+
|
|
9
|
+
def generate_access_token(self, request: GenerateAccessTokenRequest = None) -> GenerateAccessTokenResponse:
|
|
10
|
+
r"""
|
|
11
|
+
Args:
|
|
12
|
+
request (GenerateAccessTokenRequest):
|
|
13
|
+
The request object; initialized to empty instance if not specified.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
if request is None:
|
|
17
|
+
request = GenerateAccessTokenRequest()
|
|
18
|
+
|
|
19
|
+
return self._client.call("users.AccountService", "GenerateAccessToken", request, GenerateAccessTokenResponse)
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
from datetime import timedelta
|
|
2
|
+
import enum
|
|
3
|
+
from kagglesdk.kaggle_object import *
|
|
4
|
+
from kagglesdk.security.types.authentication import AuthorizationScope
|
|
5
|
+
from typing import Optional, List
|
|
6
|
+
|
|
7
|
+
class ApiVersion(enum.Enum):
|
|
8
|
+
API_VERSION_UNSPECIFIED = 0
|
|
9
|
+
API_VERSION_V1 = 1
|
|
10
|
+
"""Publicly available ('/api/v1' endpoints)."""
|
|
11
|
+
API_VERSION_V2 = 2
|
|
12
|
+
"""Experimental, admin-only, internal ('/api/i' endpoints)."""
|
|
13
|
+
|
|
14
|
+
class GenerateAccessTokenRequest(KaggleObject):
|
|
15
|
+
r"""
|
|
16
|
+
Attributes:
|
|
17
|
+
refresh_token (str)
|
|
18
|
+
Refresh token used to generate a short-lived restricted access token.
|
|
19
|
+
If not specified current user credentials will be used to generate an
|
|
20
|
+
unrestricted access token.
|
|
21
|
+
api_version (ApiVersion)
|
|
22
|
+
Version of the Kaggle API for which this token will be used.
|
|
23
|
+
expiration_duration (timedelta)
|
|
24
|
+
Token expiration.
|
|
25
|
+
authorization_context (AuthorizationContext)
|
|
26
|
+
On which context (such as a Kaggle notebook) this token can be used.
|
|
27
|
+
authorization_scopes (AuthorizationScope)
|
|
28
|
+
Set of scopes to further restrict the token. If 'refresh_token' is
|
|
29
|
+
specified, these should be a subset of the scopes allowed by the
|
|
30
|
+
'refresh_token'.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self):
|
|
34
|
+
self._refresh_token = None
|
|
35
|
+
self._api_version = ApiVersion.API_VERSION_UNSPECIFIED
|
|
36
|
+
self._expiration_duration = None
|
|
37
|
+
self._authorization_context = None
|
|
38
|
+
self._authorization_scopes = []
|
|
39
|
+
self._freeze()
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def refresh_token(self) -> str:
|
|
43
|
+
r"""
|
|
44
|
+
Refresh token used to generate a short-lived restricted access token.
|
|
45
|
+
If not specified current user credentials will be used to generate an
|
|
46
|
+
unrestricted access token.
|
|
47
|
+
"""
|
|
48
|
+
return self._refresh_token or ""
|
|
49
|
+
|
|
50
|
+
@refresh_token.setter
|
|
51
|
+
def refresh_token(self, refresh_token: str):
|
|
52
|
+
if refresh_token is None:
|
|
53
|
+
del self.refresh_token
|
|
54
|
+
return
|
|
55
|
+
if not isinstance(refresh_token, str):
|
|
56
|
+
raise TypeError('refresh_token must be of type str')
|
|
57
|
+
self._refresh_token = refresh_token
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def api_version(self) -> 'ApiVersion':
|
|
61
|
+
"""Version of the Kaggle API for which this token will be used."""
|
|
62
|
+
return self._api_version
|
|
63
|
+
|
|
64
|
+
@api_version.setter
|
|
65
|
+
def api_version(self, api_version: 'ApiVersion'):
|
|
66
|
+
if api_version is None:
|
|
67
|
+
del self.api_version
|
|
68
|
+
return
|
|
69
|
+
if not isinstance(api_version, ApiVersion):
|
|
70
|
+
raise TypeError('api_version must be of type ApiVersion')
|
|
71
|
+
self._api_version = api_version
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def expiration_duration(self) -> timedelta:
|
|
75
|
+
"""Token expiration."""
|
|
76
|
+
return self._expiration_duration
|
|
77
|
+
|
|
78
|
+
@expiration_duration.setter
|
|
79
|
+
def expiration_duration(self, expiration_duration: timedelta):
|
|
80
|
+
if expiration_duration is None:
|
|
81
|
+
del self.expiration_duration
|
|
82
|
+
return
|
|
83
|
+
if not isinstance(expiration_duration, timedelta):
|
|
84
|
+
raise TypeError('expiration_duration must be of type timedelta')
|
|
85
|
+
self._expiration_duration = expiration_duration
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def authorization_context(self) -> Optional['AuthorizationContext']:
|
|
89
|
+
"""On which context (such as a Kaggle notebook) this token can be used."""
|
|
90
|
+
return self._authorization_context
|
|
91
|
+
|
|
92
|
+
@authorization_context.setter
|
|
93
|
+
def authorization_context(self, authorization_context: Optional['AuthorizationContext']):
|
|
94
|
+
if authorization_context is None:
|
|
95
|
+
del self.authorization_context
|
|
96
|
+
return
|
|
97
|
+
if not isinstance(authorization_context, AuthorizationContext):
|
|
98
|
+
raise TypeError('authorization_context must be of type AuthorizationContext')
|
|
99
|
+
self._authorization_context = authorization_context
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def authorization_scopes(self) -> Optional[List[Optional['AuthorizationScope']]]:
|
|
103
|
+
r"""
|
|
104
|
+
Set of scopes to further restrict the token. If 'refresh_token' is
|
|
105
|
+
specified, these should be a subset of the scopes allowed by the
|
|
106
|
+
'refresh_token'.
|
|
107
|
+
"""
|
|
108
|
+
return self._authorization_scopes
|
|
109
|
+
|
|
110
|
+
@authorization_scopes.setter
|
|
111
|
+
def authorization_scopes(self, authorization_scopes: Optional[List[Optional['AuthorizationScope']]]):
|
|
112
|
+
if authorization_scopes is None:
|
|
113
|
+
del self.authorization_scopes
|
|
114
|
+
return
|
|
115
|
+
if not isinstance(authorization_scopes, list):
|
|
116
|
+
raise TypeError('authorization_scopes must be of type list')
|
|
117
|
+
if not all([isinstance(t, AuthorizationScope) for t in authorization_scopes]):
|
|
118
|
+
raise TypeError('authorization_scopes must contain only items of type AuthorizationScope')
|
|
119
|
+
self._authorization_scopes = authorization_scopes
|
|
120
|
+
|
|
121
|
+
def endpoint(self):
|
|
122
|
+
path = '/api/v1/access-tokens/generate'
|
|
123
|
+
return path.format_map(self.to_field_map(self))
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@staticmethod
|
|
127
|
+
def method():
|
|
128
|
+
return 'POST'
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def body_fields():
|
|
132
|
+
return '*'
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class GenerateAccessTokenResponse(KaggleObject):
|
|
136
|
+
r"""
|
|
137
|
+
Attributes:
|
|
138
|
+
token (str)
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
def __init__(self):
|
|
142
|
+
self._token = ""
|
|
143
|
+
self._freeze()
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def token(self) -> str:
|
|
147
|
+
return self._token
|
|
148
|
+
|
|
149
|
+
@token.setter
|
|
150
|
+
def token(self, token: str):
|
|
151
|
+
if token is None:
|
|
152
|
+
del self.token
|
|
153
|
+
return
|
|
154
|
+
if not isinstance(token, str):
|
|
155
|
+
raise TypeError('token must be of type str')
|
|
156
|
+
self._token = token
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class AuthorizationContext(KaggleObject):
|
|
160
|
+
r"""
|
|
161
|
+
Attributes:
|
|
162
|
+
kernel_session_id (int)
|
|
163
|
+
If set, access token is restricted to be used only from the specified
|
|
164
|
+
notebook session.
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
def __init__(self):
|
|
168
|
+
self._kernel_session_id = None
|
|
169
|
+
self._freeze()
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def kernel_session_id(self) -> int:
|
|
173
|
+
r"""
|
|
174
|
+
If set, access token is restricted to be used only from the specified
|
|
175
|
+
notebook session.
|
|
176
|
+
"""
|
|
177
|
+
return self._kernel_session_id or 0
|
|
178
|
+
|
|
179
|
+
@kernel_session_id.setter
|
|
180
|
+
def kernel_session_id(self, kernel_session_id: int):
|
|
181
|
+
if kernel_session_id is None:
|
|
182
|
+
del self.kernel_session_id
|
|
183
|
+
return
|
|
184
|
+
if not isinstance(kernel_session_id, int):
|
|
185
|
+
raise TypeError('kernel_session_id must be of type int')
|
|
186
|
+
self._kernel_session_id = kernel_session_id
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
GenerateAccessTokenRequest._fields = [
|
|
190
|
+
FieldMetadata("refreshToken", "refresh_token", "_refresh_token", str, None, PredefinedSerializer(), optional=True),
|
|
191
|
+
FieldMetadata("apiVersion", "api_version", "_api_version", ApiVersion, ApiVersion.API_VERSION_UNSPECIFIED, EnumSerializer()),
|
|
192
|
+
FieldMetadata("expirationDuration", "expiration_duration", "_expiration_duration", timedelta, None, TimeDeltaSerializer()),
|
|
193
|
+
FieldMetadata("authorizationContext", "authorization_context", "_authorization_context", AuthorizationContext, None, KaggleObjectSerializer()),
|
|
194
|
+
FieldMetadata("authorizationScopes", "authorization_scopes", "_authorization_scopes", AuthorizationScope, [], ListSerializer(KaggleObjectSerializer())),
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
GenerateAccessTokenResponse._fields = [
|
|
198
|
+
FieldMetadata("token", "token", "_token", str, "", PredefinedSerializer()),
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
AuthorizationContext._fields = [
|
|
202
|
+
FieldMetadata("kernelSessionId", "kernel_session_id", "_kernel_session_id", int, None, PredefinedSerializer(), optional=True),
|
|
203
|
+
]
|
|
204
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|