gsnet-sdk 0.1.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.
- gsnet/__init__.py +32 -0
- gsnet/_dataclass.py +404 -0
- gsnet/_exceptions.py +273 -0
- gsnet/_file.py +300 -0
- gsnet/_login.py +183 -0
- gsnet/_session.py +319 -0
- gsnet/_tqdm.py +141 -0
- gsnet/adaptor/__init__.py +0 -0
- gsnet/adaptor/om_hub/__init__.py +3 -0
- gsnet/adaptor/om_hub/download.py +155 -0
- gsnet/adaptor/om_hub/file_manager.py +382 -0
- gsnet/adaptor/om_hub/upload.py +137 -0
- gsnet/adaptor/om_hub/utils.py +50 -0
- gsnet/api.py +820 -0
- gsnet/commands/__init__.py +13 -0
- gsnet/commands/dataset.py +222 -0
- gsnet/commands/dataset_deprecated.py +203 -0
- gsnet/commands/gsnet_cli.py +47 -0
- gsnet/commands/model.py +220 -0
- gsnet/commands/model_deprecated.py +235 -0
- gsnet/commands/user.py +121 -0
- gsnet/constants.py +59 -0
- gsnet/downloader.py +361 -0
- gsnet/log.py +72 -0
- gsnet/refactor/__init__.py +2 -0
- gsnet/refactor/api.py +0 -0
- gsnet/refactor/constants.py +105 -0
- gsnet/refactor/controlled/__init__.py +51 -0
- gsnet/refactor/controlled/crypto.py +145 -0
- gsnet/refactor/controlled/exceptions.py +41 -0
- gsnet/refactor/controlled/header.py +29 -0
- gsnet/refactor/controlled/kms_client.py +183 -0
- gsnet/refactor/controlled/models.py +145 -0
- gsnet/refactor/core/__init__.py +1 -0
- gsnet/refactor/core/auth.py +58 -0
- gsnet/refactor/core/dataclass.py +70 -0
- gsnet/refactor/core/router.py +324 -0
- gsnet/refactor/core/session.py +156 -0
- gsnet/refactor/plugins/__init__.py +0 -0
- gsnet/refactor/plugins/errors.py +211 -0
- gsnet/refactor/plugins/log.py +47 -0
- gsnet/refactor/plugins/progress.py +585 -0
- gsnet/refactor/sdk.py +126 -0
- gsnet/refactor/service/__init__.py +0 -0
- gsnet/refactor/service/downloader.py +809 -0
- gsnet/refactor/service/file_manager.py +522 -0
- gsnet/refactor/service/notification.py +81 -0
- gsnet/refactor/service/uploader.py +820 -0
- gsnet/refactor/service/validators.py +47 -0
- gsnet/refactor/utils/__init__.py +0 -0
- gsnet/refactor/utils/deprecate.py +18 -0
- gsnet/refactor/utils/utils.py +13 -0
- gsnet/uploader.py +340 -0
- gsnet/utils.py +129 -0
- gsnet_sdk-0.1.0.dist-info/METADATA +120 -0
- gsnet_sdk-0.1.0.dist-info/RECORD +59 -0
- gsnet_sdk-0.1.0.dist-info/WHEEL +5 -0
- gsnet_sdk-0.1.0.dist-info/entry_points.txt +2 -0
- gsnet_sdk-0.1.0.dist-info/top_level.txt +1 -0
gsnet/__init__.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
from gsnet._login import login, logout, whoami
|
|
6
|
+
from gsnet.refactor.constants import BOLD, DIM, RESET
|
|
7
|
+
from gsnet.refactor.core import GSnetRouter
|
|
8
|
+
from gsnet.refactor.plugins.log import setup_logging
|
|
9
|
+
from gsnet.refactor.sdk import notice, gsnet_download_file, gsnet_upload_file
|
|
10
|
+
|
|
11
|
+
from .downloader import download_file, download_model, download_model_file
|
|
12
|
+
from .uploader import upload_file, upload_model, upload_model_file
|
|
13
|
+
|
|
14
|
+
setup_logging()
|
|
15
|
+
|
|
16
|
+
# if windows machine, do not set uvloop
|
|
17
|
+
if os.name == "nt":
|
|
18
|
+
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
|
19
|
+
else:
|
|
20
|
+
try:
|
|
21
|
+
import uvloop
|
|
22
|
+
except ImportError:
|
|
23
|
+
import subprocess
|
|
24
|
+
|
|
25
|
+
print(f"{DIM}Module {BOLD}`uvloop`{RESET} {DIM}undetected, installing...{RESET}")
|
|
26
|
+
subprocess.check_call(
|
|
27
|
+
[sys.executable, "-m", "pip", "install", "-qq", "uvloop"],
|
|
28
|
+
stdout=subprocess.DEVNULL,
|
|
29
|
+
stderr=subprocess.DEVNULL,
|
|
30
|
+
)
|
|
31
|
+
import uvloop
|
|
32
|
+
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
gsnet/_dataclass.py
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import asdict, dataclass, field
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
from .utils import parse_time
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class UserInfo:
|
|
12
|
+
"""
|
|
13
|
+
User Info Dataclass
|
|
14
|
+
|
|
15
|
+
Attributes:
|
|
16
|
+
username (str):
|
|
17
|
+
username for GSnet links and repo_id
|
|
18
|
+
id (int):
|
|
19
|
+
unique number id of user
|
|
20
|
+
login (str):
|
|
21
|
+
username used for login purpose
|
|
22
|
+
subject_name (str):
|
|
23
|
+
self-defined name for display
|
|
24
|
+
email (str):
|
|
25
|
+
registered email address
|
|
26
|
+
avatar_url (str):
|
|
27
|
+
user avatar url
|
|
28
|
+
language (str):
|
|
29
|
+
user default language
|
|
30
|
+
is_admin (bool):
|
|
31
|
+
whether the user is admin or not
|
|
32
|
+
is_active (bool):
|
|
33
|
+
whether the user is active or not
|
|
34
|
+
last_login (str):
|
|
35
|
+
last login time
|
|
36
|
+
created (str):
|
|
37
|
+
created time
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
username: str
|
|
41
|
+
id: Optional[int]
|
|
42
|
+
login: Optional[str]
|
|
43
|
+
subject_name: Optional[str]
|
|
44
|
+
email: Optional[str]
|
|
45
|
+
avatar_url: Optional[str]
|
|
46
|
+
language: Optional[str]
|
|
47
|
+
is_admin: Optional[bool]
|
|
48
|
+
is_active: Optional[bool]
|
|
49
|
+
last_login: Optional[str]
|
|
50
|
+
created: Optional[str]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class RepoPermission:
|
|
55
|
+
"""
|
|
56
|
+
Permission Info Dataclass
|
|
57
|
+
|
|
58
|
+
Attributes:
|
|
59
|
+
admin (bool):
|
|
60
|
+
whether the user is admin or not
|
|
61
|
+
push (bool):
|
|
62
|
+
whether the user can push to the repository or not
|
|
63
|
+
pull (bool):
|
|
64
|
+
whether the user can pull from the repository or not
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
admin: bool
|
|
68
|
+
push: bool
|
|
69
|
+
pull: bool
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass
|
|
73
|
+
class RepoInfo:
|
|
74
|
+
"""
|
|
75
|
+
Repo Info Dataclass
|
|
76
|
+
|
|
77
|
+
Attributes:
|
|
78
|
+
id (int):
|
|
79
|
+
repo id
|
|
80
|
+
owner (UserInfo):
|
|
81
|
+
owner info
|
|
82
|
+
name (str):
|
|
83
|
+
repo name
|
|
84
|
+
repo_id (str):
|
|
85
|
+
repo id in `Username/Reponame` format
|
|
86
|
+
size (int):
|
|
87
|
+
repo size
|
|
88
|
+
html_url (str):
|
|
89
|
+
repo url
|
|
90
|
+
permissions (RepoPermission):
|
|
91
|
+
repo permissions
|
|
92
|
+
created_at (str):
|
|
93
|
+
created time
|
|
94
|
+
updated_at (str):
|
|
95
|
+
updated time
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
id: int
|
|
99
|
+
owner: UserInfo
|
|
100
|
+
name: str
|
|
101
|
+
repo_id: str
|
|
102
|
+
size: Optional[int]
|
|
103
|
+
html_url: Optional[str]
|
|
104
|
+
permissions: Optional[RepoPermission]
|
|
105
|
+
created_at: Optional[datetime]
|
|
106
|
+
updated_at: Optional[datetime]
|
|
107
|
+
|
|
108
|
+
def __init__(self, **kwargs):
|
|
109
|
+
self.id = kwargs.pop("id")
|
|
110
|
+
self.owner = UserInfo(**kwargs.pop("owner"))
|
|
111
|
+
self.name = kwargs.pop("name")
|
|
112
|
+
self.repo_id = kwargs.pop("subject_name")
|
|
113
|
+
|
|
114
|
+
self.size = kwargs.pop("size", None)
|
|
115
|
+
self.html_url = kwargs.pop("html_url", None)
|
|
116
|
+
permissions = kwargs.pop("permissions", None)
|
|
117
|
+
self.permissions = RepoPermission(**permissions) if permissions else None
|
|
118
|
+
|
|
119
|
+
created_at = kwargs.pop("created_at", None)
|
|
120
|
+
self.created_at = parse_time(created_at) if created_at else None
|
|
121
|
+
updated_at = kwargs.pop("updated_at", None)
|
|
122
|
+
self.updated_at = parse_time(updated_at) if updated_at else None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass
|
|
126
|
+
class DatasetFile:
|
|
127
|
+
"""TODO"""
|
|
128
|
+
|
|
129
|
+
uuid: str
|
|
130
|
+
name: str
|
|
131
|
+
size: int
|
|
132
|
+
type: int
|
|
133
|
+
id: int
|
|
134
|
+
datasetId: int
|
|
135
|
+
repo_id: str
|
|
136
|
+
uploaderId: Optional[int]
|
|
137
|
+
isPrivate: Optional[bool]
|
|
138
|
+
decompressState: Optional[int]
|
|
139
|
+
|
|
140
|
+
def __init__(self, **kwargs):
|
|
141
|
+
self.uuid = kwargs.pop("uuid")
|
|
142
|
+
self.name = kwargs.pop("name")
|
|
143
|
+
self.size = kwargs.pop("size")
|
|
144
|
+
self.type = kwargs.pop("type")
|
|
145
|
+
self.id = kwargs.pop("id")
|
|
146
|
+
self.datasetId = kwargs.pop("datasetId")
|
|
147
|
+
self.repo_id = kwargs.pop("repo_id")
|
|
148
|
+
|
|
149
|
+
self.uploaderId = kwargs.pop("uploaderId", None)
|
|
150
|
+
self.isPrivate = kwargs.pop("isPrivate", None)
|
|
151
|
+
self.decompressState = kwargs.pop("decompressState", None)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@dataclass
|
|
155
|
+
class DatasetInfo:
|
|
156
|
+
"""TODO"""
|
|
157
|
+
|
|
158
|
+
id: str
|
|
159
|
+
userId: int
|
|
160
|
+
repoId: int
|
|
161
|
+
title: str
|
|
162
|
+
repo_id: str
|
|
163
|
+
attachments: Optional[List[DatasetFile]]
|
|
164
|
+
status: Optional[int]
|
|
165
|
+
|
|
166
|
+
def __init__(self, **kwargs):
|
|
167
|
+
self.id = kwargs.pop("id")
|
|
168
|
+
self.userId = kwargs.pop("userId")
|
|
169
|
+
self.repoId = kwargs.pop("repoId")
|
|
170
|
+
self.title = kwargs.pop("title")
|
|
171
|
+
self.repo_id = kwargs.pop("repo_id")
|
|
172
|
+
|
|
173
|
+
attachments = kwargs.pop("attachments", [])
|
|
174
|
+
if attachments:
|
|
175
|
+
for data in attachments:
|
|
176
|
+
data.update({"repo_id": self.repo_id})
|
|
177
|
+
self.attachments = [DatasetFile(**data) for data in attachments]
|
|
178
|
+
else:
|
|
179
|
+
self.attachments = None
|
|
180
|
+
|
|
181
|
+
self.status = kwargs.pop("status", None)
|
|
182
|
+
self.recommend = kwargs.pop("recommend", None)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@dataclass
|
|
186
|
+
class FileChunkInfo:
|
|
187
|
+
"""
|
|
188
|
+
File Chunk Info Dataclass
|
|
189
|
+
|
|
190
|
+
API Response (dict):
|
|
191
|
+
- dataset "/attachments/get_chunks"
|
|
192
|
+
"uuid": fileChunk.UUID,
|
|
193
|
+
"uploaded": strconv.Itoa(fileChunk.IsUploaded),
|
|
194
|
+
"uploadID": fileChunk.UploadID,
|
|
195
|
+
"chunks": string(chunks),
|
|
196
|
+
"attachID": "0",
|
|
197
|
+
"datasetID": "0",
|
|
198
|
+
"fileName": "",
|
|
199
|
+
"datasetName": "",
|
|
200
|
+
|
|
201
|
+
- model "/attachments/model/get_chunks"
|
|
202
|
+
"uuid": fileChunk.UUID,
|
|
203
|
+
"uploaded": strconv.Itoa(fileChunk.IsUploaded),
|
|
204
|
+
"uploadID": fileChunk.UploadID,
|
|
205
|
+
"chunks": string(chunks),
|
|
206
|
+
"attachID": "0",
|
|
207
|
+
"modeluuid": modeluuid,
|
|
208
|
+
"datasetID": "0",
|
|
209
|
+
"fileName": "",
|
|
210
|
+
"modelName": "",
|
|
211
|
+
|
|
212
|
+
- error response
|
|
213
|
+
"result_code": "-1",
|
|
214
|
+
"msg": errStr,
|
|
215
|
+
|
|
216
|
+
Attributes:
|
|
217
|
+
result_code (int):
|
|
218
|
+
return 0 when success, otherwise return -1 with error message
|
|
219
|
+
msg (str):
|
|
220
|
+
return plain string error message, return "success" when None
|
|
221
|
+
uploaded (Optional[bool]):
|
|
222
|
+
whether the file is uploaded or not
|
|
223
|
+
attachID (Optional[int]):
|
|
224
|
+
attachment id
|
|
225
|
+
uploaded_chunks (Optional[list]):
|
|
226
|
+
list of uploaded chunks
|
|
227
|
+
uploadID (Optional[str]):
|
|
228
|
+
upload id
|
|
229
|
+
uuid (Optional[str]):
|
|
230
|
+
file uuid
|
|
231
|
+
repo_id (Optional[str]):
|
|
232
|
+
repo id in `Username/Reponame` format
|
|
233
|
+
dataset_or_model_name (Optional[str]):
|
|
234
|
+
dataset or model name
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
result_code: int
|
|
238
|
+
msg: str
|
|
239
|
+
uploaded: Optional[bool]
|
|
240
|
+
md5: Optional[str]
|
|
241
|
+
fileName: Optional[str]
|
|
242
|
+
attachID: Optional[int]
|
|
243
|
+
uploaded_chunks: Optional[list]
|
|
244
|
+
uploadID: Optional[str]
|
|
245
|
+
uuid: Optional[str]
|
|
246
|
+
repo_id: Optional[str]
|
|
247
|
+
dataset_or_model_name: Optional[str]
|
|
248
|
+
realName: Optional[str]
|
|
249
|
+
datasetID: Optional[str]
|
|
250
|
+
upload_mode: Optional[str]
|
|
251
|
+
|
|
252
|
+
def __init__(self, **kwargs):
|
|
253
|
+
result_code = kwargs.pop("result_code", 0)
|
|
254
|
+
self.result_code = int(result_code)
|
|
255
|
+
self.msg = kwargs.pop("msg", "success")
|
|
256
|
+
|
|
257
|
+
uploaded = kwargs.pop("uploaded", "")
|
|
258
|
+
self.uploaded = True if uploaded == "1" else False
|
|
259
|
+
self.attachID = kwargs.pop("attachID", None)
|
|
260
|
+
|
|
261
|
+
raw_chunks = kwargs.pop("chunks", "")
|
|
262
|
+
uploaded_chunks = [i for i in raw_chunks.split(",") if i != ""]
|
|
263
|
+
self.uploaded_chunks = uploaded_chunks
|
|
264
|
+
|
|
265
|
+
uploadID = kwargs.pop("uploadID", "")
|
|
266
|
+
self.uploadID = uploadID if uploadID != "" else None
|
|
267
|
+
uuid = kwargs.pop("uuid", "")
|
|
268
|
+
self.uuid = uuid if uuid != "" else None
|
|
269
|
+
|
|
270
|
+
repo = kwargs.pop("repoName", None)
|
|
271
|
+
owner = kwargs.pop("repoOwner", None)
|
|
272
|
+
self.repo_id = owner + "/" + repo if owner and repo else None
|
|
273
|
+
|
|
274
|
+
if kwargs.pop("upload_mode") == "dataset":
|
|
275
|
+
self.dataset_or_model_name = kwargs.pop("datasetName", "")
|
|
276
|
+
else:
|
|
277
|
+
self.dataset_or_model_name = kwargs.pop("modelName", "")
|
|
278
|
+
|
|
279
|
+
self.fileName = kwargs.pop("fileName", "")
|
|
280
|
+
self.realName = self.fileName
|
|
281
|
+
self.datasetID = kwargs.pop("datasetID", "")
|
|
282
|
+
self.md5 = kwargs.pop("md5", None)
|
|
283
|
+
self.upload_mode = kwargs.pop("upload_mode", None)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
@dataclass
|
|
287
|
+
class NewMultipart:
|
|
288
|
+
"""TODO"""
|
|
289
|
+
|
|
290
|
+
result_code: int
|
|
291
|
+
msg: str
|
|
292
|
+
uuid: Optional[str]
|
|
293
|
+
uploadID: Optional[str]
|
|
294
|
+
|
|
295
|
+
def __init__(self, **kwargs):
|
|
296
|
+
result_code = kwargs.pop("result_code", 0)
|
|
297
|
+
self.result_code = int(result_code)
|
|
298
|
+
self.msg = kwargs.pop("msg", "success")
|
|
299
|
+
self.uuid = kwargs.pop("uuid", None)
|
|
300
|
+
self.uploadID = kwargs.pop("uploadID", None)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
@dataclass
|
|
304
|
+
class MultipartUrl:
|
|
305
|
+
"""TODO"""
|
|
306
|
+
|
|
307
|
+
url: Optional[str] = None
|
|
308
|
+
msg: Optional[str] = None
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
@dataclass
|
|
312
|
+
class ModelFile:
|
|
313
|
+
FileName: Optional[str]
|
|
314
|
+
ModTime: Optional[str]
|
|
315
|
+
IsDir: Optional[bool]
|
|
316
|
+
Size: Optional[int]
|
|
317
|
+
ParenDir: Optional[str]
|
|
318
|
+
UUID: Optional[str]
|
|
319
|
+
RelativePath: Optional[str]
|
|
320
|
+
repo_id: Optional[str]
|
|
321
|
+
model_id: Optional[str]
|
|
322
|
+
IsSupportPreview: Optional[str] = ""
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
@dataclass
|
|
326
|
+
class ModelInfo:
|
|
327
|
+
id: Optional[str]
|
|
328
|
+
name: Optional[str]
|
|
329
|
+
size: Optional[int]
|
|
330
|
+
path: Optional[str]
|
|
331
|
+
repo_id: Optional[str]
|
|
332
|
+
repoId: Optional[int]
|
|
333
|
+
userId: Optional[int]
|
|
334
|
+
userName: Optional[str]
|
|
335
|
+
isCanOper: Optional[bool]
|
|
336
|
+
isCanDelete: Optional[bool]
|
|
337
|
+
isCanDownload: Optional[bool]
|
|
338
|
+
repoName: Optional[str]
|
|
339
|
+
repoOwnerName: Optional[str]
|
|
340
|
+
modelFileList: Optional[List[ModelFile]]
|
|
341
|
+
modelType: Optional[int]
|
|
342
|
+
|
|
343
|
+
def __init__(self, **kwargs):
|
|
344
|
+
self.id = kwargs.pop("id", None)
|
|
345
|
+
self.name = kwargs.pop("name", None)
|
|
346
|
+
self.size = kwargs.pop("size", None)
|
|
347
|
+
self.path = kwargs.pop("path", None)
|
|
348
|
+
self.repo_id = kwargs.pop("repo_id", None)
|
|
349
|
+
self.repoId = kwargs.pop("repoId", None)
|
|
350
|
+
self.userId = kwargs.pop("userId", None)
|
|
351
|
+
self.userName = kwargs.pop("userName", None)
|
|
352
|
+
self.isCanOper = kwargs.pop("isCanOper", None)
|
|
353
|
+
self.isCanDelete = kwargs.pop("isCanDelete", None)
|
|
354
|
+
self.isCanDownload = kwargs.pop("isCanDownload", None)
|
|
355
|
+
self.repoName = kwargs.pop("repoName", None)
|
|
356
|
+
self.repoOwnerName = kwargs.pop("repoOwnerName", None)
|
|
357
|
+
|
|
358
|
+
modelFileList = kwargs.pop("modelFileList", [])
|
|
359
|
+
if modelFileList:
|
|
360
|
+
for data in modelFileList:
|
|
361
|
+
data.update({"repo_id": self.repo_id, "model_id": self.id})
|
|
362
|
+
self.modelFileList = [ModelFile(**data) for data in modelFileList]
|
|
363
|
+
else:
|
|
364
|
+
self.modelFileList = None
|
|
365
|
+
|
|
366
|
+
self.modelType = kwargs.pop("modelType", None)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
@dataclass
|
|
370
|
+
class ModelCreate:
|
|
371
|
+
code: str
|
|
372
|
+
msg: Optional[str] = None
|
|
373
|
+
id: Optional[int] = None
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
@dataclass
|
|
377
|
+
class BasicResp:
|
|
378
|
+
code: int
|
|
379
|
+
msg: str
|
|
380
|
+
data: any
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
@dataclass
|
|
384
|
+
class CreateRepoOption:
|
|
385
|
+
name: str
|
|
386
|
+
alias: Optional[str] = None
|
|
387
|
+
description: Optional[str] = None
|
|
388
|
+
private: bool = False
|
|
389
|
+
issue_labels: Optional[str] = None
|
|
390
|
+
auto_init: bool = False
|
|
391
|
+
gitignores: Optional[str] = None
|
|
392
|
+
license: Optional[str] = None
|
|
393
|
+
readme: Optional[str] = None
|
|
394
|
+
default_branch: Optional[str] = None
|
|
395
|
+
|
|
396
|
+
def __post_init__(self):
|
|
397
|
+
if len(self.name) > 100:
|
|
398
|
+
raise ValueError("Name must be at most 100 characters long")
|
|
399
|
+
if self.alias and len(self.alias) > 100:
|
|
400
|
+
raise ValueError("Alias must be at most 100 characters long")
|
|
401
|
+
if self.description and len(self.description) > 255:
|
|
402
|
+
raise ValueError("Description must be at most 255 characters long")
|
|
403
|
+
if self.default_branch and len(self.default_branch) > 100:
|
|
404
|
+
raise ValueError("Default branch must be at most 100 characters long")
|
gsnet/_exceptions.py
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import re
|
|
3
|
+
from functools import wraps
|
|
4
|
+
from inspect import signature
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Callable, Type, TypeVar
|
|
7
|
+
|
|
8
|
+
from gsnet.refactor.constants import REPO_ID_REGEX
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TokenNotFoundWarn(Warning):
|
|
14
|
+
def __init__(self):
|
|
15
|
+
self.message = (
|
|
16
|
+
"未找到本地 token;若遇到提示 PageNotFound 或 UnauthorizedError,"
|
|
17
|
+
"则需要使用 `login` 保存GSnet账户 token 到本地以获取授权。"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def __str__(self):
|
|
21
|
+
return repr(self.message)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class GSnetError(BaseException):
|
|
25
|
+
def __init__(self, msg):
|
|
26
|
+
self.msg = msg
|
|
27
|
+
|
|
28
|
+
def __str__(self):
|
|
29
|
+
return "❌ " + self.msg
|
|
30
|
+
|
|
31
|
+
def __repr__(self):
|
|
32
|
+
return "❌ " + self.msg
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ServerError(GSnetError):
|
|
36
|
+
def __init__(self, status_code: int):
|
|
37
|
+
self.msg = f"{status_code} GSnet服务器暂时不可用,请联系社区管理员或稍后再试"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class HttpProxyError(GSnetError):
|
|
41
|
+
def __init__(self):
|
|
42
|
+
self.msg = "无法发送请求,请检查网络代理"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class HttpConnectionError(GSnetError):
|
|
46
|
+
def __init__(self):
|
|
47
|
+
self.msg = "无法连接网络,请检查网络设置"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class InvalidTokenError(GSnetError):
|
|
51
|
+
def __init__(self):
|
|
52
|
+
self.msg = f"Invalid or broken GSnet token."
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class TokenNotFoundError(GSnetError):
|
|
56
|
+
def __init__(self):
|
|
57
|
+
token_help_doc_url = "https://gsnet.pcl.ac.cn/docs/index.html#/api/token"
|
|
58
|
+
self.msg = f"未找到本地 token;请先使用 `gsnet login` 保存GSnet账户 token 到本地以获取授权。具体使用方法请参考: {token_help_doc_url}"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class UnauthorizedError(GSnetError):
|
|
62
|
+
def __init__(self, status_code: int = 401):
|
|
63
|
+
self.msg = f"{status_code} 您无权建立此连接。请确保您拥有对应的权限。"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class PageNotFound(GSnetError):
|
|
67
|
+
def __init__(self):
|
|
68
|
+
self.msg = "无效请求,请确保仓库路径填写正确并且您拥有对应的权限"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class ParamsTypeError(GSnetError):
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
arg_name: str,
|
|
75
|
+
arg_value: any,
|
|
76
|
+
accepted_type: Type[any],
|
|
77
|
+
):
|
|
78
|
+
self.msg = f"`{arg_name}` 参数类型错误 {type(arg_value)}: `{arg_value}`. " f"正确的参数类型为 {accepted_type}"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class RepoIdError(GSnetError):
|
|
82
|
+
def __init__(self, repo_id):
|
|
83
|
+
self.msg = f"`{repo_id}` 参数格式错误. 正确的 `repo_id` 参数格式应为: `用户名/仓库名`"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class RepoNotFoundError(GSnetError):
|
|
87
|
+
def __init__(self, repo_id):
|
|
88
|
+
self.msg = f"仓库不存在: `{repo_id}`"
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class RepoExistsError(GSnetError):
|
|
92
|
+
def __init__(self, repo_id):
|
|
93
|
+
self.msg = f"仓库已存在: `{repo_id}`,请勿重复创建"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class KeyboardInterruptError(GSnetError):
|
|
97
|
+
def __init__(self, msg):
|
|
98
|
+
self.msg = f"用户中断操作; {msg}"
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class DatasetNotFound(GSnetError):
|
|
102
|
+
def __init__(self, repo_id, dataset_url):
|
|
103
|
+
self.msg = f"`{repo_id}` 仓库尚未创建数据集: {dataset_url}"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class EmptyDataset(GSnetError):
|
|
107
|
+
def __init__(self, repo_id, dataset_url):
|
|
108
|
+
self.msg = f"`{repo_id}` 仓库数据集内未找到任何文件: {dataset_url}"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class ModelCreateError(GSnetError):
|
|
112
|
+
def __init__(self, model_name, msg):
|
|
113
|
+
self.msg = f" `{model_name}` 模型创建失败: {msg}"
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class ModelNotFoundError(GSnetError):
|
|
117
|
+
def __init__(self, model_name, model_list_url):
|
|
118
|
+
self.msg = f"模型不存在 `{model_name}`; 请在网页端查看正确模型名称: {model_list_url}"
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class ServerFileExistsError(GSnetError):
|
|
122
|
+
def __init__(
|
|
123
|
+
self,
|
|
124
|
+
filename: str,
|
|
125
|
+
existing_filename: str,
|
|
126
|
+
existing_repo_id: str = None,
|
|
127
|
+
):
|
|
128
|
+
if existing_repo_id:
|
|
129
|
+
self.msg = (
|
|
130
|
+
f"`{filename}` 该文件已被上传为 {existing_repo_id} 仓库中的 `{existing_filename}` 文件, 无法重复上传"
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
self.msg = f"`{filename}` 文件已上传, 无法重复上传"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class ServerFileNotFoundError(GSnetError):
|
|
137
|
+
def __init__(self, msg):
|
|
138
|
+
self.msg = msg
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class EmptyFolderError(GSnetError):
|
|
142
|
+
def __init__(self, local_dir: Path):
|
|
143
|
+
self.msg = f"空目录,未能找到任何本地文件: {local_dir.absolute()}"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class LocalPathNotFound(GSnetError):
|
|
147
|
+
def __init__(self, filepath: Path):
|
|
148
|
+
self.msg = f"本地文件或目录不存在: {filepath.absolute()}"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class LocalDirNotFound(GSnetError):
|
|
152
|
+
def __init__(self, local_dir: Path):
|
|
153
|
+
self.msg = f"本地目录不存在: {local_dir.absolute()}"
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class FileTypeError(GSnetError):
|
|
157
|
+
def __init__(self, filepath: Path):
|
|
158
|
+
self.msg = f"非压缩文件(`.zip` 或 `.tar.gz`): {filepath.absolute()}"
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class FileSizeError(GSnetError):
|
|
162
|
+
def __init__(self, msg):
|
|
163
|
+
self.msg = msg
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class PutUploadError(GSnetError):
|
|
167
|
+
def __init__(self, msg):
|
|
168
|
+
self.msg = msg
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class UploadError(GSnetError):
|
|
172
|
+
def __init__(self, msg):
|
|
173
|
+
self.msg = msg
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
CallableT = TypeVar("CallableT", bound=Callable)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def validate_gsnet_args(fn: CallableT) -> CallableT:
|
|
180
|
+
"""Decorator that retrieves and prints all input arguments of a function.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
fn: The function to be decorated.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
A wrapper function that prints arguments and calls the original function.
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
@wraps(fn)
|
|
190
|
+
def _inner_fn(*args, **kwargs):
|
|
191
|
+
params = signature(fn).parameters
|
|
192
|
+
arg_names = [param.name for param in params.values()]
|
|
193
|
+
|
|
194
|
+
_kwargs = dict()
|
|
195
|
+
|
|
196
|
+
for i, arg_name in enumerate(arg_names):
|
|
197
|
+
if i < len(args):
|
|
198
|
+
value = args[i]
|
|
199
|
+
else:
|
|
200
|
+
value = kwargs.get(arg_name, None)
|
|
201
|
+
_kwargs.update({arg_name: value})
|
|
202
|
+
|
|
203
|
+
repo_id = _kwargs.get("repo_id", None)
|
|
204
|
+
if not repo_id or not isinstance(repo_id, str):
|
|
205
|
+
raise ParamsTypeError(
|
|
206
|
+
arg_name="repo_id",
|
|
207
|
+
arg_value=repo_id,
|
|
208
|
+
accepted_type=str,
|
|
209
|
+
)
|
|
210
|
+
if not re.match(REPO_ID_REGEX, repo_id):
|
|
211
|
+
raise RepoIdError(
|
|
212
|
+
repo_id=repo_id,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
filename = _kwargs.get("file", None)
|
|
216
|
+
if filename and not isinstance(filename, (Path, str)):
|
|
217
|
+
raise ParamsTypeError(
|
|
218
|
+
arg_name="file",
|
|
219
|
+
arg_value=filename,
|
|
220
|
+
accepted_type="either a pathlib.Path() object or str",
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
cluster = _kwargs.get("cluster", None)
|
|
224
|
+
if cluster and (not isinstance(cluster, str) or cluster.lower() not in ["gpu", "npu"]):
|
|
225
|
+
raise ParamsTypeError(
|
|
226
|
+
arg_name="cluster",
|
|
227
|
+
arg_value=cluster,
|
|
228
|
+
accepted_type="['gpu', 'npu'] case insensitive",
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
save_path = _kwargs.get("save_path", None)
|
|
232
|
+
if save_path and not isinstance(save_path, (Path, str)):
|
|
233
|
+
raise ParamsTypeError(
|
|
234
|
+
arg_name="save_path",
|
|
235
|
+
arg_value=save_path,
|
|
236
|
+
accepted_type="either a pathlib.Path() object or str",
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
force = _kwargs.get("force", None)
|
|
240
|
+
if force and not isinstance(force, bool):
|
|
241
|
+
raise ParamsTypeError(
|
|
242
|
+
arg_name="force",
|
|
243
|
+
arg_value=force,
|
|
244
|
+
accepted_type=bool,
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
model_name = _kwargs.get("model_name", None)
|
|
248
|
+
if model_name and not isinstance(model_name, str):
|
|
249
|
+
raise ParamsTypeError(
|
|
250
|
+
arg_name="model_name",
|
|
251
|
+
arg_value=model_name,
|
|
252
|
+
accepted_type=str,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
upload_name = _kwargs.get("upload_name", None)
|
|
256
|
+
if upload_name and not isinstance(upload_name, str):
|
|
257
|
+
raise ParamsTypeError(
|
|
258
|
+
arg_name="upload_name",
|
|
259
|
+
arg_value=upload_name,
|
|
260
|
+
accepted_type=str,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
folder = _kwargs.get("folder", None)
|
|
264
|
+
if folder and not isinstance(folder, (Path, str)):
|
|
265
|
+
raise ParamsTypeError(
|
|
266
|
+
arg_name="folder",
|
|
267
|
+
arg_value=folder,
|
|
268
|
+
accepted_type=str,
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
return fn(*args, **kwargs)
|
|
272
|
+
|
|
273
|
+
return _inner_fn
|