openbayes-cli 0.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.
- bayes/__init__.py +0 -0
- bayes/client/__init__.py +0 -0
- bayes/client/base.py +20 -0
- bayes/client/dataset_version_client.py +91 -0
- bayes/client/gear_client.py +468 -0
- bayes/client/job_run_client.py +504 -0
- bayes/client/job_upload_client.py +114 -0
- bayes/client/org_client.py +67 -0
- bayes/client/resource_client.py +108 -0
- bayes/client/runtime_client.py +32 -0
- bayes/client/ssh_client.py +66 -0
- bayes/client/status_client.py +14 -0
- bayes/client/user_client.py +58 -0
- bayes/commands/__init__.py +0 -0
- bayes/commands/gear.py +691 -0
- bayes/commands/org.py +100 -0
- bayes/commands/ssh.py +70 -0
- bayes/error.py +9 -0
- bayes/model/__init__.py +0 -0
- bayes/model/dataset_version.py +14 -0
- bayes/model/file/__init__.py +0 -0
- bayes/model/file/data_bindings.py +42 -0
- bayes/model/file/openbayes_data.py +133 -0
- bayes/model/file/openbayes_gear.py +72 -0
- bayes/model/file/openbayes_ignore.py +75 -0
- bayes/model/file/openbayes_yaml.py +180 -0
- bayes/model/file/settings.py +157 -0
- bayes/model/party.py +35 -0
- bayes/model/resource.py +147 -0
- bayes/model/runtime.py +34 -0
- bayes/root.py +170 -0
- bayes/templates/openbayes_zh-Hans.yaml +134 -0
- bayes/templates/openbayesignore.yaml +3 -0
- bayes/usercases/__init__.py +0 -0
- bayes/usercases/archive_usecase.py +79 -0
- bayes/usercases/auth_usecase.py +35 -0
- bayes/usercases/dataset_version_usecase.py +61 -0
- bayes/usercases/disk_usecase.py +98 -0
- bayes/usercases/gear_download_usecese.py +113 -0
- bayes/usercases/gear_logs_usecase.py +44 -0
- bayes/usercases/gear_open_usecase.py +16 -0
- bayes/usercases/gear_run_usecase.py +123 -0
- bayes/usercases/gear_upload_usecase.py +248 -0
- bayes/usercases/gear_usecase.py +301 -0
- bayes/usercases/openbayes_data_usecase.py +73 -0
- bayes/usercases/org_usecase.py +85 -0
- bayes/usercases/resource_usecase.py +74 -0
- bayes/usercases/runtime_usecase.py +58 -0
- bayes/usercases/ssh_usecase.py +110 -0
- bayes/usercases/switch_usercase.py +19 -0
- bayes/utils.py +163 -0
- openbayes_cli-0.4.5.dist-info/METADATA +62 -0
- openbayes_cli-0.4.5.dist-info/RECORD +55 -0
- openbayes_cli-0.4.5.dist-info/WHEEL +4 -0
- openbayes_cli-0.4.5.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
import websocket
|
|
4
|
+
from websocket import WebSocketConnectionClosedException
|
|
5
|
+
|
|
6
|
+
from bayes.client import gear_client
|
|
7
|
+
from bayes.client.base import BayesGQLClient
|
|
8
|
+
from bayes.model.file.settings import BayesSettings
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_logs(id, party_name):
|
|
12
|
+
default_env = BayesSettings().default_env
|
|
13
|
+
gql_client = BayesGQLClient(default_env.graphQL, default_env.token)
|
|
14
|
+
logs = gear_client.get_logs(gql_client, id, party_name)
|
|
15
|
+
|
|
16
|
+
return logs
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_logs_follow(id, party_name):
|
|
20
|
+
default_env = BayesSettings().default_env
|
|
21
|
+
gql_client = BayesGQLClient(default_env.graphQL, default_env.token)
|
|
22
|
+
|
|
23
|
+
job = gear_client.get_job_by_id(gql_client, id, party_name)
|
|
24
|
+
if job:
|
|
25
|
+
ws_url = job.get_link_value("websocket")
|
|
26
|
+
if ws_url is None:
|
|
27
|
+
return None, "不存在"
|
|
28
|
+
# Establish WebSocket connection
|
|
29
|
+
ws = websocket.WebSocket()
|
|
30
|
+
ws.connect(ws_url)
|
|
31
|
+
return ws, None
|
|
32
|
+
else:
|
|
33
|
+
return None, "不存在"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def receive_logs(ws: websocket.WebSocket, job_id: str):
|
|
37
|
+
try:
|
|
38
|
+
data = ws.recv()
|
|
39
|
+
except (WebSocketConnectionClosedException, EOFError):
|
|
40
|
+
return None, f"容器 {job_id} 已关闭,没有更多日志"
|
|
41
|
+
except Exception as err:
|
|
42
|
+
return None, err
|
|
43
|
+
|
|
44
|
+
return data, None
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
import webbrowser
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def open_browser(url: str) -> bool:
|
|
6
|
+
try:
|
|
7
|
+
opened = webbrowser.open(url)
|
|
8
|
+
if opened:
|
|
9
|
+
typer.echo("已成功打开浏览器.")
|
|
10
|
+
return True
|
|
11
|
+
else:
|
|
12
|
+
typer.echo("Failed to open the browser.")
|
|
13
|
+
return False
|
|
14
|
+
except Exception as e:
|
|
15
|
+
typer.echo(f"An error occurred when open browser: {e}")
|
|
16
|
+
return False
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import List, Tuple, Dict, Any, Optional
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
|
|
6
|
+
from bayes.client import job_run_client, gear_client
|
|
7
|
+
from bayes.client.base import BayesGQLClient
|
|
8
|
+
from bayes.error import Error
|
|
9
|
+
from bayes.model.file.openbayes_yaml import OpenBayesYaml
|
|
10
|
+
from bayes.model.file.settings import BayesEnvConfig, BayesSettings, TypeHyperTuning, DefaultJobModeWorkSpace, \
|
|
11
|
+
DefaultBatchJobModeWorkSpace, DefaultJobModeTask, DefaultBatchJobModeTask
|
|
12
|
+
from bayes.model.party import ModeEnum
|
|
13
|
+
from bayes.usercases import gear_usecase
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def create(party_name, directory, project_id, mode, yaml: OpenBayesYaml, datasets: List[str], node_count: int, runtime,
|
|
17
|
+
resource, code_id, command, message) -> Tuple[str, str, Exception]:
|
|
18
|
+
if not project_id:
|
|
19
|
+
project_id, _, project_name, err = gear_usecase.read(directory)
|
|
20
|
+
if err:
|
|
21
|
+
logging.error("Error reading project ID: %s", err)
|
|
22
|
+
return "", "", err
|
|
23
|
+
|
|
24
|
+
if len(datasets) == 0 and yaml is not None:
|
|
25
|
+
datasets = yaml.get_dataset_bindings()
|
|
26
|
+
print(f"yaml.get_dataset_bindings(): {datasets}")
|
|
27
|
+
|
|
28
|
+
if runtime == "" and yaml is not None:
|
|
29
|
+
runtime = yaml.get_runtime()
|
|
30
|
+
|
|
31
|
+
if resource == "" and yaml is not None:
|
|
32
|
+
resource = yaml.resource
|
|
33
|
+
|
|
34
|
+
if command == "" and yaml is not None:
|
|
35
|
+
command = yaml.command
|
|
36
|
+
|
|
37
|
+
if node_count <= 0 and yaml is not None and yaml.node >= 1:
|
|
38
|
+
node_count = yaml.node
|
|
39
|
+
if node_count < 1:
|
|
40
|
+
node_count = 1
|
|
41
|
+
|
|
42
|
+
parameters: Dict[str, Any] = {}
|
|
43
|
+
if yaml is not None and yaml.parameters is not None:
|
|
44
|
+
parameters = yaml.parameters
|
|
45
|
+
|
|
46
|
+
default_env: Optional[BayesEnvConfig] = BayesSettings().default_env
|
|
47
|
+
gql_client = BayesGQLClient(default_env.graphQL, default_env.token)
|
|
48
|
+
|
|
49
|
+
frontend_value = ""
|
|
50
|
+
job_id = ""
|
|
51
|
+
# 如果是hypertuning
|
|
52
|
+
if mode == ModeEnum.hypertuning:
|
|
53
|
+
try:
|
|
54
|
+
hypertuning = job_run_client.create_hypertuning(party_name, gql_client, project_id, datasets, runtime,
|
|
55
|
+
resource,
|
|
56
|
+
code_id, command, yaml.hyper_tuning)
|
|
57
|
+
frontend_value = hypertuning.get_link_value("frontend")
|
|
58
|
+
job_id = hypertuning.id
|
|
59
|
+
except Exception as e:
|
|
60
|
+
return "", "", e
|
|
61
|
+
else:
|
|
62
|
+
try:
|
|
63
|
+
job = job_run_client.create(party_name, gql_client, mode, project_id, datasets, runtime, resource, code_id,
|
|
64
|
+
command, parameters, node_count)
|
|
65
|
+
|
|
66
|
+
frontend_value = job.get_link_value("frontend")
|
|
67
|
+
job_id = job.id
|
|
68
|
+
except Exception as e:
|
|
69
|
+
return "", "", e
|
|
70
|
+
|
|
71
|
+
if message != "":
|
|
72
|
+
err = job_run_client.update_job_description(gql_client, party_name, job_id, message)
|
|
73
|
+
if err is not None:
|
|
74
|
+
return frontend_value, job_id, err
|
|
75
|
+
|
|
76
|
+
return frontend_value, job_id, None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def restart(jid, party_name, data, runtime, resource, task_command, nodeCount, message):
|
|
80
|
+
default_env: Optional[BayesEnvConfig] = BayesSettings().default_env
|
|
81
|
+
gql_client = BayesGQLClient(default_env.graphQL, default_env.token)
|
|
82
|
+
|
|
83
|
+
job = gear_client.get_job_by_id(gql_client, jid, party_name)
|
|
84
|
+
if job is None:
|
|
85
|
+
return None, f"job {jid} not found"
|
|
86
|
+
|
|
87
|
+
mode = job.mode
|
|
88
|
+
|
|
89
|
+
if len(data) == 0:
|
|
90
|
+
data = job.get_job_dataBindings()
|
|
91
|
+
|
|
92
|
+
if runtime == "":
|
|
93
|
+
runtime = job.get_runtime()
|
|
94
|
+
if resource == "":
|
|
95
|
+
resource = job.resource.name
|
|
96
|
+
|
|
97
|
+
frontend_value = ""
|
|
98
|
+
job_id = ""
|
|
99
|
+
if mode == DefaultJobModeWorkSpace:
|
|
100
|
+
job = job_run_client.restart_workspace(gql_client, party_name, jid, runtime, resource, data, [])
|
|
101
|
+
frontend_value = job.get_link_value("frontend")
|
|
102
|
+
job_id = job.id
|
|
103
|
+
elif mode == DefaultBatchJobModeWorkSpace:
|
|
104
|
+
job = job_run_client.restart_batch_workspace(gql_client, party_name, jid, runtime, resource, data, [])
|
|
105
|
+
frontend_value = job.get_link_value("frontend")
|
|
106
|
+
job_id = job.id
|
|
107
|
+
# task 或者 batch task create
|
|
108
|
+
elif mode == DefaultJobModeTask or DefaultBatchJobModeTask:
|
|
109
|
+
if task_command == "" or task_command is None:
|
|
110
|
+
if job.command == "" or job.command is None:
|
|
111
|
+
print("task command 不能为空")
|
|
112
|
+
raise typer.Exit(code=1)
|
|
113
|
+
else:
|
|
114
|
+
task_command = job.command
|
|
115
|
+
|
|
116
|
+
if nodeCount == -1:
|
|
117
|
+
nodeCount = job.children_count()
|
|
118
|
+
|
|
119
|
+
frontend_value, job_id, _ = create(party_name, "", job.project.id, mode, None, data, nodeCount, runtime, resource, job.sourceCode.id, task_command, message)
|
|
120
|
+
|
|
121
|
+
return frontend_value, job_id
|
|
122
|
+
|
|
123
|
+
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import base64
|
|
4
|
+
import json
|
|
5
|
+
from typing import Optional, Tuple, Callable
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
from tusclient import client
|
|
9
|
+
from tusclient.storage import filestorage
|
|
10
|
+
from rich.progress import (
|
|
11
|
+
Progress,
|
|
12
|
+
TextColumn,
|
|
13
|
+
BarColumn,
|
|
14
|
+
TransferSpeedColumn,
|
|
15
|
+
TimeRemainingColumn,
|
|
16
|
+
)
|
|
17
|
+
from tusclient.exceptions import TusCommunicationError
|
|
18
|
+
|
|
19
|
+
from pydantic import BaseModel
|
|
20
|
+
|
|
21
|
+
from bayes.model.file.settings import BayesSettings
|
|
22
|
+
from bayes.model.file.openbayes_data import (
|
|
23
|
+
OpenBayesData,
|
|
24
|
+
OpenBayesDataSettings,
|
|
25
|
+
OpenBayesDataType,
|
|
26
|
+
DATA_FILE_NAME,
|
|
27
|
+
)
|
|
28
|
+
from bayes.model.file.openbayes_ignore import IGNORE_FILE_NAME, IGNORE_CLEANUPS
|
|
29
|
+
from bayes.usercases import openbayes_data_usecase, archive_usecase
|
|
30
|
+
from bayes.usercases.disk_usecase import IgnoreService, DiskService
|
|
31
|
+
from bayes.utils import Utils
|
|
32
|
+
|
|
33
|
+
UPLOAD_PART_SIZE = 268435456 # -1 or 0 means unlimited
|
|
34
|
+
UPLOAD_CODE_LIMIT = 500 # 500MB
|
|
35
|
+
TUS_STORAGE_FILE = ".tus_storage"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class RequestUploadUrl(BaseModel):
|
|
39
|
+
upload_url: str
|
|
40
|
+
token: str
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def upload_request() -> Tuple[Optional[RequestUploadUrl], Optional[Exception]]:
|
|
44
|
+
default_env = BayesSettings().default_env
|
|
45
|
+
url = f"{default_env.endpoint}/api/users/{default_env.username}/jobs/upload-request?protocol=tusd"
|
|
46
|
+
print(f"upload_request url:{url}")
|
|
47
|
+
auth_token = default_env.token
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
response = requests.post(url, headers={"Authorization": f"Bearer {auth_token}"})
|
|
51
|
+
except requests.RequestException as e:
|
|
52
|
+
return None, e
|
|
53
|
+
|
|
54
|
+
logging.info(response)
|
|
55
|
+
|
|
56
|
+
if response.status_code != 200:
|
|
57
|
+
err = Exception(f"Request failed with status code {response.status_code}")
|
|
58
|
+
return None, err
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
result = response.json()
|
|
62
|
+
upload_request = RequestUploadUrl(**result)
|
|
63
|
+
return upload_request, None
|
|
64
|
+
except ValueError as e:
|
|
65
|
+
return None, e
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _upload_file(
|
|
69
|
+
file_path: str, upload_url: str, token: str
|
|
70
|
+
) -> Tuple[bool, Optional[str], Optional[Exception]]:
|
|
71
|
+
try:
|
|
72
|
+
my_client = client.TusClient(
|
|
73
|
+
upload_url, headers={"Authorization": f"Bearer {token}"}
|
|
74
|
+
)
|
|
75
|
+
file_size = os.path.getsize(file_path)
|
|
76
|
+
|
|
77
|
+
storage = filestorage.FileStorage(
|
|
78
|
+
os.path.join(os.path.dirname(file_path), TUS_STORAGE_FILE)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
filename = os.path.basename(file_path)
|
|
82
|
+
metadata = {"filename": filename}
|
|
83
|
+
|
|
84
|
+
with Progress(
|
|
85
|
+
TextColumn("[progress.description]{task.description}"),
|
|
86
|
+
BarColumn(),
|
|
87
|
+
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
|
|
88
|
+
TransferSpeedColumn(),
|
|
89
|
+
TimeRemainingColumn(),
|
|
90
|
+
) as progress:
|
|
91
|
+
task = progress.add_task("Uploading", total=file_size)
|
|
92
|
+
|
|
93
|
+
uploader = my_client.uploader(
|
|
94
|
+
file_path,
|
|
95
|
+
chunk_size=2 * 1024 * 1024,
|
|
96
|
+
store_url=True,
|
|
97
|
+
url_storage=storage,
|
|
98
|
+
upload_checksum=False,
|
|
99
|
+
metadata=metadata,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
while uploader.offset < file_size:
|
|
103
|
+
uploader.upload_chunk()
|
|
104
|
+
progress.update(task, completed=uploader.offset)
|
|
105
|
+
|
|
106
|
+
print(f"File uploaded successfully: {file_path}")
|
|
107
|
+
|
|
108
|
+
storage_path = os.path.join(os.path.dirname(file_path), TUS_STORAGE_FILE)
|
|
109
|
+
if os.path.exists(storage_path):
|
|
110
|
+
os.remove(storage_path)
|
|
111
|
+
print(f"Removed filestorage: {storage_path}")
|
|
112
|
+
|
|
113
|
+
payload_part = token.split(".")[1]
|
|
114
|
+
padded_payload = payload_part + "=" * (4 - len(payload_part) % 4)
|
|
115
|
+
decoded_payload = base64.urlsafe_b64decode(padded_payload).decode("utf-8")
|
|
116
|
+
payload_data = json.loads(decoded_payload)
|
|
117
|
+
sub_payload = json.loads(payload_data["sub"])["payload"]
|
|
118
|
+
|
|
119
|
+
return True, sub_payload, None
|
|
120
|
+
|
|
121
|
+
except TusCommunicationError as e:
|
|
122
|
+
print(f"TUS Communication Error: {e}")
|
|
123
|
+
print(f"Response status: {e.status_code}")
|
|
124
|
+
print(f"Response body: {e.response_content}")
|
|
125
|
+
return False, None, e
|
|
126
|
+
except Exception as e:
|
|
127
|
+
print(f"Unexpected error: {e}")
|
|
128
|
+
return False, None, e
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def upload_file(
|
|
132
|
+
file_path: str, upload_url: str, token: str
|
|
133
|
+
) -> Tuple[bool, Optional[str], Optional[Exception]]:
|
|
134
|
+
return _upload_file(file_path, upload_url, token)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def remove_after_upload_success(zip_path, data_file_path, pid):
|
|
138
|
+
logging.debug("remove after upload success")
|
|
139
|
+
if os.path.exists(zip_path):
|
|
140
|
+
os.remove(zip_path)
|
|
141
|
+
openbayes_data_usecase.remove_by_cur_user(data_file_path, pid)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def has_last_upload(path: str, pid: str) -> Tuple[bool, Optional[OpenBayesData]]:
|
|
145
|
+
data_settings = OpenBayesDataSettings(path)
|
|
146
|
+
data, err = data_settings.read_by_cur_user(pid)
|
|
147
|
+
if data is None:
|
|
148
|
+
return False, None
|
|
149
|
+
|
|
150
|
+
print(f"has_last_upload data.has_last_upload():{data.has_last_upload()}")
|
|
151
|
+
|
|
152
|
+
if data.has_last_upload():
|
|
153
|
+
# Check if the zip file still exists
|
|
154
|
+
if os.path.exists(data.zip):
|
|
155
|
+
# Check if the upload URL is still valid
|
|
156
|
+
print(f"is_upload_url_valid(data.location, data.token):{is_upload_url_valid(data.location, data.token)}")
|
|
157
|
+
if is_upload_url_valid(data.location, data.token):
|
|
158
|
+
return True, data
|
|
159
|
+
|
|
160
|
+
return False, None
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def is_upload_url_valid(upload_url: str, token: str) -> bool:
|
|
164
|
+
try:
|
|
165
|
+
headers = {"Authorization": f"Bearer {token}"}
|
|
166
|
+
response = requests.head(upload_url, headers=headers)
|
|
167
|
+
print(f"is_upload_url_valid response.status_code:{response.status_code}")
|
|
168
|
+
if response.status_code == 401:
|
|
169
|
+
print("Token has expired")
|
|
170
|
+
return False
|
|
171
|
+
return True
|
|
172
|
+
except requests.RequestException as e:
|
|
173
|
+
print(f"is_upload_url_valid error: {e}")
|
|
174
|
+
return False
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
# Update the upload function to support resuming
|
|
178
|
+
def upload(data: OpenBayesData):
|
|
179
|
+
success, payload, err = _upload_file(data.zip, data.location, data.token)
|
|
180
|
+
if success:
|
|
181
|
+
remove_after_upload_success(data.zip, data.path, data.pid)
|
|
182
|
+
return data.length if success else 0, payload, err
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def clear_last_upload(data: OpenBayesData):
|
|
186
|
+
if data:
|
|
187
|
+
try:
|
|
188
|
+
os.remove(data.zip)
|
|
189
|
+
except FileNotFoundError:
|
|
190
|
+
print(f"zip_path:{data.zip} not found")
|
|
191
|
+
|
|
192
|
+
print(f"OpenBayesDataSettings(data.path):{OpenBayesDataSettings(data.path)}")
|
|
193
|
+
settings = OpenBayesDataSettings(data.path)
|
|
194
|
+
settings.remove_by_cur_user(data.pid or data.did)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def pre_upload(
|
|
198
|
+
path: str, pid: str, process: Callable
|
|
199
|
+
) -> Tuple[Optional[dict], Optional[Exception]]:
|
|
200
|
+
process("正在向服务器发送上传请求...")
|
|
201
|
+
|
|
202
|
+
req, err = upload_request()
|
|
203
|
+
if err is not None:
|
|
204
|
+
return None, err
|
|
205
|
+
|
|
206
|
+
process("服务器已响应")
|
|
207
|
+
process("正在读取文件列表,请稍候...")
|
|
208
|
+
|
|
209
|
+
ignore_service = IgnoreService(IGNORE_FILE_NAME, IGNORE_CLEANUPS)
|
|
210
|
+
disk_service = DiskService(ignore_service)
|
|
211
|
+
files, _, err = disk_service.directory_computing(path, UPLOAD_CODE_LIMIT)
|
|
212
|
+
if err is not None:
|
|
213
|
+
return None, err
|
|
214
|
+
|
|
215
|
+
process("剔除在 .openbayesignore 中忽略的文件及文件夹...")
|
|
216
|
+
process(f"共有文件 {files} 个")
|
|
217
|
+
|
|
218
|
+
data_file_path, err = openbayes_data_usecase.write_file(
|
|
219
|
+
path, OpenBayesDataType.CODE, pid
|
|
220
|
+
)
|
|
221
|
+
if err is not None:
|
|
222
|
+
return None, err
|
|
223
|
+
|
|
224
|
+
process("正在压缩代码...")
|
|
225
|
+
|
|
226
|
+
zip_path = Utils.generate_temp_zip_path()
|
|
227
|
+
err = archive_usecase.archive(path, zip_path)
|
|
228
|
+
if err is not None:
|
|
229
|
+
return None, err
|
|
230
|
+
|
|
231
|
+
process("压缩代码完成")
|
|
232
|
+
|
|
233
|
+
try:
|
|
234
|
+
stat = os.stat(zip_path)
|
|
235
|
+
except Exception as e:
|
|
236
|
+
return None, e
|
|
237
|
+
|
|
238
|
+
process("正在初始化上传中...")
|
|
239
|
+
process(f"正在上传压缩包。总共上传大小:{Utils.byte_size(stat.st_size, True)}")
|
|
240
|
+
|
|
241
|
+
data, err = openbayes_data_usecase.update_by_cur_user(
|
|
242
|
+
data_file_path, pid, req.upload_url, req.token, zip_path, stat.st_size
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
if err is not None:
|
|
246
|
+
return None, err
|
|
247
|
+
|
|
248
|
+
return data, None
|