openbayes-cli 0.26.0__tar.gz → 0.26.1__tar.gz

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 (71) hide show
  1. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/PKG-INFO +1 -1
  2. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/gear_client.py +5 -0
  3. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/commands/gear.py +16 -7
  4. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/commands/hpc.py +14 -7
  5. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/gear_usecase.py +49 -1
  6. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/pyproject.toml +1 -1
  7. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/README.md +0 -0
  8. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/__init__.py +0 -0
  9. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/__init__.py +0 -0
  10. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/base.py +0 -0
  11. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/dataset_client.py +0 -0
  12. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/dataset_list_client.py +0 -0
  13. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/dataset_upload_client.py +0 -0
  14. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/dataset_version_client.py +0 -0
  15. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/job_run_client.py +0 -0
  16. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/minio_storage_client.py +0 -0
  17. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/org_client.py +0 -0
  18. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/resource_client.py +0 -0
  19. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/runtime_client.py +0 -0
  20. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/ssh_client.py +0 -0
  21. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/status_client.py +0 -0
  22. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/client/user_client.py +0 -0
  23. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/commands/__init__.py +0 -0
  24. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/commands/data.py +0 -0
  25. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/commands/org.py +0 -0
  26. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/commands/ssh.py +0 -0
  27. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/error.py +0 -0
  28. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/__init__.py +0 -0
  29. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/dataset.py +0 -0
  30. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/dataset_version.py +0 -0
  31. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/file/__init__.py +0 -0
  32. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/file/bayes_file.py +0 -0
  33. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/file/data_bindings.py +0 -0
  34. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/file/openbayes_gear.py +0 -0
  35. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/file/openbayes_ignore.py +0 -0
  36. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/file/openbayes_yaml.py +0 -0
  37. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/file/settings.py +0 -0
  38. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/party.py +0 -0
  39. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/resource.py +0 -0
  40. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/model/runtime.py +0 -0
  41. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/root.py +0 -0
  42. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/templates/__init__.py +0 -0
  43. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/templates/openbayes_zh-Hans.yaml +0 -0
  44. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/templates/openbayesignore.yaml +0 -0
  45. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/__init__.py +0 -0
  46. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/archive_usecase.py +0 -0
  47. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/auth_usecase.py +0 -0
  48. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/dataset_list_usecase.py +0 -0
  49. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/dataset_usecase.py +0 -0
  50. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/dataset_version_usecase.py +0 -0
  51. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/disk_usecase.py +0 -0
  52. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/gear_download_usecese.py +0 -0
  53. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/gear_logs_usecase.py +0 -0
  54. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/gear_run_usecase.py +0 -0
  55. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/minio_storage_usecase.py +0 -0
  56. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/open_usecase.py +0 -0
  57. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/org_usecase.py +0 -0
  58. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/resource_usecase.py +0 -0
  59. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/runtime_usecase.py +0 -0
  60. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/ssh_usecase.py +0 -0
  61. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/switch_usercase.py +0 -0
  62. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/usercases/upload_state_manager.py +0 -0
  63. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/utils/__init__.py +0 -0
  64. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/utils/add_global_param.py +0 -0
  65. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/bayes/utils.py +0 -0
  66. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/openbayestool/__init__.py +0 -0
  67. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/openbayestool/config.py +0 -0
  68. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/openbayestool/http_client.py +0 -0
  69. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/openbayestool/jwt_client.py +0 -0
  70. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/openbayestool/tracker.py +0 -0
  71. {openbayes_cli-0.26.0 → openbayes_cli-0.26.1}/openbayestool/updater.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openbayes-cli
3
- Version: 0.26.0
3
+ Version: 0.26.1
4
4
  Summary: A Python CLI for OpenBayes
5
5
  License: OpenBayes Public Source License
6
6
  Keywords: openbayes,cli,machine learning
@@ -106,6 +106,11 @@ class Job(BaseModel):
106
106
  def is_finished(self) -> bool:
107
107
  return self.status in {"SUCCEEDED", "CANCELLED", "FAILED"}
108
108
 
109
+ def is_workspace(self) -> bool:
110
+ # API 返回的 mode 形如 "WORKSPACE" / "BATCH_WORKSPACE" / "TASK" / "BATCH_TASK"。
111
+ # workspace 进入 RUNNING 后会持续保持运行,是 follow 的合理终点;其它模式会跑完后进入 finished。
112
+ return bool(self.mode) and "WORKSPACE" in self.mode.upper()
113
+
109
114
  def get_job_dataBindings(self) -> List[str]:
110
115
  datasets = []
111
116
  for binding in self.dataBindings or []:
@@ -124,7 +124,7 @@ def run(
124
124
  data: List[str] = typer.Option([], "-d", "--data", help="绑定数据"),
125
125
  env: str = typer.Option("", "-e", "--env", help="选择镜像"),
126
126
  resource: str = typer.Option("", "-r", "--resource", help="选择算力"),
127
- follow: bool = typer.Option(False, "-f", "--follow", help="运行容器的状态跟踪"),
127
+ follow: bool = typer.Option(False, "-f", "--follow", help="跟踪容器运行;task 模式会自动打印实时日志直到任务结束,workspace 进入运行后退出"),
128
128
  message: str = typer.Option("", "-m", "--message", help="执行描述"),
129
129
  open_browser: bool = typer.Option(False, "-o", "--open", help="成功创建容器后,在浏览器打开"),
130
130
  node: int = typer.Option(-1, "-n", "--node", help="指定运行节点数量"),
@@ -142,7 +142,7 @@ def run(
142
142
 
143
143
  -e, --env string 选择镜像
144
144
 
145
- -f, --follow [可选] 运行容器的状态跟踪
145
+ -f, --follow [可选] 跟踪容器运行;task 模式会自动打印实时日志直到任务结束,workspace 进入运行后退出
146
146
 
147
147
  -h, --help 查看 run 的帮助
148
148
 
@@ -249,7 +249,12 @@ def run(
249
249
  gear_settings.update_jid(str(current_path), job_id)
250
250
 
251
251
  if follow and mode != ModeEnum.hypertuning:
252
- gear_usecase.follow_status(job_id, party_name, True)
252
+ if mode == ModeEnum.workspace:
253
+ # workspace 进入 RUNNING 即视为就绪
254
+ gear_usecase.follow_status(job_id, party_name, stop_with_running=True)
255
+ else:
256
+ # task 等到 RUNNING 后切换为日志流,跟随直到任务结束
257
+ gear_usecase.follow_logs_until_finished(job_id, party_name)
253
258
  gear_usecase.print_last_status(job_id, party_name)
254
259
 
255
260
 
@@ -304,7 +309,7 @@ def restart(ctx: typer.Context,
304
309
  data: List[str] = typer.Option([], "-d", "--data", help="绑定数据"),
305
310
  env: str = typer.Option("", "-e", "--env", help="选择镜像"),
306
311
  resource: str = typer.Option("", "-r", "--resource", help="选择算力"),
307
- follow: bool = typer.Option(False, "-f", "--follow", help="运行容器的状态跟踪"),
312
+ follow: bool = typer.Option(False, "-f", "--follow", help="跟踪容器运行;task 模式会自动打印实时日志直到任务结束,workspace 进入运行后退出"),
308
313
  message: str = typer.Option("", "-m", "--message", help="执行描述"),
309
314
  open_browser: bool = typer.Option(False, "-o", "--open", help="成功创建容器后,在浏览器打开"),
310
315
  node: int = typer.Option(-1, "-n", "--node", help="指定运行节点数量"),
@@ -322,7 +327,7 @@ def restart(ctx: typer.Context,
322
327
 
323
328
  -e, --env string 选择镜像
324
329
 
325
- -f, --follow [可选] 继续执行容器的状态跟踪
330
+ -f, --follow [可选] 跟踪容器运行;task 模式会自动打印实时日志直到任务结束,workspace 进入运行后退出
326
331
 
327
332
  -h, --help 查看 restart 的帮助
328
333
 
@@ -385,7 +390,10 @@ def restart(ctx: typer.Context,
385
390
  open_usecase.open_browser(new_open_url)
386
391
 
387
392
  if follow:
388
- gear_usecase.follow_status(job_id, party_name, True)
393
+ if job.is_workspace():
394
+ gear_usecase.follow_status(job_id, party_name, stop_with_running=True)
395
+ else:
396
+ gear_usecase.follow_logs_until_finished(job_id, party_name)
389
397
  gear_usecase.print_last_status(job_id, party_name)
390
398
 
391
399
 
@@ -448,7 +456,8 @@ def stop(ctx: typer.Context,
448
456
  open_usecase.open_browser(link_value)
449
457
 
450
458
  if follow:
451
- gear_usecase.follow_status(id, party_name, True)
459
+ # 等待容器真正进入终止态(CANCELLED / FAILED / SUCCEEDED),否则中途的 RUNNING 会让跟踪过早退出。
460
+ gear_usecase.follow_status(id, party_name, False)
452
461
  gear_usecase.print_last_status(id, party_name)
453
462
 
454
463
 
@@ -125,7 +125,7 @@ def run(
125
125
  data: List[str] = typer.Option([], "-d", "--data", help="绑定数据"),
126
126
  env: str = typer.Option("", "-e", "--env", help="选择镜像"),
127
127
  resource: str = typer.Option("", "-r", "--resource", help="选择算力"),
128
- follow: bool = typer.Option(False, "-f", "--follow", help="运行容器的状态跟踪"),
128
+ follow: bool = typer.Option(False, "-f", "--follow", help="跟踪容器运行;task 模式会自动打印实时日志直到任务结束,workspace 进入运行后退出"),
129
129
  message: str = typer.Option("", "-m", "--message", help="执行描述"),
130
130
  open_browser: bool = typer.Option(False, "-o", "--open", help="成功创建容器后,在浏览器打开"),
131
131
  node: int = typer.Option(-1, "-n", "--node", help="指定运行节点数量"),
@@ -143,7 +143,7 @@ def run(
143
143
 
144
144
  -e, --env string 选择镜像
145
145
 
146
- -f, --follow [可选] 运行容器的状态跟踪
146
+ -f, --follow [可选] 跟踪容器运行;task 模式会自动打印实时日志直到任务结束,workspace 进入运行后退出
147
147
 
148
148
  -h, --help 查看 run 的帮助
149
149
 
@@ -252,7 +252,10 @@ def run(
252
252
  gear_settings.update_jid(str(current_path), job_id)
253
253
 
254
254
  if follow and mode != ModeEnum.hypertuning:
255
- gear_usecase.follow_status(job_id, party_name, True)
255
+ if mode == ModeEnum.workspace:
256
+ gear_usecase.follow_status(job_id, party_name, stop_with_running=True)
257
+ else:
258
+ gear_usecase.follow_logs_until_finished(job_id, party_name)
256
259
  gear_usecase.print_last_status(job_id, party_name)
257
260
 
258
261
 
@@ -307,7 +310,7 @@ def restart(ctx: typer.Context,
307
310
  data: List[str] = typer.Option([], "-d", "--data", help="绑定数据"),
308
311
  env: str = typer.Option("", "-e", "--env", help="选择镜像"),
309
312
  resource: str = typer.Option("", "-r", "--resource", help="选择算力"),
310
- follow: bool = typer.Option(False, "-f", "--follow", help="运行容器的状态跟踪"),
313
+ follow: bool = typer.Option(False, "-f", "--follow", help="跟踪容器运行;task 模式会自动打印实时日志直到任务结束,workspace 进入运行后退出"),
311
314
  message: str = typer.Option("", "-m", "--message", help="执行描述"),
312
315
  open_browser: bool = typer.Option(False, "-o", "--open", help="成功创建容器后,在浏览器打开"),
313
316
  node: int = typer.Option(-1, "-n", "--node", help="指定运行节点数量"),
@@ -325,7 +328,7 @@ def restart(ctx: typer.Context,
325
328
 
326
329
  -e, --env string 选择镜像
327
330
 
328
- -f, --follow [可选] 继续执行容器的状态跟踪
331
+ -f, --follow [可选] 跟踪容器运行;task 模式会自动打印实时日志直到任务结束,workspace 进入运行后退出
329
332
 
330
333
  -h, --help 查看 restart 的帮助
331
334
 
@@ -388,7 +391,10 @@ def restart(ctx: typer.Context,
388
391
  open_usecase.open_browser(new_open_url)
389
392
 
390
393
  if follow:
391
- gear_usecase.follow_status(job_id, party_name, True)
394
+ if job.is_workspace():
395
+ gear_usecase.follow_status(job_id, party_name, stop_with_running=True)
396
+ else:
397
+ gear_usecase.follow_logs_until_finished(job_id, party_name)
392
398
  gear_usecase.print_last_status(job_id, party_name)
393
399
 
394
400
 
@@ -452,7 +458,8 @@ def stop(ctx: typer.Context,
452
458
  open_usecase.open_browser(link_value)
453
459
 
454
460
  if follow:
455
- gear_usecase.follow_status(id, party_name, True)
461
+ # 等待容器真正进入终止态(CANCELLED / FAILED / SUCCEEDED),否则中途的 RUNNING 会让跟踪过早退出。
462
+ gear_usecase.follow_status(id, party_name, False)
456
463
  gear_usecase.print_last_status(id, party_name)
457
464
 
458
465
 
@@ -26,7 +26,7 @@ from bayes.model.file.openbayes_gear import (
26
26
  )
27
27
  from bayes.model.file.openbayes_ignore import OpenBayesIgnoreSettings
28
28
  from bayes.model.file.settings import BayesEnvConfig, BayesSettings
29
- from bayes.usercases import dataset_version_usecase
29
+ from bayes.usercases import dataset_version_usecase, gear_logs_usecase
30
30
  from bayes.usercases.org_usecase import display_table
31
31
  from bayes.utils import Utils
32
32
 
@@ -194,6 +194,54 @@ def follow_status(id, party_name, stop_with_running):
194
194
  time.sleep(0.1)
195
195
 
196
196
 
197
+ def follow_logs_until_finished(id, party_name):
198
+ """先等容器进入 RUNNING(或直接 finished),再切换到日志流跟随直到容器结束。
199
+
200
+ 日志流不可用时降级为单纯的状态轮询,保证 -f 至少跟到 finished。
201
+ """
202
+ follow_status(id, party_name, stop_with_running=True)
203
+
204
+ default_env: Optional[BayesEnvConfig] = BayesSettings().default_env
205
+ gql_client = BayesGQLClient(default_env.graphQL, default_env.token)
206
+ job = gear_client.get_job_by_id(gql_client, id, party_name)
207
+ if job is None or job.is_finished():
208
+ return
209
+
210
+ historical = gear_logs_usecase.get_logs(id, party_name)
211
+ if historical:
212
+ print(historical)
213
+
214
+ ws, error = gear_logs_usecase.get_logs_follow(id, party_name)
215
+ if error is not None or ws is None:
216
+ # 拿不到日志流就退化成轮询状态,仍然跟到任务结束
217
+ follow_status(id, party_name, stop_with_running=False)
218
+ return
219
+
220
+ print("已连接到日志流,按 Ctrl+C 停止跟踪...")
221
+ log_stream_closed = False
222
+ try:
223
+ while True:
224
+ data, err = gear_logs_usecase.receive_logs(ws, id)
225
+ if err is not None:
226
+ print(err)
227
+ log_stream_closed = True
228
+ break
229
+ if data:
230
+ print(data)
231
+ except KeyboardInterrupt:
232
+ print("\n已停止日志跟踪")
233
+ finally:
234
+ try:
235
+ ws.close()
236
+ except Exception:
237
+ pass
238
+
239
+ # 日志流自然结束后,job 状态需要几秒才上报为 finished;这里轮询一下,
240
+ # 让调用方的 print_last_status 拿到正确的最终状态。Ctrl+C 提前退出则跳过。
241
+ if log_stream_closed:
242
+ follow_status(id, party_name, stop_with_running=False)
243
+
244
+
197
245
  def print_last_status(id, party_name):
198
246
  default_env: Optional[BayesEnvConfig] = BayesSettings().default_env
199
247
  gql_client = BayesGQLClient(default_env.graphQL, default_env.token)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "openbayes-cli"
3
- version = "0.26.0"
3
+ version = "0.26.1"
4
4
  description = "A Python CLI for OpenBayes"
5
5
  authors = ["OpenBayes <dev@openbayes.com>"]
6
6
  readme = "README.md"
File without changes