kaggle 1.7.4.5__py3-none-any.whl → 1.8.0__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.
Files changed (110) hide show
  1. kaggle/__init__.py +10 -6
  2. kaggle/api/kaggle_api.py +574 -598
  3. kaggle/api/kaggle_api_extended.py +5251 -4769
  4. kaggle/cli.py +1335 -1585
  5. kaggle/models/api_blob_type.py +3 -3
  6. kaggle/models/dataset_column.py +165 -174
  7. kaggle/models/dataset_new_request.py +83 -41
  8. kaggle/models/dataset_new_version_request.py +32 -25
  9. kaggle/models/dataset_update_settings_request.py +35 -27
  10. kaggle/models/kaggle_models_extended.py +169 -172
  11. kaggle/models/kernel_push_request.py +66 -49
  12. kaggle/models/model_instance_new_version_request.py +10 -18
  13. kaggle/models/model_instance_update_request.py +103 -34
  14. kaggle/models/model_new_instance_request.py +138 -41
  15. kaggle/models/model_new_request.py +35 -27
  16. kaggle/models/model_update_request.py +32 -25
  17. kaggle/models/start_blob_upload_request.py +192 -195
  18. kaggle/models/start_blob_upload_response.py +98 -98
  19. kaggle/models/upload_file.py +114 -120
  20. kaggle/test/test_authenticate.py +23 -23
  21. {kaggle-1.7.4.5.dist-info → kaggle-1.8.0.dist-info}/METADATA +11 -15
  22. kaggle-1.8.0.dist-info/RECORD +148 -0
  23. kagglesdk/__init__.py +5 -1
  24. kagglesdk/benchmarks/services/__init__.py +0 -0
  25. kagglesdk/benchmarks/services/benchmarks_api_service.py +19 -0
  26. kagglesdk/benchmarks/types/__init__.py +0 -0
  27. kagglesdk/benchmarks/types/benchmark_types.py +307 -0
  28. kagglesdk/benchmarks/types/benchmarks_api_service.py +243 -0
  29. kagglesdk/blobs/services/blob_api_service.py +1 -1
  30. kagglesdk/blobs/types/blob_api_service.py +2 -2
  31. kagglesdk/common/services/__init__.py +0 -0
  32. kagglesdk/common/services/operations_service.py +46 -0
  33. kagglesdk/common/types/file_download.py +1 -1
  34. kagglesdk/common/types/http_redirect.py +1 -1
  35. kagglesdk/common/types/operations.py +194 -0
  36. kagglesdk/common/types/operations_service.py +48 -0
  37. kagglesdk/community/__init__.py +0 -0
  38. kagglesdk/community/types/__init__.py +0 -0
  39. kagglesdk/community/types/content_enums.py +44 -0
  40. kagglesdk/community/types/organization.py +410 -0
  41. kagglesdk/competitions/services/competition_api_service.py +49 -12
  42. kagglesdk/competitions/types/competition.py +14 -0
  43. kagglesdk/competitions/types/competition_api_service.py +1639 -1275
  44. kagglesdk/competitions/types/search_competitions.py +28 -0
  45. kagglesdk/datasets/databundles/__init__.py +0 -0
  46. kagglesdk/datasets/databundles/types/__init__.py +0 -0
  47. kagglesdk/datasets/databundles/types/databundle_api_types.py +540 -0
  48. kagglesdk/datasets/services/dataset_api_service.py +39 -14
  49. kagglesdk/datasets/types/dataset_api_service.py +554 -300
  50. kagglesdk/datasets/types/dataset_enums.py +21 -0
  51. kagglesdk/datasets/types/dataset_service.py +145 -0
  52. kagglesdk/datasets/types/dataset_types.py +74 -74
  53. kagglesdk/datasets/types/search_datasets.py +6 -0
  54. kagglesdk/discussions/__init__.py +0 -0
  55. kagglesdk/discussions/types/__init__.py +0 -0
  56. kagglesdk/discussions/types/search_discussions.py +43 -0
  57. kagglesdk/discussions/types/writeup_enums.py +11 -0
  58. kagglesdk/education/services/education_api_service.py +1 -1
  59. kagglesdk/education/types/education_api_service.py +1 -1
  60. kagglesdk/kaggle_client.py +46 -23
  61. kagglesdk/kaggle_creds.py +148 -0
  62. kagglesdk/kaggle_env.py +89 -25
  63. kagglesdk/kaggle_http_client.py +216 -306
  64. kagglesdk/kaggle_oauth.py +200 -0
  65. kagglesdk/kaggle_object.py +286 -293
  66. kagglesdk/kernels/services/kernels_api_service.py +46 -9
  67. kagglesdk/kernels/types/kernels_api_service.py +635 -159
  68. kagglesdk/kernels/types/kernels_enums.py +6 -0
  69. kagglesdk/kernels/types/search_kernels.py +6 -0
  70. kagglesdk/licenses/__init__.py +0 -0
  71. kagglesdk/licenses/types/__init__.py +0 -0
  72. kagglesdk/licenses/types/licenses_types.py +182 -0
  73. kagglesdk/models/services/model_api_service.py +41 -17
  74. kagglesdk/models/types/model_api_service.py +987 -637
  75. kagglesdk/models/types/model_enums.py +8 -0
  76. kagglesdk/models/types/model_service.py +71 -71
  77. kagglesdk/models/types/model_types.py +1057 -5
  78. kagglesdk/models/types/search_models.py +8 -0
  79. kagglesdk/search/__init__.py +0 -0
  80. kagglesdk/search/services/__init__.py +0 -0
  81. kagglesdk/search/services/search_api_service.py +19 -0
  82. kagglesdk/search/types/__init__.py +0 -0
  83. kagglesdk/search/types/search_api_service.py +2435 -0
  84. kagglesdk/search/types/search_content_shared.py +50 -0
  85. kagglesdk/search/types/search_enums.py +45 -0
  86. kagglesdk/search/types/search_service.py +303 -0
  87. kagglesdk/security/services/iam_service.py +31 -0
  88. kagglesdk/security/services/oauth_service.py +27 -1
  89. kagglesdk/security/types/authentication.py +63 -63
  90. kagglesdk/security/types/iam_service.py +496 -0
  91. kagglesdk/security/types/oauth_service.py +797 -10
  92. kagglesdk/security/types/roles.py +8 -0
  93. kagglesdk/security/types/security_types.py +159 -0
  94. kagglesdk/test/__init__.py +0 -0
  95. kagglesdk/test/test_client.py +20 -22
  96. kagglesdk/users/services/account_service.py +13 -1
  97. kagglesdk/users/services/group_api_service.py +31 -0
  98. kagglesdk/users/types/account_service.py +169 -28
  99. kagglesdk/users/types/group_api_service.py +315 -0
  100. kagglesdk/users/types/group_types.py +165 -0
  101. kagglesdk/users/types/groups_enum.py +8 -0
  102. kagglesdk/users/types/progression_service.py +9 -0
  103. kagglesdk/users/types/search_users.py +23 -0
  104. kagglesdk/users/types/user_avatar.py +226 -0
  105. kaggle/configuration.py +0 -206
  106. kaggle-1.7.4.5.dist-info/RECORD +0 -98
  107. {kaggle-1.7.4.5.dist-info → kaggle-1.8.0.dist-info}/WHEEL +0 -0
  108. {kaggle-1.7.4.5.dist-info → kaggle-1.8.0.dist-info}/entry_points.txt +0 -0
  109. {kaggle-1.7.4.5.dist-info → kaggle-1.8.0.dist-info}/licenses/LICENSE.txt +0 -0
  110. {kaggle/test → kagglesdk/benchmarks}/__init__.py +0 -0
@@ -0,0 +1,200 @@
1
+ import base64
2
+ import hashlib
3
+ import http.server
4
+ import logging
5
+ import os
6
+ import platform
7
+ import random
8
+ import secrets
9
+ import socketserver
10
+ import uuid
11
+ import urllib.parse
12
+ import webbrowser
13
+ from datetime import datetime, timedelta, timezone
14
+ from kagglesdk.kaggle_client import KaggleClient
15
+ from kagglesdk.kaggle_creds import KaggleCredentials
16
+ from kagglesdk.security.types.oauth_service import ExchangeOAuthTokenRequest
17
+
18
+
19
+ class KaggleOAuth:
20
+ OAUTH_CLIENT_ID = "kagglesdk"
21
+
22
+ def __init__(self, client: KaggleClient):
23
+ self._client = client
24
+ self._http_client = client.http_client()
25
+ self._server_running = False
26
+ self._creds = None
27
+ self._logger = logging.getLogger(__name__)
28
+
29
+ class OAuthState:
30
+ def __init__(self):
31
+ self.state = str(uuid.uuid4())
32
+ self.code_verifier = KaggleOAuth.OAuthState._generate_code_verifier()
33
+ self.code_challenge = KaggleOAuth.OAuthState._generate_code_challenge(self.code_verifier)
34
+
35
+ def _generate_state(length: int = 32):
36
+ return secrets.token_urlsafe(length)
37
+
38
+ def _generate_code_verifier(length: int = 64) -> str:
39
+ if not 42 <= length <= 128:
40
+ raise ValueError("Code verifier length must be between 42 and 128 characters.")
41
+ return secrets.token_urlsafe(length)
42
+
43
+ def _generate_code_challenge(code_verifier: str) -> str:
44
+ code_verifier_bytes = code_verifier.encode("utf-8")
45
+ code_challenge_bytes = hashlib.sha256(code_verifier_bytes).digest()
46
+ code_challenge_base64 = base64.urlsafe_b64encode(code_challenge_bytes).decode("utf-8")
47
+ return code_challenge_base64
48
+
49
+ class OAuthCallbackHandler(http.server.BaseHTTPRequestHandler):
50
+ def __init__(
51
+ self,
52
+ *args,
53
+ oauth: "KaggleOAuth" = None,
54
+ oauth_state: "KaggleOAuth.OAuthState" = None,
55
+ on_success=None,
56
+ logger=None,
57
+ **kwargs,
58
+ ):
59
+ self._oauth = oauth
60
+ self._oauth_state = oauth_state
61
+ self._on_success = on_success
62
+ self._logger = logger
63
+ super().__init__(*args, **kwargs)
64
+
65
+ def do_GET(self):
66
+ if self.path == "/favicon.ico":
67
+ return
68
+ try:
69
+ self._handle_oauth_callback()
70
+ finally:
71
+ self._stop_server()
72
+
73
+ def _handle_oauth_callback(self):
74
+ parsed_url = urllib.parse.urlparse(self.path)
75
+ query_params = urllib.parse.parse_qs(parsed_url.query)
76
+ if "code" in query_params and "state" in query_params:
77
+ code = query_params["code"][0]
78
+ state = query_params["state"][0]
79
+ self._logger.debug(f"\nReceived OAuth Callback:")
80
+ self._logger.debug(f" code : {code}")
81
+ self._logger.debug(f" state: {state}")
82
+ if state == self._oauth_state.state:
83
+ self.send_response(200)
84
+ self.send_header("Content-type", "text/html")
85
+ self.end_headers()
86
+ self.wfile.write(
87
+ b"<html><body><h1>Authentication Successful!</h1><p>You can close this window.</p></body></html>"
88
+ )
89
+ self._on_success(code)
90
+ else:
91
+ self._logger.error(f"Invalid state! Expected: {self._oauth_state.state}, Received: {state}")
92
+ self.send_response(400)
93
+ self.send_header("Content-type", "text/html")
94
+ self.end_headers()
95
+ self.wfile.write(b"<html><body><h1>Authentication Failed!</h1></body></html>")
96
+ else:
97
+ self._logger.debug(f"\nReceived Invalid OAuth Callback: {self.path}")
98
+ self.send_response(400)
99
+ self.send_header("Content-type", "text/html")
100
+ self.end_headers()
101
+ self.wfile.write(
102
+ b"<html><body><h1>Authentication Failed!</h1><p>Invalid callback parameters.</p></body></html>"
103
+ )
104
+
105
+ def _stop_server(self):
106
+ self._oauth.stop_server()
107
+
108
+ @staticmethod
109
+ def _can_open_browser():
110
+ if platform.system() in ["Windows", "Darwin"]:
111
+ return True # Assume GUI on Windows/Mac
112
+
113
+ if "DISPLAY" in os.environ and os.environ["DISPLAY"] != "":
114
+ return True # X11 display available
115
+
116
+ return False
117
+
118
+ def _exchange_oauth_token(self, code: str, scopes: list[str], oauth_state: "KaggleOAuth.OAuthState"):
119
+ request = ExchangeOAuthTokenRequest()
120
+ request.code = code
121
+ request.code_verifier = oauth_state.code_verifier
122
+ request.grant_type = "authorization_code"
123
+
124
+ response = self._client.security.oauth_client.exchange_oauth_token(request)
125
+ self._creds = KaggleCredentials(
126
+ client=self._client,
127
+ refresh_token=response.refreshToken,
128
+ access_token=response.accessToken,
129
+ access_token_expiration=datetime.now(timezone.utc) + timedelta(seconds=response.expires_in),
130
+ username=response.username,
131
+ scopes=scopes,
132
+ )
133
+
134
+ def _run_oauth_flow(self, scopes: list[str], no_launch_browser: bool) -> KaggleCredentials:
135
+ use_browser = not no_launch_browser and KaggleOAuth._can_open_browser()
136
+ redirect_uri = self._http_client.get_oauth_default_redirect_url()
137
+ if use_browser:
138
+ port = random.randint(8000, 9000)
139
+ redirect_uri = f"http://localhost:{port}"
140
+ self._logger.debug(f"Will listen for the callback at: {redirect_uri}")
141
+
142
+ oauth_state = KaggleOAuth.OAuthState()
143
+ oauth_start_url = self._http_client.build_start_oauth_url(
144
+ client_id=KaggleOAuth.OAUTH_CLIENT_ID,
145
+ redirect_uri=redirect_uri,
146
+ scope=scopes,
147
+ state=oauth_state.state,
148
+ code_challenge=oauth_state.code_challenge,
149
+ )
150
+
151
+ if use_browser:
152
+ webbrowser.open(oauth_start_url)
153
+ print("Your browser has been opened to visit:")
154
+ print(f" {oauth_start_url}\n\n")
155
+
156
+ def exchange_oauth_token(code: str):
157
+ self._exchange_oauth_token(code, scopes, oauth_state)
158
+
159
+ def handler_factory(*args, **kwargs):
160
+ return KaggleOAuth.OAuthCallbackHandler(
161
+ *args,
162
+ oauth=self,
163
+ oauth_state=oauth_state,
164
+ on_success=exchange_oauth_token,
165
+ logger=self._logger,
166
+ **kwargs,
167
+ )
168
+
169
+ self._server_running = True
170
+ with socketserver.TCPServer(("127.0.0.1", port), handler_factory) as httpd:
171
+ self._logger.debug(f"Listening for callback on port {port}...")
172
+ while self._server_running:
173
+ httpd.handle_request()
174
+ self._logger.debug("OAuth flow completed (or server stopped).")
175
+ else:
176
+ print("\nGo to the following link in your browser, and complete the sign-in prompts at Kaggle:\n")
177
+ print(f" {oauth_start_url}")
178
+ print(
179
+ "\nOnce finished, enter the verification code provided in your browser: ",
180
+ end="",
181
+ )
182
+ code = input()
183
+ self._exchange_oauth_token(code, scopes, oauth_state)
184
+
185
+ return self._creds
186
+
187
+ def stop_server(self):
188
+ self._server_running = False
189
+
190
+ def _ensure_creds_valid(self, creds: KaggleCredentials):
191
+ if not creds:
192
+ raise Exception("Authentication failed.")
193
+ return creds.introspect()
194
+
195
+ def authenticate(self, scopes: list[str], no_launch_browser: bool = False) -> KaggleCredentials:
196
+ creds = self._run_oauth_flow(scopes, no_launch_browser)
197
+ username = self._ensure_creds_valid(creds)
198
+ creds.save()
199
+ print(f"\nYou are now logged in as [{username}]\n")
200
+ return creds