kaggle 1.7.4.2__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.
- kaggle/__init__.py +10 -6
- kaggle/api/kaggle_api.py +574 -585
- kaggle/api/kaggle_api_extended.py +5251 -4738
- kaggle/cli.py +1335 -1585
- kaggle/models/api_blob_type.py +3 -3
- kaggle/models/dataset_column.py +129 -129
- kaggle/models/dataset_new_request.py +130 -72
- kaggle/models/dataset_new_version_request.py +88 -56
- kaggle/models/dataset_update_settings_request.py +93 -59
- kaggle/models/kaggle_models_extended.py +169 -172
- kaggle/models/kernel_push_request.py +152 -100
- kaggle/models/model_instance_new_version_request.py +30 -30
- kaggle/models/model_instance_update_request.py +171 -71
- kaggle/models/model_new_instance_request.py +223 -88
- kaggle/models/model_new_request.py +61 -46
- kaggle/models/model_update_request.py +66 -48
- kaggle/models/start_blob_upload_request.py +146 -138
- kaggle/models/start_blob_upload_response.py +83 -78
- kaggle/models/upload_file.py +92 -96
- kaggle/test/test_authenticate.py +23 -23
- {kaggle-1.7.4.2.dist-info → kaggle-1.8.0.dist-info}/METADATA +11 -15
- kaggle-1.8.0.dist-info/RECORD +148 -0
- kagglesdk/__init__.py +5 -1
- kagglesdk/benchmarks/services/__init__.py +0 -0
- kagglesdk/benchmarks/services/benchmarks_api_service.py +19 -0
- kagglesdk/benchmarks/types/__init__.py +0 -0
- kagglesdk/benchmarks/types/benchmark_types.py +307 -0
- kagglesdk/benchmarks/types/benchmarks_api_service.py +243 -0
- kagglesdk/blobs/services/blob_api_service.py +1 -1
- kagglesdk/blobs/types/blob_api_service.py +2 -2
- kagglesdk/common/services/__init__.py +0 -0
- kagglesdk/common/services/operations_service.py +46 -0
- kagglesdk/common/types/file_download.py +1 -1
- kagglesdk/common/types/http_redirect.py +1 -1
- kagglesdk/common/types/operations.py +194 -0
- kagglesdk/common/types/operations_service.py +48 -0
- kagglesdk/community/__init__.py +0 -0
- kagglesdk/community/types/__init__.py +0 -0
- kagglesdk/community/types/content_enums.py +44 -0
- kagglesdk/community/types/organization.py +410 -0
- kagglesdk/competitions/services/competition_api_service.py +49 -12
- kagglesdk/competitions/types/competition.py +14 -0
- kagglesdk/competitions/types/competition_api_service.py +1639 -1275
- kagglesdk/competitions/types/search_competitions.py +28 -0
- kagglesdk/datasets/databundles/__init__.py +0 -0
- kagglesdk/datasets/databundles/types/__init__.py +0 -0
- kagglesdk/datasets/databundles/types/databundle_api_types.py +540 -0
- kagglesdk/datasets/services/dataset_api_service.py +39 -14
- kagglesdk/datasets/types/dataset_api_service.py +567 -297
- kagglesdk/datasets/types/dataset_enums.py +21 -0
- kagglesdk/datasets/types/dataset_service.py +145 -0
- kagglesdk/datasets/types/dataset_types.py +74 -74
- kagglesdk/datasets/types/search_datasets.py +6 -0
- kagglesdk/discussions/__init__.py +0 -0
- kagglesdk/discussions/types/__init__.py +0 -0
- kagglesdk/discussions/types/search_discussions.py +43 -0
- kagglesdk/discussions/types/writeup_enums.py +11 -0
- kagglesdk/education/services/education_api_service.py +1 -1
- kagglesdk/education/types/education_api_service.py +1 -1
- kagglesdk/kaggle_client.py +55 -20
- kagglesdk/kaggle_creds.py +148 -0
- kagglesdk/kaggle_env.py +89 -27
- kagglesdk/kaggle_http_client.py +235 -290
- kagglesdk/kaggle_oauth.py +200 -0
- kagglesdk/kaggle_object.py +298 -250
- kagglesdk/kernels/services/kernels_api_service.py +46 -9
- kagglesdk/kernels/types/kernels_api_service.py +658 -158
- kagglesdk/kernels/types/kernels_enums.py +6 -0
- kagglesdk/kernels/types/search_kernels.py +6 -0
- kagglesdk/licenses/__init__.py +0 -0
- kagglesdk/licenses/types/__init__.py +0 -0
- kagglesdk/licenses/types/licenses_types.py +182 -0
- kagglesdk/models/services/model_api_service.py +46 -21
- kagglesdk/models/types/model_api_service.py +1018 -652
- kagglesdk/models/types/model_enums.py +8 -0
- kagglesdk/models/types/model_service.py +71 -71
- kagglesdk/models/types/model_types.py +1057 -5
- kagglesdk/models/types/search_models.py +8 -0
- kagglesdk/search/__init__.py +0 -0
- kagglesdk/search/services/__init__.py +0 -0
- kagglesdk/search/services/search_api_service.py +19 -0
- kagglesdk/search/types/__init__.py +0 -0
- kagglesdk/search/types/search_api_service.py +2435 -0
- kagglesdk/search/types/search_content_shared.py +50 -0
- kagglesdk/search/types/search_enums.py +45 -0
- kagglesdk/search/types/search_service.py +303 -0
- kagglesdk/security/__init__.py +0 -0
- kagglesdk/security/services/__init__.py +0 -0
- kagglesdk/security/services/iam_service.py +31 -0
- kagglesdk/security/services/oauth_service.py +58 -0
- kagglesdk/security/types/__init__.py +0 -0
- kagglesdk/security/types/authentication.py +171 -0
- kagglesdk/security/types/iam_service.py +496 -0
- kagglesdk/security/types/oauth_service.py +1181 -0
- kagglesdk/security/types/roles.py +8 -0
- kagglesdk/security/types/security_types.py +159 -0
- kagglesdk/test/__init__.py +0 -0
- kagglesdk/test/test_client.py +20 -24
- kagglesdk/users/services/__init__.py +0 -0
- kagglesdk/users/services/account_service.py +31 -0
- kagglesdk/users/services/group_api_service.py +31 -0
- kagglesdk/users/types/account_service.py +345 -0
- kagglesdk/users/types/group_api_service.py +315 -0
- kagglesdk/users/types/group_types.py +165 -0
- kagglesdk/users/types/groups_enum.py +8 -0
- kagglesdk/users/types/progression_service.py +9 -0
- kagglesdk/users/types/search_users.py +23 -0
- kagglesdk/users/types/user_avatar.py +226 -0
- kaggle/configuration.py +0 -206
- kaggle-1.7.4.2.dist-info/RECORD +0 -89
- {kaggle-1.7.4.2.dist-info → kaggle-1.8.0.dist-info}/WHEEL +0 -0
- {kaggle-1.7.4.2.dist-info → kaggle-1.8.0.dist-info}/entry_points.txt +0 -0
- {kaggle-1.7.4.2.dist-info → kaggle-1.8.0.dist-info}/licenses/LICENSE.txt +0 -0
- {kaggle/test → kagglesdk/benchmarks}/__init__.py +0 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from datetime import datetime, timedelta, timezone
|
|
4
|
+
from kagglesdk.kaggle_client import KaggleClient
|
|
5
|
+
from kagglesdk.security.types.oauth_service import IntrospectTokenRequest
|
|
6
|
+
from kagglesdk.users.types.account_service import (
|
|
7
|
+
ApiVersion,
|
|
8
|
+
GenerateAccessTokenRequest,
|
|
9
|
+
GenerateAccessTokenResponse,
|
|
10
|
+
ExpireApiTokenRequest,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class KaggleCredentials:
|
|
15
|
+
DEFAULT_CREDENTIALS_FILE = "~/.kaggle/credentials.json"
|
|
16
|
+
DEFAULT_ACCESS_TOKEN_EXPIRATION = timedelta(hours=12)
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
client: KaggleClient,
|
|
21
|
+
refresh_token: str = None,
|
|
22
|
+
access_token: str = None,
|
|
23
|
+
access_token_expiration: datetime = None,
|
|
24
|
+
username: str = None,
|
|
25
|
+
scopes: list[str] = None,
|
|
26
|
+
):
|
|
27
|
+
self._client = client
|
|
28
|
+
self._refresh_token = refresh_token
|
|
29
|
+
self._access_token = access_token
|
|
30
|
+
self._access_token_expiration = access_token_expiration
|
|
31
|
+
self._username = username
|
|
32
|
+
self._scopes = scopes if scopes is not None else []
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def load(cls, client: KaggleClient, file_path: str = None) -> "KaggleCredentials":
|
|
36
|
+
file_path = os.path.expanduser(file_path or KaggleCredentials.DEFAULT_CREDENTIALS_FILE)
|
|
37
|
+
if not os.path.exists(file_path):
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
with open(file_path, "r") as f:
|
|
42
|
+
data = json.load(f)
|
|
43
|
+
except (json.JSONDecodeError, KeyError):
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
refresh_token = data.get("refresh_token")
|
|
47
|
+
if not refresh_token:
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
access_token_expiration = data.get("access_token_expiration")
|
|
51
|
+
if access_token_expiration:
|
|
52
|
+
access_token_expiration = datetime.fromisoformat(access_token_expiration)
|
|
53
|
+
else:
|
|
54
|
+
access_token_expiration = None
|
|
55
|
+
|
|
56
|
+
return cls(
|
|
57
|
+
client=client,
|
|
58
|
+
refresh_token=refresh_token,
|
|
59
|
+
access_token=data.get("access_token"),
|
|
60
|
+
access_token_expiration=access_token_expiration,
|
|
61
|
+
username=data.get("username"),
|
|
62
|
+
scopes=data.get("scopes"),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def delete(self, file_path=DEFAULT_CREDENTIALS_FILE) -> None:
|
|
66
|
+
file_path = os.path.expanduser(file_path)
|
|
67
|
+
if os.path.exists(file_path):
|
|
68
|
+
os.remove(file_path)
|
|
69
|
+
|
|
70
|
+
def save(self, file_path=DEFAULT_CREDENTIALS_FILE) -> None:
|
|
71
|
+
if not self._refresh_token:
|
|
72
|
+
raise Exception("Missing refresh token")
|
|
73
|
+
|
|
74
|
+
file_path = os.path.expanduser(file_path)
|
|
75
|
+
dir_name = os.path.dirname(file_path)
|
|
76
|
+
if not os.path.exists(dir_name):
|
|
77
|
+
os.makedirs(dir_name)
|
|
78
|
+
|
|
79
|
+
data = {
|
|
80
|
+
"refresh_token": self._refresh_token,
|
|
81
|
+
"access_token": self._access_token or "",
|
|
82
|
+
"access_token_expiration": (
|
|
83
|
+
self._access_token_expiration.isoformat() if self._access_token_expiration else ""
|
|
84
|
+
),
|
|
85
|
+
"username": self._username or "",
|
|
86
|
+
"scopes": self._scopes or [],
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
with open(file_path, "w") as f:
|
|
90
|
+
json.dump(data, f, indent=2)
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
os.chmod(file_path, 0o600)
|
|
94
|
+
except OSError:
|
|
95
|
+
pass # Ignore errors, especially on Windows
|
|
96
|
+
|
|
97
|
+
def introspect(self) -> str:
|
|
98
|
+
request = IntrospectTokenRequest()
|
|
99
|
+
request.token = self._access_token
|
|
100
|
+
response = self._client.security.oauth_client.introspect_token(request)
|
|
101
|
+
|
|
102
|
+
if not response.active or not response.username:
|
|
103
|
+
raise Exception("Authentication failed.")
|
|
104
|
+
|
|
105
|
+
self._username = response.username
|
|
106
|
+
return response.username
|
|
107
|
+
|
|
108
|
+
def refresh_access_token(self) -> None:
|
|
109
|
+
if not self._refresh_token:
|
|
110
|
+
raise Exception("Missing refresh token")
|
|
111
|
+
|
|
112
|
+
response = self.generate_access_token()
|
|
113
|
+
self._access_token_expiration = datetime.now(timezone.utc) + timedelta(seconds=response.expires_in)
|
|
114
|
+
self._access_token = response.token
|
|
115
|
+
self.save()
|
|
116
|
+
|
|
117
|
+
def access_token_has_expired(self) -> bool:
|
|
118
|
+
return not self._access_token_expiration or self._access_token_expiration < datetime.now(
|
|
119
|
+
timezone.utc
|
|
120
|
+
) - timedelta(minutes=30)
|
|
121
|
+
|
|
122
|
+
def get_access_token(self) -> str:
|
|
123
|
+
if not self._access_token or self.access_token_has_expired():
|
|
124
|
+
if not self._refresh_token:
|
|
125
|
+
return None
|
|
126
|
+
self.refresh_access_token()
|
|
127
|
+
return self._access_token
|
|
128
|
+
|
|
129
|
+
def generate_access_token(self, expiration_duration: timedelta = None) -> GenerateAccessTokenResponse:
|
|
130
|
+
if not self._refresh_token:
|
|
131
|
+
return None
|
|
132
|
+
request = GenerateAccessTokenRequest()
|
|
133
|
+
request.refresh_token = self._refresh_token
|
|
134
|
+
request.api_version = ApiVersion.API_VERSION_V1
|
|
135
|
+
request.expiration_duration = expiration_duration or KaggleCredentials.DEFAULT_ACCESS_TOKEN_EXPIRATION
|
|
136
|
+
return self._client.users.account_client.generate_access_token(request)
|
|
137
|
+
|
|
138
|
+
def revoke_token(self, reason: str) -> None:
|
|
139
|
+
if not self._refresh_token:
|
|
140
|
+
return
|
|
141
|
+
request = ExpireApiTokenRequest()
|
|
142
|
+
request.token = self._refresh_token
|
|
143
|
+
request.reason = reason
|
|
144
|
+
self._client.users.account_client.expire_api_token(request)
|
|
145
|
+
self.delete()
|
|
146
|
+
|
|
147
|
+
def get_username(self) -> str:
|
|
148
|
+
return self._username
|
kagglesdk/kaggle_env.py
CHANGED
|
@@ -1,42 +1,104 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
import os
|
|
2
3
|
from enum import Enum
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
KAGGLE_NOTEBOOK_ENV_VAR_NAME = "KAGGLE_KERNEL_RUN_TYPE"
|
|
7
|
+
KAGGLE_DATA_PROXY_URL_ENV_VAR_NAME = "KAGGLE_DATA_PROXY_URL"
|
|
8
|
+
KAGGLE_API_V1_TOKEN_PATH = "KAGGLE_API_V1_TOKEN"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_logger():
|
|
12
|
+
return logging.getLogger(__name__)
|
|
3
13
|
|
|
4
14
|
|
|
5
15
|
class KaggleEnv(Enum):
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
#
|
|
11
|
-
PROD = 4 # www.kaggle.com
|
|
16
|
+
LOCAL = 0 # localhost
|
|
17
|
+
STAGING = 1 # staging.kaggle.com
|
|
18
|
+
ADMIN = 2 # admin.kaggle.com
|
|
19
|
+
QA = 3 # qa.kaggle.com
|
|
20
|
+
PROD = 4 # api.kaggle.com
|
|
12
21
|
|
|
13
22
|
|
|
14
23
|
_env_to_endpoint = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
KaggleEnv.PROD: "https://www.kaggle.com",
|
|
24
|
+
KaggleEnv.LOCAL: "http://localhost",
|
|
25
|
+
KaggleEnv.STAGING: "https://staging.kaggle.com",
|
|
26
|
+
KaggleEnv.ADMIN: "https://admin.kaggle.com",
|
|
27
|
+
KaggleEnv.QA: "https://qa.kaggle.com",
|
|
28
|
+
KaggleEnv.PROD: "https://api.kaggle.com",
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
|
|
24
32
|
def get_endpoint(env: KaggleEnv):
|
|
25
|
-
|
|
33
|
+
return _env_to_endpoint[env]
|
|
26
34
|
|
|
27
35
|
|
|
28
36
|
def get_env():
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
env = os.getenv("KAGGLE_API_ENVIRONMENT")
|
|
38
|
+
if env is None or env == "PROD":
|
|
39
|
+
return KaggleEnv.PROD
|
|
40
|
+
if env == "LOCALHOST":
|
|
41
|
+
return KaggleEnv.LOCAL
|
|
42
|
+
if env == "ADMIN":
|
|
43
|
+
return KaggleEnv.ADMIN
|
|
44
|
+
if env == "STAGING":
|
|
45
|
+
return KaggleEnv.STAGING
|
|
46
|
+
if env == "QA":
|
|
47
|
+
return KaggleEnv.QA
|
|
48
|
+
raise Exception(f'Unrecognized value in KAGGLE_API_ENVIRONMENT: "{env}"')
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def is_in_kaggle_notebook() -> bool:
|
|
52
|
+
if os.getenv(KAGGLE_NOTEBOOK_ENV_VAR_NAME) is not None:
|
|
53
|
+
if os.getenv(KAGGLE_DATA_PROXY_URL_ENV_VAR_NAME) is None:
|
|
54
|
+
# Missing endpoint for the Jwt client
|
|
55
|
+
get_logger().warning(
|
|
56
|
+
"Can't use the Kaggle Cache. "
|
|
57
|
+
f"The '{KAGGLE_DATA_PROXY_URL_ENV_VAR_NAME}' environment variable is not set."
|
|
58
|
+
)
|
|
59
|
+
return False
|
|
60
|
+
return True
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _get_access_token_from_file(path):
|
|
65
|
+
if not path:
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
token_path = Path(path)
|
|
69
|
+
if not token_path.exists():
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
token_value = token_path.read_text().strip()
|
|
73
|
+
if not token_value:
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
get_logger().debug(f'Using access token from file: "{path}"')
|
|
77
|
+
return token_value
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_access_token_from_env():
|
|
81
|
+
if is_in_kaggle_notebook():
|
|
82
|
+
token = _get_access_token_from_file(os.environ.get(KAGGLE_API_V1_TOKEN_PATH))
|
|
83
|
+
if token:
|
|
84
|
+
return (token, KAGGLE_API_V1_TOKEN_PATH)
|
|
85
|
+
|
|
86
|
+
access_token = os.environ.get("KAGGLE_API_TOKEN")
|
|
87
|
+
if access_token:
|
|
88
|
+
if Path(access_token).exists():
|
|
89
|
+
return (_get_access_token_from_file(access_token), "KAGGLE_API_TOKEN")
|
|
90
|
+
get_logger().debug(
|
|
91
|
+
"Using access token from KAGGLE_API_TOKEN environment variable"
|
|
92
|
+
)
|
|
93
|
+
return (access_token, "KAGGLE_API_TOKEN")
|
|
94
|
+
|
|
95
|
+
access_token = _get_access_token_from_file(os.path.expanduser("~/.kaggle/access_token"))
|
|
96
|
+
if access_token:
|
|
97
|
+
return (access_token, "access_token")
|
|
98
|
+
|
|
99
|
+
# Check ".txt" as well in case Windows users create the file with this extension.
|
|
100
|
+
access_token = _get_access_token_from_file(os.path.expanduser("~/.kaggle/access_token.txt"))
|
|
101
|
+
if access_token:
|
|
102
|
+
return (access_token, "access_token")
|
|
103
|
+
|
|
104
|
+
return (None, None)
|