experimaestro 2.0.0b8__py3-none-any.whl → 2.0.0b17__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.

Potentially problematic release.


This version of experimaestro might be problematic. Click here for more details.

Files changed (152) hide show
  1. experimaestro/__init__.py +12 -5
  2. experimaestro/cli/__init__.py +239 -126
  3. experimaestro/cli/filter.py +48 -23
  4. experimaestro/cli/jobs.py +253 -71
  5. experimaestro/cli/refactor.py +1 -2
  6. experimaestro/commandline.py +7 -4
  7. experimaestro/connectors/__init__.py +9 -1
  8. experimaestro/connectors/local.py +43 -3
  9. experimaestro/core/arguments.py +18 -18
  10. experimaestro/core/identifier.py +11 -11
  11. experimaestro/core/objects/config.py +96 -39
  12. experimaestro/core/objects/config_walk.py +3 -3
  13. experimaestro/core/{subparameters.py → partial.py} +16 -16
  14. experimaestro/core/partial_lock.py +394 -0
  15. experimaestro/core/types.py +12 -15
  16. experimaestro/dynamic.py +290 -0
  17. experimaestro/experiments/__init__.py +6 -2
  18. experimaestro/experiments/cli.py +217 -50
  19. experimaestro/experiments/configuration.py +24 -0
  20. experimaestro/generators.py +5 -5
  21. experimaestro/ipc.py +118 -1
  22. experimaestro/launcherfinder/__init__.py +2 -2
  23. experimaestro/launcherfinder/registry.py +6 -7
  24. experimaestro/launcherfinder/specs.py +2 -9
  25. experimaestro/launchers/slurm/__init__.py +2 -2
  26. experimaestro/launchers/slurm/base.py +62 -0
  27. experimaestro/locking.py +957 -1
  28. experimaestro/notifications.py +89 -201
  29. experimaestro/progress.py +63 -366
  30. experimaestro/rpyc.py +0 -2
  31. experimaestro/run.py +29 -2
  32. experimaestro/scheduler/__init__.py +8 -1
  33. experimaestro/scheduler/base.py +629 -53
  34. experimaestro/scheduler/dependencies.py +20 -16
  35. experimaestro/scheduler/experiment.py +732 -167
  36. experimaestro/scheduler/interfaces.py +316 -101
  37. experimaestro/scheduler/jobs.py +58 -20
  38. experimaestro/scheduler/remote/adaptive_sync.py +265 -0
  39. experimaestro/scheduler/remote/client.py +171 -117
  40. experimaestro/scheduler/remote/protocol.py +8 -193
  41. experimaestro/scheduler/remote/server.py +95 -71
  42. experimaestro/scheduler/services.py +53 -28
  43. experimaestro/scheduler/state_provider.py +663 -2430
  44. experimaestro/scheduler/state_status.py +1247 -0
  45. experimaestro/scheduler/transient.py +31 -0
  46. experimaestro/scheduler/workspace.py +1 -1
  47. experimaestro/scheduler/workspace_state_provider.py +1273 -0
  48. experimaestro/scriptbuilder.py +4 -4
  49. experimaestro/settings.py +36 -0
  50. experimaestro/tests/conftest.py +33 -5
  51. experimaestro/tests/connectors/bin/executable.py +1 -1
  52. experimaestro/tests/fixtures/pre_experiment/experiment_check_env.py +16 -0
  53. experimaestro/tests/fixtures/pre_experiment/experiment_check_mock.py +14 -0
  54. experimaestro/tests/fixtures/pre_experiment/experiment_simple.py +12 -0
  55. experimaestro/tests/fixtures/pre_experiment/pre_setup_env.py +5 -0
  56. experimaestro/tests/fixtures/pre_experiment/pre_setup_error.py +3 -0
  57. experimaestro/tests/fixtures/pre_experiment/pre_setup_mock.py +8 -0
  58. experimaestro/tests/launchers/bin/test.py +1 -0
  59. experimaestro/tests/launchers/test_slurm.py +9 -9
  60. experimaestro/tests/partial_reschedule.py +46 -0
  61. experimaestro/tests/restart.py +3 -3
  62. experimaestro/tests/restart_main.py +1 -0
  63. experimaestro/tests/scripts/notifyandwait.py +1 -0
  64. experimaestro/tests/task_partial.py +38 -0
  65. experimaestro/tests/task_tokens.py +2 -2
  66. experimaestro/tests/tasks/test_dynamic.py +6 -6
  67. experimaestro/tests/test_dependencies.py +3 -3
  68. experimaestro/tests/test_deprecated.py +15 -15
  69. experimaestro/tests/test_dynamic_locking.py +317 -0
  70. experimaestro/tests/test_environment.py +24 -14
  71. experimaestro/tests/test_experiment.py +171 -36
  72. experimaestro/tests/test_identifier.py +25 -25
  73. experimaestro/tests/test_identifier_stability.py +3 -5
  74. experimaestro/tests/test_multitoken.py +2 -4
  75. experimaestro/tests/{test_subparameters.py → test_partial.py} +25 -25
  76. experimaestro/tests/test_partial_paths.py +81 -138
  77. experimaestro/tests/test_pre_experiment.py +219 -0
  78. experimaestro/tests/test_progress.py +2 -8
  79. experimaestro/tests/test_remote_state.py +560 -99
  80. experimaestro/tests/test_stray_jobs.py +261 -0
  81. experimaestro/tests/test_tasks.py +1 -2
  82. experimaestro/tests/test_token_locking.py +52 -67
  83. experimaestro/tests/test_tokens.py +5 -6
  84. experimaestro/tests/test_transient.py +225 -0
  85. experimaestro/tests/test_workspace_state_provider.py +768 -0
  86. experimaestro/tests/token_reschedule.py +1 -3
  87. experimaestro/tests/utils.py +2 -7
  88. experimaestro/tokens.py +227 -372
  89. experimaestro/tools/diff.py +1 -0
  90. experimaestro/tools/documentation.py +4 -5
  91. experimaestro/tools/jobs.py +1 -2
  92. experimaestro/tui/app.py +438 -1966
  93. experimaestro/tui/app.tcss +162 -0
  94. experimaestro/tui/dialogs.py +172 -0
  95. experimaestro/tui/log_viewer.py +253 -3
  96. experimaestro/tui/messages.py +137 -0
  97. experimaestro/tui/utils.py +54 -0
  98. experimaestro/tui/widgets/__init__.py +23 -0
  99. experimaestro/tui/widgets/experiments.py +468 -0
  100. experimaestro/tui/widgets/global_services.py +238 -0
  101. experimaestro/tui/widgets/jobs.py +972 -0
  102. experimaestro/tui/widgets/log.py +156 -0
  103. experimaestro/tui/widgets/orphans.py +363 -0
  104. experimaestro/tui/widgets/runs.py +185 -0
  105. experimaestro/tui/widgets/services.py +314 -0
  106. experimaestro/tui/widgets/stray_jobs.py +528 -0
  107. experimaestro/utils/__init__.py +1 -1
  108. experimaestro/utils/environment.py +105 -22
  109. experimaestro/utils/fswatcher.py +124 -0
  110. experimaestro/utils/jobs.py +1 -2
  111. experimaestro/utils/jupyter.py +1 -2
  112. experimaestro/utils/logging.py +72 -0
  113. experimaestro/version.py +2 -2
  114. experimaestro/webui/__init__.py +9 -0
  115. experimaestro/webui/app.py +117 -0
  116. experimaestro/{server → webui}/data/index.css +66 -11
  117. experimaestro/webui/data/index.css.map +1 -0
  118. experimaestro/{server → webui}/data/index.js +82763 -87217
  119. experimaestro/webui/data/index.js.map +1 -0
  120. experimaestro/webui/routes/__init__.py +5 -0
  121. experimaestro/webui/routes/auth.py +53 -0
  122. experimaestro/webui/routes/proxy.py +117 -0
  123. experimaestro/webui/server.py +200 -0
  124. experimaestro/webui/state_bridge.py +152 -0
  125. experimaestro/webui/websocket.py +413 -0
  126. {experimaestro-2.0.0b8.dist-info → experimaestro-2.0.0b17.dist-info}/METADATA +5 -6
  127. experimaestro-2.0.0b17.dist-info/RECORD +219 -0
  128. experimaestro/cli/progress.py +0 -269
  129. experimaestro/scheduler/state.py +0 -75
  130. experimaestro/scheduler/state_db.py +0 -437
  131. experimaestro/scheduler/state_sync.py +0 -891
  132. experimaestro/server/__init__.py +0 -467
  133. experimaestro/server/data/index.css.map +0 -1
  134. experimaestro/server/data/index.js.map +0 -1
  135. experimaestro/tests/test_cli_jobs.py +0 -615
  136. experimaestro/tests/test_file_progress.py +0 -425
  137. experimaestro/tests/test_file_progress_integration.py +0 -477
  138. experimaestro/tests/test_state_db.py +0 -434
  139. experimaestro-2.0.0b8.dist-info/RECORD +0 -187
  140. /experimaestro/{server → webui}/data/1815e00441357e01619e.ttf +0 -0
  141. /experimaestro/{server → webui}/data/2463b90d9a316e4e5294.woff2 +0 -0
  142. /experimaestro/{server → webui}/data/2582b0e4bcf85eceead0.ttf +0 -0
  143. /experimaestro/{server → webui}/data/89999bdf5d835c012025.woff2 +0 -0
  144. /experimaestro/{server → webui}/data/914997e1bdfc990d0897.ttf +0 -0
  145. /experimaestro/{server → webui}/data/c210719e60948b211a12.woff2 +0 -0
  146. /experimaestro/{server → webui}/data/favicon.ico +0 -0
  147. /experimaestro/{server → webui}/data/index.html +0 -0
  148. /experimaestro/{server → webui}/data/login.html +0 -0
  149. /experimaestro/{server → webui}/data/manifest.json +0 -0
  150. {experimaestro-2.0.0b8.dist-info → experimaestro-2.0.0b17.dist-info}/WHEEL +0 -0
  151. {experimaestro-2.0.0b8.dist-info → experimaestro-2.0.0b17.dist-info}/entry_points.txt +0 -0
  152. {experimaestro-2.0.0b8.dist-info → experimaestro-2.0.0b17.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,219 @@
1
+ experimaestro/__init__.py,sha256=fGG4EuceRzoqPDFXbkyFZobB14V874UUOPFpr0KA1A4,1823
2
+ experimaestro/__main__.py,sha256=Dv9lFl03yt1dswd0Xb9NIJRgHpA5_IwH4RfQPEHyFz0,158
3
+ experimaestro/annotations.py,sha256=1gdi17YT7t1WteJCUz7SAis0J1ctQl2ABxlUv49mXog,8842
4
+ experimaestro/checkers.py,sha256=ZCMbnE_GFC5compWjt-fuHhPImi9fCPjImF8Ow9NqK8,696
5
+ experimaestro/click.py,sha256=6FQPLtD61C65lcOYy-dOIOukXIeJEanhAUQO1ax1jHI,1311
6
+ experimaestro/commandline.py,sha256=XSCiL7cXWQaqOAu-HSL7nXB6HincN8_N5sZTtrKOzjM,9741
7
+ experimaestro/dynamic.py,sha256=hmiIrxzeZh7vTbNG81phWN-GlE6M9lzNsuk2jMwEKnk,9532
8
+ experimaestro/exceptions.py,sha256=dVdbYwbpJokjqu-m8go5Oh6TpvSMbT2ztv1P3aV9weQ,990
9
+ experimaestro/generators.py,sha256=HIcjxutBEI7GmUpeFgunLWB2a4HHrEvmW-LKRbCbIz0,2888
10
+ experimaestro/huggingface.py,sha256=G8kTgFzhCRJJfz1DcbZsPD7NprDYVajW-rTBAjg6jX4,3000
11
+ experimaestro/ipc.py,sha256=A5sZ_-GgVxWv6ty-Kz_unBMgacreuSO-TrNZilsVYqA,5393
12
+ experimaestro/locking.py,sha256=DbHZEpyb0SOzQ3wwx3CbeJFqOhbyKbnOhMPDaMOUq6Y,32583
13
+ experimaestro/mypy.py,sha256=WyaZU01v8sSqXc7meiIY-e8cBKqKrMbK-ITlpUkIrgc,14217
14
+ experimaestro/notifications.py,sha256=2IBYQEwTRDKWzurPA2GhMcPn5FdZpgyqJPR7MqYCfpM,6976
15
+ experimaestro/progress.py,sha256=gj_oH51KX6hQT6ZtWYjtd6GkBYHwOwDT3-sGbGHAu5g,3650
16
+ experimaestro/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ experimaestro/rpyc.py,sha256=yVxA7KAA7AD1o2SJv5BulY04-nA3krp0_7ua1K-BoNw,3526
18
+ experimaestro/run.py,sha256=eTHB1EhekPwVoCsZZJxGyKYgYwRE2RtIzIbj5IQ7sw0,7120
19
+ experimaestro/scriptbuilder.py,sha256=r7n4k4F7CsRXK3D4OWaA7aeyKqxz_sYfiDjMkzAKSfo,5307
20
+ experimaestro/settings.py,sha256=idE2dLj8-pcbRpHTmSj0Lecu-aRYEalgiQvbTDFcY2Q,5763
21
+ experimaestro/taskglobals.py,sha256=A_P49RHu8FLOfoybfwcLzDcDZiUug4mLFKiAzsCof_k,1315
22
+ experimaestro/tokens.py,sha256=HG8gCtuawR0llKBr1gsAk4XV4n9GiiiVVdIPabwmIa0,13635
23
+ experimaestro/typingutils.py,sha256=v7wS9xewF3cYOKvaBFxlTB-qplJ8olI1OaO3tAKiwIo,3678
24
+ experimaestro/version.py,sha256=mPTLTNByL1YBlqNfyX-dOwy7Ii6RHijbs-ImrwYJ8WY,714
25
+ experimaestro/xpmutils.py,sha256=S21eMbDYsHfvmZ1HmKpq5Pz5O-1HnCLYxKbyTBbASyQ,638
26
+ experimaestro/cli/__init__.py,sha256=NPbvO67Rkq0ESFy5ldXgMrkIXVHTX1E9Evr1hj5Q8sQ,21876
27
+ experimaestro/cli/filter.py,sha256=_mLPWsvuKPc-mfQq6PQaBVOeM8Cq1BSWz5fYqYcZzTM,6073
28
+ experimaestro/cli/jobs.py,sha256=f-Y9HLtfZwts3IGCF2NI6os056LgOrntwQwYMmLe_Ok,16033
29
+ experimaestro/cli/refactor.py,sha256=SAdWnYtVpkXkqTz7ezUhXoIBBw4b1Yx-8uEjJbOWQR0,8277
30
+ experimaestro/connectors/__init__.py,sha256=0qFKkfJH2yPCLdrVyZPd8XQB54GsR-NBANSse3cfpW0,7097
31
+ experimaestro/connectors/local.py,sha256=kSfchwx5jHl_MJcY8IlVvW_DNJt3JTHYchfXqp0uLgs,7971
32
+ experimaestro/connectors/ssh.py,sha256=5giqvv1y0QQKF-GI0IFUzI_Z5H8Bj9EuL_Szpvk899Q,8600
33
+ experimaestro/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ experimaestro/core/arguments.py,sha256=MAltbcqFQO7kHwndmeJ5NuyDU5Pq_JrTRQsxUKb0yaQ,13151
35
+ experimaestro/core/callbacks.py,sha256=59JfeUgWcCCdIQ3pvh-xNnoRp9BX8f4iOAkgm16wBzE,1660
36
+ experimaestro/core/context.py,sha256=1tLmX7WcgEKSbGw77vfziTzS8KNsoZJ02JBWMBCqqOk,2606
37
+ experimaestro/core/identifier.py,sha256=gbyHAzfjN3Wn9uEN_s1LPwP4VW8ZYTxtMrQat9iziis,15299
38
+ experimaestro/core/partial.py,sha256=OS33qvjrVKoXhQuamGdtVj4oUg2GFFgGqG2niPPGrPI,5751
39
+ experimaestro/core/partial_lock.py,sha256=CCjNHSy1xbEScHirEnFYPt7QAHB95UoVCbs_e9NrMeI,13878
40
+ experimaestro/core/serialization.py,sha256=nwHqnSjplceGxFJs1CsVkHmlG6uK89G_nXq39B0FYrg,8365
41
+ experimaestro/core/serializers.py,sha256=iOBuASEgD8dRKPnL16iOLBsM0GHChCJgjBd7LixFui4,919
42
+ experimaestro/core/types.py,sha256=h80ofaPOxJ0s9vhTbSJ653A7jFxW11xnpRcchtExP7k,26736
43
+ experimaestro/core/utils.py,sha256=JfC3qGUS9b6FUHc2VxIYUI9ysNpXSQ1LjOBkjfZ8n7o,495
44
+ experimaestro/core/objects/__init__.py,sha256=-7FUbhIgZ1_eqi9RKwQZRPmxrtLgt2DqqOge7Blz5ZU,833
45
+ experimaestro/core/objects/config.py,sha256=n4FiRzv_vwRCHkJBXPNl3VouKAni57_IwbqJpxKx2Io,76644
46
+ experimaestro/core/objects/config_utils.py,sha256=ZLECGkeIWdzunm8vwWsQhvcSgV1e064BgXbLiZnxSEM,1288
47
+ experimaestro/core/objects/config_walk.py,sha256=KmFo1d9QNU44PpDLw7Y3ZmPK0YcCyBAlALF33barWVE,4956
48
+ experimaestro/experiments/__init__.py,sha256=K1hyfi_44937dABlcNmwY_72efISLexQFge06veTv9c,155
49
+ experimaestro/experiments/cli.py,sha256=5mIS7_q-YxNUdAsOlnYGvoiiduG0k9yhei0jOCSc1sg,19590
50
+ experimaestro/experiments/configuration.py,sha256=nz7CzsTOxwIS3YVOM-VWgK3_M1PFShfpb7YshXEFOLg,2282
51
+ experimaestro/launcherfinder/__init__.py,sha256=O4HKPAdG5v4tt9DflHJuf3z6vhOj6gr69l1_gJqKdUQ,318
52
+ experimaestro/launcherfinder/base.py,sha256=q47SsF_cXdo5O6ZhFKn5385WVFcx8Wd-BcEpd6tRpbs,515
53
+ experimaestro/launcherfinder/parser.py,sha256=2Z4lIX5drbZr5jWqL2vZy1qmPfFw_homxaXEb86fKTc,3489
54
+ experimaestro/launcherfinder/registry.py,sha256=LBKdlCu3zYJQLgwZJD8_Cn7-B_SOQVrurcX-lKp7Prs,6379
55
+ experimaestro/launcherfinder/specs.py,sha256=ENQ0BKIuRKjoKT7ctiWY0rqEYfs1fcBF2ZFGfD8NdBA,7803
56
+ experimaestro/launchers/__init__.py,sha256=asoe6Bn7tjXEpZL7sfpV5V7k7YWFexZWaxtYtBY7Se8,3440
57
+ experimaestro/launchers/direct.py,sha256=7Uec6dkssUzHOYcXz6ZwOr-NF-CuiXuQU3Uj11IHKz0,678
58
+ experimaestro/launchers/oar.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
+ experimaestro/launchers/slurm/__init__.py,sha256=NFYOFb8liS1Ll4GoxiHBCbNa-PK8DEZIiLdvcyQqpFw,53
60
+ experimaestro/launchers/slurm/base.py,sha256=HbfWVlg_ssbfxqx97Gt3MyIBgFpIv85uf2Wbw_WmymM,23368
61
+ experimaestro/mkdocs/__init__.py,sha256=L9UDM7vOrRZl41zXTBOaHKSINEEsbmxwjIMIGESmLfU,46
62
+ experimaestro/mkdocs/annotations.py,sha256=qpDw8lzrxpsOShXcpcP_LAeR3UhiIXAybG8UvS64-OU,263
63
+ experimaestro/mkdocs/base.py,sha256=qHDZZFdoNRsW6RcjRB1WCSp2sOtRiBk9zFO1acK05BQ,16706
64
+ experimaestro/mkdocs/metaloader.py,sha256=ItchfE3emrzKUrT-8f8WsDHNHisYzs9XDCzhWcu6VaQ,1471
65
+ experimaestro/mkdocs/style.css,sha256=42kJ6Ozq_n4Iw5UfJ4-nO1u-HN3ELvV7Vhvj1Xkn7rQ,66
66
+ experimaestro/scheduler/__init__.py,sha256=c5lquqWQ_qk78vU9rhSFO0CGb6nRsr1hPO2IAgHHeTs,533
67
+ experimaestro/scheduler/base.py,sha256=2ycw5I-DmoakoX-asmUzcPBK5a2TakFz0mmj1biiieM,49754
68
+ experimaestro/scheduler/dependencies.py,sha256=L2GX6ZoD2o-jspON61jzRqOI-SNqOpTSrllvpp2mIPg,2598
69
+ experimaestro/scheduler/dynamic_outputs.py,sha256=pKSm73D_XIgUHawf432JJXfQKISO34qEMf5w-nWTl-g,11187
70
+ experimaestro/scheduler/experiment.py,sha256=X7bMHSrlMDTuMcuUlb4QLZSpunrjUBMxC-a7LifVnZg,43931
71
+ experimaestro/scheduler/interfaces.py,sha256=Zlc5fxC9otpwTV10UmGMY_U1OBxBQyIxRcbuKHO9rW0,22426
72
+ experimaestro/scheduler/jobs.py,sha256=Nhrj75Lcavtxbh8V4VVC0f9Ojq6dZcLBjYAFqY7kI0U,17162
73
+ experimaestro/scheduler/services.py,sha256=j6r0akI2niQQQv88Vo81HmMzy3YACu4g7b0xEcl8W-g,13983
74
+ experimaestro/scheduler/signal_handler.py,sha256=B4ZeSVB8O41VDdFmV4n2cyBds7wKFG3kH2Fp7cpyxa4,872
75
+ experimaestro/scheduler/state_provider.py,sha256=g7G5Pj6JEwWNR1C-eanpQyC4oKVlgkA5o-KHVDu3S1I,34138
76
+ experimaestro/scheduler/state_status.py,sha256=K-jeR7yZ5thz6Gc1hn7uzZUAxTQ4Byfg4ZqdmMZku6E,43439
77
+ experimaestro/scheduler/transient.py,sha256=pg7h17Y2zRTTZRnUgRkDx6H4QWnErAwGgbIWMrKGqcw,893
78
+ experimaestro/scheduler/workspace.py,sha256=PF_dirRAdrVqt6f8u9lJu6RY7ZRsd47OlRwbIjNH_PA,3824
79
+ experimaestro/scheduler/workspace_state_provider.py,sha256=mP5PB4YC6U6ofUYDj4EgcVOjSmFDApaus-lqYXpVZW4,46593
80
+ experimaestro/scheduler/remote/__init__.py,sha256=QBXrl4V09nPbwxKRtV7-uLdZCXtktWBeSAV7kB2ZWOM,1134
81
+ experimaestro/scheduler/remote/adaptive_sync.py,sha256=uU7jTEtx9sQTJtdhXgKHtBEPAHN1wuN9SbPLLSQw3lk,8903
82
+ experimaestro/scheduler/remote/client.py,sha256=kULgKfBzFOeh3CflbYmY1pFho3yZNKTTKMwACLRLKIw,33516
83
+ experimaestro/scheduler/remote/protocol.py,sha256=EvYCmgeZB005Qd6l94YLuM0d7ToD6QcibVwqNHYse80,7474
84
+ experimaestro/scheduler/remote/server.py,sha256=brjAfCK81ktbyWAcJmAvp6XetC6xTRAAnczfMBH8Euo,16268
85
+ experimaestro/scheduler/remote/sync.py,sha256=BgPK96EJY3AxjBmrwo53CN5fUmGED-a12ZTODkJ_mQk,4917
86
+ experimaestro/sphinx/__init__.py,sha256=DhFRj8MxA9XZH-TCnbl_5bYhGiF4ihiuFwQj74oPEp4,9466
87
+ experimaestro/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
+ experimaestro/tests/conftest.py,sha256=KjlRfXdlfzfhg7sFfTUF9fhXJJaXPirFaYobdhW8zm8,4754
89
+ experimaestro/tests/definitions_types.py,sha256=nMoQxZxhTJAYV87Ce9F2dAITxXGHf7Uw5j-MKsZ3LmQ,399
90
+ experimaestro/tests/identifier_stability.json,sha256=ygb6p1e8RsjGoqvGoW02ftFCCZIXAZIBsDZjP0Zsdhg,3791
91
+ experimaestro/tests/partial_reschedule.py,sha256=KicxIbzsVBy0kI6YNM2_dfOXzhpCEd9_zkvrZz4cdR4,1694
92
+ experimaestro/tests/restart.py,sha256=RVuFSMPwNFZyk0tC1tO8OSY1BkOEYeY61V4mMlq3GI8,4191
93
+ experimaestro/tests/restart_main.py,sha256=bU_L5bwWyFGdbJf_yPxgS26eviEtaa4zJ0ad2C1GI_Y,335
94
+ experimaestro/tests/task_partial.py,sha256=fNsnA1cyS_bUo2YDqYVl4VxEoimJYGT0IYP1mTlXCPI,1128
95
+ experimaestro/tests/task_tokens.py,sha256=mumfDzT1C0ug8mS05PEVQO6kX1tQxwj5CO3wAlgP0so,505
96
+ experimaestro/tests/test_checkers.py,sha256=e6Rv2TlePRY__VXs0vUb6a5Aw_KIq_cs4N86VhnYHtw,407
97
+ experimaestro/tests/test_dependencies.py,sha256=yBmXDqTyXEnIlqgRt5i9YwhqiaczrNDMqg6ZEBWx05w,1890
98
+ experimaestro/tests/test_deprecated.py,sha256=NoxAAz0h9l4LhKNIwy3hPkKKIFgmpDTwxqNVBgqxkHk,20061
99
+ experimaestro/tests/test_dynamic_locking.py,sha256=SQZ7LwSiG3Gsc07-a5XjZYtFwPdNHW5WWSyHUhpiLwE,10572
100
+ experimaestro/tests/test_environment.py,sha256=DFULUs46Ysin2Hs9xRa9rCQpgPKV_r0k8TCBFymVBig,7457
101
+ experimaestro/tests/test_experiment.py,sha256=hqA69vhQpgDq-Laej2rYhcVdyX4CzDY_lyKg9-2RbhI,7191
102
+ experimaestro/tests/test_findlauncher.py,sha256=KPy8ow--NXS1KFCIpxrmEJFRvjo-v-PwlVHVyoVKLPg,3134
103
+ experimaestro/tests/test_forward.py,sha256=UYYmFl3N4icoA024ubKmCq_vngrGK2aBthfFptIX66U,786
104
+ experimaestro/tests/test_generators.py,sha256=R0UypTzxX0dPYvY4A_kozpLDHhGzQDNfLQyc0oRaSx8,2891
105
+ experimaestro/tests/test_identifier.py,sha256=__-Vwie4sbKJfcg3kFFGq4YVxerGSzHuCyspDo98M-g,26716
106
+ experimaestro/tests/test_identifier_stability.py,sha256=7_DfvReo4EuWOZlR1T7F3_hmx6mRf4NRuPIOsW1NwW8,12594
107
+ experimaestro/tests/test_instance.py,sha256=CZ49fjEIvbiJCb-GdDRSt7kP48JnpZUk1GvSvXNb1Bc,1376
108
+ experimaestro/tests/test_multitoken.py,sha256=7hIMnmnTyMrThLDfDSEB0u4tzQkHuaSmdxq2gEZzcdE,14398
109
+ experimaestro/tests/test_mypy.py,sha256=wtcPd8vCn7mCyMo5-DCaOEYZS9IARw3IGa-C4ezGKxs,11900
110
+ experimaestro/tests/test_objects.py,sha256=YVOfdWjAieFTWQFqm9Q6RFg8rBgNmP8_PXXmkX_RLMA,9988
111
+ experimaestro/tests/test_outputs.py,sha256=wO53O6yWVT2sBlRXHTgsv_9i_Y8X5-JnOVfrExQSw2M,826
112
+ experimaestro/tests/test_param.py,sha256=cmCvzpCGSNpcFAI2lfIQe2lTYBfxO8gr5I0SVXiNafQ,7346
113
+ experimaestro/tests/test_partial.py,sha256=BfiXpCcZXBd7irg_oUSLUQ9i6zt5LN3wvmX1IUycyNE,5650
114
+ experimaestro/tests/test_partial_paths.py,sha256=vmDWSA8fw3Qc8FA-rwCV-icQMriR_rmjcJfAlgA1aGE,6437
115
+ experimaestro/tests/test_pre_experiment.py,sha256=PkAtkRR9t9wOjTO8hti4TQunhfmv2jGhYys8NrId1U8,6085
116
+ experimaestro/tests/test_progress.py,sha256=D2mgB_8O1f9vYBRIjsFagl0eX6Bfjj8_lNc2oJQqqVI,5808
117
+ experimaestro/tests/test_remote_state.py,sha256=sMUXTBk1BKrBriSF-ZXcgggX8EasqEcLRXTE9Qp5OAU,40783
118
+ experimaestro/tests/test_resumable_task.py,sha256=H5plRfuQ7bhWzP9TQgGAxm6-GlbtPOTLm9WMZhvRUZ0,17080
119
+ experimaestro/tests/test_serializers.py,sha256=DWe3gbaQP16tQawDz8uSiDpQ_nyTuYjFMvoGEwIWfhU,5302
120
+ experimaestro/tests/test_snippets.py,sha256=rojnyDjtmAMnSuDUj6Bv9XEgdP8oQf2nVc132JF8vsM,3081
121
+ experimaestro/tests/test_ssh.py,sha256=KS1NWltiXrJBSStY9d4mwrexeqgNGWmhxuAU_WLQDAU,1449
122
+ experimaestro/tests/test_stray_jobs.py,sha256=LaRPeEmVyT7pejE84ZKIClMTKZN6wKvuaSw-lvi9bqo,9626
123
+ experimaestro/tests/test_tags.py,sha256=VTjowJljm8sCGiEuOIDeoNO4NPJNY1pu4b7G8dWqBes,6596
124
+ experimaestro/tests/test_tasks.py,sha256=QxjM3POpK3JD6AqoMo4NyIievSBLE9h0nGWHEXi59DA,9117
125
+ experimaestro/tests/test_token_locking.py,sha256=b_SFwh6JIu7Vi6AdKf_8wodvcXhvTkTrbAEisSBoww0,6600
126
+ experimaestro/tests/test_tokens.py,sha256=4nh6PI7BRChu2tv-UFYswsiMFpP61OCTUHRBimh3EAU,8074
127
+ experimaestro/tests/test_transient.py,sha256=3YTax2VG2C9XZmzVdwYf5cZVnEVNyC_rveCs21maoBU,8993
128
+ experimaestro/tests/test_types.py,sha256=AavpWOtwQTVp5IuzfwRskBU4khoeomXXizhZoeSVPp4,4724
129
+ experimaestro/tests/test_validation.py,sha256=tinkXETcAGtgPIsmbioKSU00kGIV1YnniHTGDDcUOq8,4118
130
+ experimaestro/tests/test_workspace_state_provider.py,sha256=OWtVqePsxrEn-LR8TEwHmyy5QwiLjmlrzl6QeGvL6kg,27439
131
+ experimaestro/tests/test_workspace_triggers.py,sha256=idXnS95CBNmTj3YajWS93ZCZfVzOffne2hcMIwmEd2w,4700
132
+ experimaestro/tests/token_reschedule.py,sha256=tPLllGjM7M1gnkSPXRYR1AlaNRAAEltFK_zfj4B9VQE,1772
133
+ experimaestro/tests/utils.py,sha256=sW2ou6eqgzc59RFK2_YxLXnjR2kGUHAdxypPTuZpllU,3704
134
+ experimaestro/tests/connectors/test_local.py,sha256=hMX3maYYRABGXqRZFZbTWjf-jcvPkBq9nReLtDwLydk,1204
135
+ experimaestro/tests/connectors/utils.py,sha256=9sM3Pwy2nRfSr7pwQoOoSCDhBrEcDsEElI08Fmrw_gU,702
136
+ experimaestro/tests/connectors/bin/executable.py,sha256=Ct66Ua0vqMi0GLO-fczpRPiKE1OC6NnX4oYXMQ45_6Y,35
137
+ experimaestro/tests/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
+ experimaestro/tests/core/test_generics.py,sha256=oRKSmmofWBwnL2DgUtILSuzjgaTd7Y3EeN003Me9SQk,5214
139
+ experimaestro/tests/fixtures/pre_experiment/experiment_check_env.py,sha256=MQxnxBvKI0xcRSxhodOTYoO0Smw5v1QwNmugfGou3Qw,477
140
+ experimaestro/tests/fixtures/pre_experiment/experiment_check_mock.py,sha256=CUCt2V5PVeQJBN3kycH8G8Z9pAhd4X9ZZj_WXZmsMRc,486
141
+ experimaestro/tests/fixtures/pre_experiment/experiment_simple.py,sha256=paQGawl7EFP6Gnrg672zxgAJVgRsoaG4Ej3T2jSk2kI,267
142
+ experimaestro/tests/fixtures/pre_experiment/pre_setup_env.py,sha256=LLiVpLM0yGs6a_EjqkPuYotGbYTKG48y7DcToszB1p0,126
143
+ experimaestro/tests/fixtures/pre_experiment/pre_setup_error.py,sha256=ucWzGnSPk-tRE0ws3kJVB8BezyZmj57ZVBOQBdhQTns,109
144
+ experimaestro/tests/fixtures/pre_experiment/pre_setup_mock.py,sha256=6YfBTIWYkdfFfHZtIJTrsuPNjGakwa0CNBzd7kvHTHo,220
145
+ experimaestro/tests/launchers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
146
+ experimaestro/tests/launchers/common.py,sha256=WqVcWX3g0XYJS0aJO7XWVvOmncRBbQmGvuNxH9AHUAE,2998
147
+ experimaestro/tests/launchers/test_local.py,sha256=4oGgWH2YgkEm-Muu6s4cwlgriXtYr5xAd72DVoIw_Yk,717
148
+ experimaestro/tests/launchers/test_slurm.py,sha256=fosrv1uXEDpRRtFIK--PqQA6uJI0kDXYmga4JDNsXZM,6010
149
+ experimaestro/tests/launchers/bin/sacct,sha256=hSrYRbwQBB0vY-Bn_FWvuU1xEXAv5G3fTUGglRpyv74,788
150
+ experimaestro/tests/launchers/bin/sbatch,sha256=iaek9dgAFeEs927QOQQcWkCIkXL-6PFsTSk4qjIx9ZQ,1780
151
+ experimaestro/tests/launchers/bin/srun,sha256=3oE3qq0UFpVtTvXfR1kH3tovFYX74fp1Fk-o8zgsaJA,47
152
+ experimaestro/tests/launchers/bin/test.py,sha256=NgGGydqrt-8eg05DmIasIyOhw8aCd1UJ8h6wyzH4f7I,533
153
+ experimaestro/tests/launchers/config_slurm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
154
+ experimaestro/tests/launchers/config_slurm/launchers.py,sha256=DohwQVv1eXWfDpAYFg7KJekEm7q7G-lMou2lPg-PKOk,838
155
+ experimaestro/tests/scripts/notifyandwait.py,sha256=-M-m6ZS2Tm53SqPTnCIzJbWKAM9CKe9Hb4_ePD3OSyU,470
156
+ experimaestro/tests/scripts/waitforfile.py,sha256=EDT-TuFi2fU_qt51K5EmAxjw_OnJKkBW7UCfhrtDbVw,120
157
+ experimaestro/tests/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
158
+ experimaestro/tests/tasks/all.py,sha256=2KF0D1CB2PBwM_aXX09Ug6vy0MUQgoTATdheNeNKXHg,2101
159
+ experimaestro/tests/tasks/foreign.py,sha256=uhXDOcWozkcm26ybbeEU9RElJpbhjC-zdzmlSKfPcdY,122
160
+ experimaestro/tests/tasks/test_dynamic.py,sha256=nLpJ9T_GefDa3OGTsSPhkScFjNy5rAT_ITRX80vjz74,7984
161
+ experimaestro/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
162
+ experimaestro/tools/diff.py,sha256=EdNY_znxiq2U_XLzu08FuEqar1NiPvukQctmNvFr1Is,3783
163
+ experimaestro/tools/documentation.py,sha256=bm_zu3-1oE3oh9MXkhnOQAIoDh7ckDQUH3_3OWHOafo,9169
164
+ experimaestro/tools/jobs.py,sha256=jJsVDqMRODpTnt8qDrxAYDffAHWxxeU7a3NM_GnBLuI,3485
165
+ experimaestro/tui/__init__.py,sha256=BTf7I5HtG7AA_vGTSG891Jjz4R3wf-cEnpaEwB6xBA4,197
166
+ experimaestro/tui/app.py,sha256=Q_drp1V0Dbl4tSynX6ljce8VwRPcShkF3V0J6t0lceg,35039
167
+ experimaestro/tui/dialogs.py,sha256=UpbWt77qS3Z2aDon1fNRwij9vx3eort6ue-zvhi1Y0Y,5506
168
+ experimaestro/tui/log_viewer.py,sha256=OAi7TSziFACQmHlIfsMtsZC9G1a57os3RqF769XY6QU,15849
169
+ experimaestro/tui/messages.py,sha256=LZwk7y6GDwnp90E-8BJ54BrxemaRVRbeUidtVroX1Yc,3748
170
+ experimaestro/tui/utils.py,sha256=FROnsiWZ-tHVnUwAhnkP6dKbK-ejsqCvCiA7hUyr16M,1911
171
+ experimaestro/tui/widgets/__init__.py,sha256=kt4KuZx6Kx4q0amKFdAkrQntaIzLmM-67-ZS0BSnbp8,746
172
+ experimaestro/tui/widgets/experiments.py,sha256=DNvTRi6lppGkXCdpto5qG0-G70rJxd3V_clq8fkb5p8,18148
173
+ experimaestro/tui/widgets/global_services.py,sha256=Hm8bv9i0GtPabmonAqeb_jvnZ11hWQkLOVNWK8qM4-8,8183
174
+ experimaestro/tui/widgets/jobs.py,sha256=0sHC3rZvUaTspJhY0Du8LrCskbNhFqwlQYdWwDR9CIU,37929
175
+ experimaestro/tui/widgets/log.py,sha256=_X6VyKu8C67V53SW1zVLNGgIHgOKCCZzSz3rq2JKx0o,5528
176
+ experimaestro/tui/widgets/orphans.py,sha256=fpJfvbwJBfWIbdKsAOsa6KsOaRpYi5zrcsMzzuQKUmE,13919
177
+ experimaestro/tui/widgets/runs.py,sha256=5MONyq8Y02ESFZeYYW5MXaH0F5QFKIUWKEpMQppnDSI,6586
178
+ experimaestro/tui/widgets/services.py,sha256=LBI0g1opxyFBO0I8DrjCkBvKPXfXQIrA8TaMVVsxzAk,11318
179
+ experimaestro/tui/widgets/stray_jobs.py,sha256=QoF9vMcPiqxWGMRydKPtiqvlm9Pgq-zxQgJmHFB2Pzg,19617
180
+ experimaestro/utils/__init__.py,sha256=bL8spQ7s0wZmpBYEbfk9mns9s7D6j1G4avDWD3tJ8Vc,3123
181
+ experimaestro/utils/asyncio.py,sha256=9r_vFQs6T6tqmymC_DbHVFhY9YVRO6X48uEuyL_ugP8,726
182
+ experimaestro/utils/environment.py,sha256=7Rl66V-1NZ57AJBUUIkMI9DFB-b9RJijy1kr1oWfK14,7963
183
+ experimaestro/utils/fswatcher.py,sha256=d4Lymhrl94jSy18hj2dOcjrGLIC-kZbKQFYCQhC7BvU,3935
184
+ experimaestro/utils/git.py,sha256=l2jcqRIgSygg5ZtrlFE9w5hsS4gr2Zca4I5OGmAwMdo,3830
185
+ experimaestro/utils/jobs.py,sha256=gNWFLFphW5g64JlxyxaXQB_BpytjmMpTVJHihggM9wQ,2362
186
+ experimaestro/utils/jupyter.py,sha256=kwPWXqvYIBOxZzEipSzhES320Pstydsb3zPrsrryb7c,2160
187
+ experimaestro/utils/logging.py,sha256=nnyrT2CNiNgNp7kg84ldj2upzmrXC39GZ0C6T59DjyA,2262
188
+ experimaestro/utils/multiprocessing.py,sha256=am3DkHP_kmWbpynbck2c9QystCUtPBoSAC0ViBVzndU,1275
189
+ experimaestro/utils/resources.py,sha256=I0UPGMhQ_bttWt5JJLs1r-CmQsCHwtbmYjUN8JJLFKg,1317
190
+ experimaestro/utils/settings.py,sha256=jpFMqF0DLL4_P1xGal0zVR5cOrdD8O0Y2IOYvnRgN3k,793
191
+ experimaestro/webui/__init__.py,sha256=3Q3M-AAgENnTb__mG_LGJX5BSkDEZNywwOivJH_HIPM,264
192
+ experimaestro/webui/app.py,sha256=JHjKGODul5O_DpZ14CvEezQRXVVRoENYDuSMOp7TJVU,3869
193
+ experimaestro/webui/server.py,sha256=LwmSTwrSCNVZGNrjr5hij3_xu_pPBHyot90Zatgwb-M,6399
194
+ experimaestro/webui/state_bridge.py,sha256=4MDUpuXlQ1zelV-dFtsJ02ySpPKBYiOsitu96IScdf4,5917
195
+ experimaestro/webui/websocket.py,sha256=rle9KysQ_x2ZWJtihOWfzty6cD7Lx-KyXszv5r6MCWA,15067
196
+ experimaestro/webui/routes/__init__.py,sha256=R_BjM8nfaYegVQkqdRGIQBNDod8Li6FqnGp76v4lYhI,107
197
+ experimaestro/webui/routes/auth.py,sha256=u8xSQ38gxYk4VhYgye2nLHsIRT34xXHJsloy_DOMSVc,1440
198
+ experimaestro/webui/routes/proxy.py,sha256=47vBrtqoxGudYadkWg1U4cwVVXBCHzg1TuLHUxGj3KY,3453
199
+ experimaestro/tui/app.tcss,sha256=z4pf6jamFp37Pca4UH0Cy0wahoUt5xe3tTshBqWsh44,6846
200
+ experimaestro/webui/data/1815e00441357e01619e.ttf,sha256=gIRDrmyCBDla3YVD2oqQpguTdvsPh-2OjqN9EJWW2AU,210792
201
+ experimaestro/webui/data/2463b90d9a316e4e5294.woff2,sha256=qnWZhiOjkeYcaQF5Ss6DLj7N0oi1bWCPIb6gQRrMC44,158220
202
+ experimaestro/webui/data/2582b0e4bcf85eceead0.ttf,sha256=0vBZNUCw4zum3iVaVPJy1GbjEUSAaVa-qM_b9-3_yb0,426112
203
+ experimaestro/webui/data/89999bdf5d835c012025.woff2,sha256=40VtEoO511M3p3Pf0Ue_kI_QLAG0v0hXbYYDppsTy-U,25472
204
+ experimaestro/webui/data/914997e1bdfc990d0897.ttf,sha256=VM9ghve7IfnQcq1JShm0aB-lFt0KFM7lLaAdNlGpE6M,68064
205
+ experimaestro/webui/data/c210719e60948b211a12.woff2,sha256=1yNqGb8jy7ICcoDo9R3JnWxFl2ou1g3nM4KwNLGKK2g,118684
206
+ experimaestro/webui/data/favicon.ico,sha256=PRD32mxgMXg0AIFmjErFs66XQ8qaJiqw_NMS-7n0i90,3870
207
+ experimaestro/webui/data/index.css,sha256=Zne_juNBV2RHKSj_z9PqiS-dTFZBVc3aGxqd6Mgm6Bg,390604
208
+ experimaestro/webui/data/index.css.map,sha256=eNE-Z4tCXw4DbPPnllyh7BZT7ec0IibVL-f18j-l0Io,573179
209
+ experimaestro/webui/data/index.html,sha256=LcXSo2QU5jcmqgmFhVWWOG_CfGyrqdm3H8jwkdRgdGU,706
210
+ experimaestro/webui/data/index.js,sha256=timHhgub4NA-PRI8dr9TrcC_QSWxQ0J2A_Us8WEKYok,3477463
211
+ experimaestro/webui/data/index.js.map,sha256=mjiDikzG9Q_AY3ajG1w4MNL9N-wSgpA3EXrJzuiz2Z4,3684806
212
+ experimaestro/webui/data/login.html,sha256=4dvhSOn6DHp_tbmzqIKrqq2uAo0sAUbgLVD0lTnPp4s,511
213
+ experimaestro/webui/data/manifest.json,sha256=EpzHQZzrGh9c1Kf63nrqvI33H1cm0nLYfdh5lDm8ijI,318
214
+ experimaestro/sphinx/static/experimaestro.css,sha256=0rEgt1LoDdD-a_R5rVfWZ19zD1gR-1L7q3f4UibIB58,294
215
+ experimaestro-2.0.0b17.dist-info/METADATA,sha256=56iEwuk-rewnXZhJItSTUPECQcP0TWNg0qygf1Z6uyk,6979
216
+ experimaestro-2.0.0b17.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
217
+ experimaestro-2.0.0b17.dist-info/entry_points.txt,sha256=S6AkrX0dM7MWcV-6QN6bazCcL18QAb-uyvmhtlI5hFI,440
218
+ experimaestro-2.0.0b17.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
219
+ experimaestro-2.0.0b17.dist-info/RECORD,,
@@ -1,269 +0,0 @@
1
- """Simplified CLI commands for managing and viewing progress files"""
2
-
3
- import time
4
- from datetime import datetime
5
- from pathlib import Path
6
- from typing import Optional, Dict
7
-
8
- import click
9
- from termcolor import colored
10
-
11
- try:
12
- from tqdm import tqdm
13
-
14
- TQDM_AVAILABLE = True
15
- except ImportError:
16
- TQDM_AVAILABLE = False
17
-
18
- from experimaestro.progress import ProgressEntry, ProgressFileReader
19
- from experimaestro.settings import find_workspace
20
- from . import cli
21
-
22
-
23
- @click.option("--workspace", default="", help="Experimaestro workspace")
24
- @click.option("--workdir", type=Path, default=None)
25
- @cli.group()
26
- @click.pass_context
27
- def progress(
28
- ctx,
29
- workdir: Optional[Path],
30
- workspace: Optional[str],
31
- ):
32
- """Progress tracking commands"""
33
- ctx.obj.workspace = find_workspace(workdir=workdir, workspace=workspace)
34
-
35
-
36
- def format_timestamp(timestamp: float) -> str:
37
- """Format timestamp for display"""
38
- dt = datetime.fromtimestamp(timestamp)
39
- return dt.strftime("%Y-%m-%d %H:%M:%S")
40
-
41
-
42
- @click.argument("jobid", type=str)
43
- @progress.command()
44
- @click.pass_context
45
- def show(ctx, jobid: str):
46
- """Show current progress state (default command)
47
-
48
- JOBID format: task_name/task_hash
49
- """
50
- try:
51
- task_name, task_hash = jobid.split("/")
52
- except ValueError:
53
- raise click.ClickException("JOBID must be in format task_name/task_hash")
54
-
55
- workspace = ctx.obj.workspace
56
- task_path = workspace.path / "jobs" / task_name / task_hash
57
-
58
- if not task_path.exists():
59
- raise click.ClickException(f"Job directory not found: {task_path}")
60
-
61
- reader = ProgressFileReader(task_path)
62
- current_progress = reader.get_current_progress()
63
-
64
- if not current_progress:
65
- click.echo("No progress information available")
66
- return
67
-
68
- # Filter out EOJ markers
69
- current_progress = {k: v for k, v in current_progress.items() if k != -1}
70
-
71
- if not current_progress:
72
- click.echo("No progress information available")
73
- return
74
-
75
- click.echo(f"Progress for job {jobid}")
76
- click.echo("=" * 80)
77
-
78
- # Show simple text-based progress for each level
79
- for level in sorted(current_progress.keys()):
80
- entry = current_progress[level]
81
- indent = " " * level
82
- progress_pct = f"{entry.progress * 100:5.1f}%"
83
- desc = entry.desc or f"Level {level}"
84
- timestamp = format_timestamp(entry.timestamp)
85
-
86
- color = "green" if entry.progress >= 1.0 else "yellow"
87
- click.echo(colored(f"{indent}L{level}: {progress_pct} - {desc}", color))
88
- click.echo(colored(f"{indent} Last updated: {timestamp}", "cyan"))
89
-
90
-
91
- def create_progress_bar(
92
- level: int,
93
- desc: str,
94
- progress: float = 0.0,
95
- ) -> tqdm:
96
- """Create a properly aligned progress bar like dashboard style"""
97
- if level > 0:
98
- indent = " " * (level - 1) + "└─ "
99
- else:
100
- indent = ""
101
- label = f"{indent}L{level}"
102
-
103
- colors = ["blue", "yellow", "magenta", "cyan", "white"]
104
- bar_color = colors[level % len(colors)]
105
-
106
- unit = desc[:50] if desc else f"Level {level}"
107
- ncols = 100
108
- wbar = 50
109
-
110
- return tqdm(
111
- total=100,
112
- desc=label,
113
- position=level,
114
- leave=True,
115
- bar_format=f"{{desc}}: {{percentage:3.0f}}%|{{bar:{wbar - len(indent)}}}| {{unit}}", # noqa: F541
116
- ncols=ncols, # Adjust width based on level
117
- unit=unit,
118
- colour=bar_color,
119
- initial=progress * 100,
120
- )
121
-
122
-
123
- def _update_progress_display(
124
- reader: ProgressFileReader, progress_bars: Dict[int, tqdm]
125
- ) -> bool:
126
- """Update the tqdm progress bars in dashboard style"""
127
- current_state: Dict[int, ProgressEntry] = {
128
- k: v for k, v in reader.get_current_state().items() if k != -1
129
- }
130
-
131
- if not current_state:
132
- click.echo("No progress information available yet...")
133
- return False
134
-
135
- # Update existing bars and create new ones
136
- for _level, entry in current_state.items():
137
- progress_val = entry.progress * 100
138
- desc = entry.desc or f"Level {entry.level}"
139
-
140
- if entry.level not in progress_bars:
141
- progress_bars[entry.level] = create_progress_bar(
142
- entry.level, desc, progress_val
143
- )
144
-
145
- bar = progress_bars[entry.level]
146
- bar.unit = desc[:50]
147
- bar.n = progress_val
148
-
149
- bar.refresh()
150
-
151
- # Remove bars for levels that no longer exist
152
- levels_to_remove = set(progress_bars.keys()) - set(current_state.keys())
153
- for level in levels_to_remove:
154
- progress_bars[level].close()
155
- del progress_bars[level]
156
-
157
- return True
158
-
159
-
160
- @click.argument("jobid", type=str)
161
- @click.option("--refresh-rate", "-r", default=0.5, help="Refresh rate in seconds")
162
- @progress.command()
163
- @click.pass_context
164
- def live(ctx, jobid: str, refresh_rate: float):
165
- """Show live progress with tqdm-style bars
166
-
167
- JOBID format: task_name/task_hash
168
- """
169
- if not TQDM_AVAILABLE:
170
- click.echo("tqdm is not available. Install with: pip install tqdm")
171
- click.echo("Falling back to basic display...")
172
- ctx.invoke(show, jobid=jobid)
173
- return
174
-
175
- try:
176
- task_name, task_hash = jobid.split("/")
177
- except ValueError:
178
- raise click.ClickException("JOBID must be in format task_name/task_hash")
179
-
180
- workspace = ctx.obj.workspace
181
- task_path = workspace.path / "jobs" / task_name / task_hash
182
-
183
- if not task_path.exists():
184
- raise click.ClickException(f"Job directory not found: {task_path}")
185
-
186
- reader = ProgressFileReader(task_path)
187
- progress_bars: Dict[int, tqdm] = {}
188
-
189
- def cleanup_bars():
190
- """Clean up all progress bars"""
191
- for bar in progress_bars.values():
192
- bar.close()
193
- progress_bars.clear()
194
-
195
- click.echo(f"Live progress for job {jobid}")
196
- click.echo("Press Ctrl+C to stop")
197
- click.echo("=" * 80)
198
-
199
- try:
200
- if not _update_progress_display(reader, progress_bars):
201
- click.echo("No progress information available yet...")
202
-
203
- while True:
204
- time.sleep(refresh_rate)
205
-
206
- if not _update_progress_display(reader, progress_bars):
207
- # Check if job is complete
208
- if reader.is_done():
209
- click.echo("\nJob completed!")
210
- break
211
-
212
- # Check if all progress bars are at 100%
213
- if progress_bars and all(bar.n >= 100 for bar in progress_bars.values()):
214
- cleanup_bars()
215
- click.echo("\nAll progress completed!")
216
- break
217
-
218
- except KeyboardInterrupt:
219
- click.echo("\nStopped monitoring progress")
220
- finally:
221
- cleanup_bars()
222
-
223
-
224
- @progress.command(name="list")
225
- @click.pass_context
226
- def list_jobs(ctx):
227
- """List all jobs with progress information"""
228
- ws = ctx.obj.workspace
229
- jobs_path = ws.path / "jobs"
230
-
231
- if not jobs_path.exists():
232
- click.echo("No jobs directory found")
233
- return
234
-
235
- for task_dir in jobs_path.iterdir():
236
- if not task_dir.is_dir():
237
- continue
238
-
239
- for job_dir in task_dir.iterdir():
240
- if not job_dir.is_dir():
241
- continue
242
-
243
- progress_dir = job_dir / ".experimaestro"
244
- if not progress_dir.exists():
245
- continue
246
-
247
- # Check if there are progress files
248
- progress_files = list(progress_dir.glob("progress-*.jsonl"))
249
- if not progress_files:
250
- continue
251
-
252
- job_id = f"{task_dir.name}/{job_dir.name}"
253
- reader = ProgressFileReader(job_dir)
254
- current_state = reader.get_current_state()
255
-
256
- # if current_progress:
257
- if current_state:
258
- # Get overall progress (level 0)
259
- level_0 = current_state.get(0)
260
- if level_0:
261
- color = "green" if level_0.progress >= 1.0 else "yellow"
262
- desc = f"{level_0.desc}" if level_0.desc else ""
263
- progress_pct = f"{level_0.progress * 100:5.1f}%"
264
- click.echo(colored(f"{job_id:50} - {progress_pct} - {desc}", color))
265
-
266
- else:
267
- click.echo(f"{job_id:50} No level 0 progress")
268
- else:
269
- click.echo(f"{job_id:50} No progress data")
@@ -1,75 +0,0 @@
1
- from dataclasses import dataclass, field
2
- import json
3
- from pathlib import Path
4
- from typing import Iterable, Optional, Type
5
- from experimaestro import Task
6
-
7
- from experimaestro.core.context import SerializationContext
8
- from experimaestro.scheduler.jobs import Job, JobDependency
9
- from experimaestro.settings import find_workspace
10
- from experimaestro.core.serialization import from_state_dict, save_definition
11
-
12
-
13
- @dataclass
14
- class JobInformation:
15
- id: str
16
- path: Path
17
- task: Task
18
- tags: dict[str, str]
19
- depends_on: list["JobInformation"] = field(default_factory=list)
20
-
21
- def __post_init__(self):
22
- self.path = Path(self.path)
23
-
24
-
25
- class ExperimentState:
26
- def __init__(self, workdir: Path, name: str):
27
- path = workdir / "xp" / name / "state.json"
28
- with path.open("rt") as fh:
29
- content = json.load(fh)
30
-
31
- self.states: dict[str, JobInformation] = {
32
- state_dict["id"]: JobInformation(**state_dict)
33
- for state_dict in from_state_dict(content, as_instance=False)
34
- }
35
-
36
- for state in self.states.values():
37
- state.depends_on = [self.states[key] for key in state.depends_on]
38
-
39
- def get_jobs(self, task_class: Type[Task]) -> list[JobInformation]:
40
- if task_class is None:
41
- return list(self.data.values())
42
-
43
- tasks = []
44
- for job_state in self.states.values():
45
- if isinstance(job_state.task, task_class):
46
- tasks.append(job_state)
47
- return tasks
48
-
49
- @staticmethod
50
- def save(path: Path, jobs: Iterable[Job]):
51
- save_definition(
52
- [
53
- {
54
- "id": job.identifier,
55
- "path": str(job.path),
56
- "task": job.config,
57
- "tags": job.config.__xpm__.tags(),
58
- "depends_on": list(
59
- dep.origin.identifier
60
- for dep in job.dependencies
61
- if isinstance(dep, JobDependency)
62
- ),
63
- }
64
- for job in jobs
65
- ],
66
- SerializationContext(),
67
- path,
68
- )
69
-
70
-
71
- def get_experiment(
72
- name: str, *, workspace: Optional[str] = None, workdir: Optional[Path] = None
73
- ) -> ExperimentState:
74
- ws = find_workspace(workspace=workspace, workdir=workdir)
75
- return ExperimentState(ws.path, name)