experimaestro 2.0.0b4__py3-none-any.whl → 2.0.0b8__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.
- experimaestro/cli/__init__.py +177 -31
- experimaestro/experiments/cli.py +6 -2
- experimaestro/scheduler/base.py +21 -0
- experimaestro/scheduler/experiment.py +64 -34
- experimaestro/scheduler/interfaces.py +27 -0
- experimaestro/scheduler/remote/__init__.py +31 -0
- experimaestro/scheduler/remote/client.py +874 -0
- experimaestro/scheduler/remote/protocol.py +467 -0
- experimaestro/scheduler/remote/server.py +423 -0
- experimaestro/scheduler/remote/sync.py +144 -0
- experimaestro/scheduler/services.py +158 -32
- experimaestro/scheduler/state_db.py +58 -9
- experimaestro/scheduler/state_provider.py +512 -91
- experimaestro/scheduler/state_sync.py +65 -8
- experimaestro/tests/test_cli_jobs.py +3 -3
- experimaestro/tests/test_remote_state.py +671 -0
- experimaestro/tests/test_state_db.py +8 -8
- experimaestro/tui/app.py +100 -8
- experimaestro/version.py +2 -2
- {experimaestro-2.0.0b4.dist-info → experimaestro-2.0.0b8.dist-info}/METADATA +4 -4
- {experimaestro-2.0.0b4.dist-info → experimaestro-2.0.0b8.dist-info}/RECORD +24 -18
- {experimaestro-2.0.0b4.dist-info → experimaestro-2.0.0b8.dist-info}/WHEEL +0 -0
- {experimaestro-2.0.0b4.dist-info → experimaestro-2.0.0b8.dist-info}/entry_points.txt +0 -0
- {experimaestro-2.0.0b4.dist-info → experimaestro-2.0.0b8.dist-info}/licenses/LICENSE +0 -0
|
@@ -23,7 +23,7 @@ def test_database_initialization(tmp_path: Path):
|
|
|
23
23
|
db_path = tmp_path / "workspace.db"
|
|
24
24
|
|
|
25
25
|
# Initialize database
|
|
26
|
-
db = initialize_workspace_database(db_path, read_only=False)
|
|
26
|
+
db, _ = initialize_workspace_database(db_path, read_only=False)
|
|
27
27
|
|
|
28
28
|
# Verify all tables were created
|
|
29
29
|
assert ExperimentModel.table_exists()
|
|
@@ -47,7 +47,7 @@ def test_database_initialization(tmp_path: Path):
|
|
|
47
47
|
def test_experiment_and_run_models(tmp_path: Path):
|
|
48
48
|
"""Test creating experiments and runs"""
|
|
49
49
|
db_path = tmp_path / "workspace.db"
|
|
50
|
-
db = initialize_workspace_database(db_path, read_only=False)
|
|
50
|
+
db, _ = initialize_workspace_database(db_path, read_only=False)
|
|
51
51
|
|
|
52
52
|
with db.bind_ctx(ALL_MODELS):
|
|
53
53
|
# Create an experiment
|
|
@@ -79,7 +79,7 @@ def test_experiment_and_run_models(tmp_path: Path):
|
|
|
79
79
|
def test_job_model_with_composite_key(tmp_path: Path):
|
|
80
80
|
"""Test job model with composite primary key (job_id, experiment_id, run_id)"""
|
|
81
81
|
db_path = tmp_path / "workspace.db"
|
|
82
|
-
db = initialize_workspace_database(db_path, read_only=False)
|
|
82
|
+
db, _ = initialize_workspace_database(db_path, read_only=False)
|
|
83
83
|
|
|
84
84
|
with db.bind_ctx(ALL_MODELS):
|
|
85
85
|
# Create experiment and run first
|
|
@@ -133,7 +133,7 @@ def test_job_model_with_composite_key(tmp_path: Path):
|
|
|
133
133
|
def test_job_tags_model(tmp_path: Path):
|
|
134
134
|
"""Test run-scoped job tags (fixes GH #128)"""
|
|
135
135
|
db_path = tmp_path / "workspace.db"
|
|
136
|
-
db = initialize_workspace_database(db_path, read_only=False)
|
|
136
|
+
db, _ = initialize_workspace_database(db_path, read_only=False)
|
|
137
137
|
|
|
138
138
|
with db.bind_ctx(ALL_MODELS):
|
|
139
139
|
# Create experiment and runs
|
|
@@ -203,7 +203,7 @@ def test_job_tags_model(tmp_path: Path):
|
|
|
203
203
|
def test_multiple_experiments_same_workspace(tmp_path: Path):
|
|
204
204
|
"""Test that multiple experiments can coexist in same workspace database"""
|
|
205
205
|
db_path = tmp_path / "workspace.db"
|
|
206
|
-
db = initialize_workspace_database(db_path, read_only=False)
|
|
206
|
+
db, _ = initialize_workspace_database(db_path, read_only=False)
|
|
207
207
|
|
|
208
208
|
with db.bind_ctx(ALL_MODELS):
|
|
209
209
|
# Create two experiments
|
|
@@ -249,13 +249,13 @@ def test_read_only_mode(tmp_path: Path):
|
|
|
249
249
|
db_path = tmp_path / "workspace.db"
|
|
250
250
|
|
|
251
251
|
# Create database with write mode
|
|
252
|
-
db_write = initialize_workspace_database(db_path, read_only=False)
|
|
252
|
+
db_write, _ = initialize_workspace_database(db_path, read_only=False)
|
|
253
253
|
with db_write.bind_ctx(ALL_MODELS):
|
|
254
254
|
ExperimentModel.create(experiment_id="exp1")
|
|
255
255
|
close_workspace_database(db_write)
|
|
256
256
|
|
|
257
257
|
# Open in read-only mode
|
|
258
|
-
db_read = initialize_workspace_database(db_path, read_only=True)
|
|
258
|
+
db_read, _ = initialize_workspace_database(db_path, read_only=True)
|
|
259
259
|
|
|
260
260
|
with db_read.bind_ctx(ALL_MODELS):
|
|
261
261
|
# Can read
|
|
@@ -272,7 +272,7 @@ def test_read_only_mode(tmp_path: Path):
|
|
|
272
272
|
def test_upsert_on_conflict(tmp_path: Path):
|
|
273
273
|
"""Test that on_conflict works for updating existing records"""
|
|
274
274
|
db_path = tmp_path / "workspace.db"
|
|
275
|
-
db = initialize_workspace_database(db_path, read_only=False)
|
|
275
|
+
db, _ = initialize_workspace_database(db_path, read_only=False)
|
|
276
276
|
|
|
277
277
|
with db.bind_ctx(ALL_MODELS):
|
|
278
278
|
# Create experiment and run
|
experimaestro/tui/app.py
CHANGED
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import Optional
|
|
6
6
|
from textual.app import App, ComposeResult
|
|
7
|
+
from textual import work
|
|
7
8
|
from textual.containers import Container, Horizontal, Vertical
|
|
8
9
|
from textual.widgets import (
|
|
9
10
|
Header,
|
|
@@ -265,6 +266,7 @@ class ExperimentsList(Widget):
|
|
|
265
266
|
"""Initialize the experiments table"""
|
|
266
267
|
table = self.query_one("#experiments-table", DataTable)
|
|
267
268
|
table.add_column("ID", key="id")
|
|
269
|
+
table.add_column("Host", key="host")
|
|
268
270
|
table.add_column("Jobs", key="jobs")
|
|
269
271
|
table.add_column("Status", key="status")
|
|
270
272
|
table.add_column("Started", key="started")
|
|
@@ -340,15 +342,21 @@ class ExperimentsList(Widget):
|
|
|
340
342
|
# Format duration
|
|
341
343
|
duration = format_duration(elapsed)
|
|
342
344
|
|
|
345
|
+
# Get hostname (may be None for older experiments)
|
|
346
|
+
hostname = getattr(exp, "hostname", None) or "-"
|
|
347
|
+
|
|
343
348
|
# Update existing row or add new one
|
|
344
349
|
if exp_id in existing_keys:
|
|
345
350
|
table.update_cell(exp_id, "id", exp_id, update_width=True)
|
|
351
|
+
table.update_cell(exp_id, "host", hostname, update_width=True)
|
|
346
352
|
table.update_cell(exp_id, "jobs", jobs_text, update_width=True)
|
|
347
353
|
table.update_cell(exp_id, "status", status, update_width=True)
|
|
348
354
|
table.update_cell(exp_id, "started", started, update_width=True)
|
|
349
355
|
table.update_cell(exp_id, "duration", duration, update_width=True)
|
|
350
356
|
else:
|
|
351
|
-
table.add_row(
|
|
357
|
+
table.add_row(
|
|
358
|
+
exp_id, hostname, jobs_text, status, started, duration, key=exp_id
|
|
359
|
+
)
|
|
352
360
|
|
|
353
361
|
# Remove rows for experiments that no longer exist
|
|
354
362
|
for old_exp_id in existing_keys - current_exp_ids:
|
|
@@ -465,6 +473,23 @@ class ViewJobLogsRequest(Message):
|
|
|
465
473
|
self.experiment_id = experiment_id
|
|
466
474
|
|
|
467
475
|
|
|
476
|
+
class LogsSyncComplete(Message):
|
|
477
|
+
"""Message sent when remote log sync is complete"""
|
|
478
|
+
|
|
479
|
+
def __init__(self, log_files: list, job_id: str) -> None:
|
|
480
|
+
super().__init__()
|
|
481
|
+
self.log_files = log_files
|
|
482
|
+
self.job_id = job_id
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
class LogsSyncFailed(Message):
|
|
486
|
+
"""Message sent when remote log sync fails"""
|
|
487
|
+
|
|
488
|
+
def __init__(self, error: str) -> None:
|
|
489
|
+
super().__init__()
|
|
490
|
+
self.error = error
|
|
491
|
+
|
|
492
|
+
|
|
468
493
|
class DeleteJobRequest(Message):
|
|
469
494
|
"""Message sent when user requests to delete a job"""
|
|
470
495
|
|
|
@@ -560,6 +585,10 @@ class ServicesList(Vertical):
|
|
|
560
585
|
|
|
561
586
|
# Get services from state provider (handles live vs DB automatically)
|
|
562
587
|
services = self.state_provider.get_services(self.current_experiment)
|
|
588
|
+
self.log.info(
|
|
589
|
+
f"refresh_services got {len(services)} services: "
|
|
590
|
+
f"{[(s.id, id(s), getattr(s, 'url', None)) for s in services]}"
|
|
591
|
+
)
|
|
563
592
|
|
|
564
593
|
for service in services:
|
|
565
594
|
service_id = service.id
|
|
@@ -596,9 +625,12 @@ class ServicesList(Vertical):
|
|
|
596
625
|
if not service:
|
|
597
626
|
return
|
|
598
627
|
|
|
628
|
+
self.log.info(f"Starting service {service.id} (id={id(service)})")
|
|
629
|
+
|
|
599
630
|
try:
|
|
600
631
|
if hasattr(service, "get_url"):
|
|
601
632
|
url = service.get_url()
|
|
633
|
+
self.log.info(f"Service started, url={url}, service.url={service.url}")
|
|
602
634
|
self.notify(f"Service started: {url}", severity="information")
|
|
603
635
|
else:
|
|
604
636
|
self.notify("Service does not support starting", severity="warning")
|
|
@@ -1888,7 +1920,7 @@ class ExperimaestroUI(App):
|
|
|
1888
1920
|
with TabPane("Monitor", id="monitor-tab"):
|
|
1889
1921
|
yield from self._compose_monitor_view()
|
|
1890
1922
|
with TabPane("Logs", id="logs-tab"):
|
|
1891
|
-
yield CaptureLog(id="logs", auto_scroll=True)
|
|
1923
|
+
yield CaptureLog(id="logs", auto_scroll=True, wrap=True)
|
|
1892
1924
|
else:
|
|
1893
1925
|
# Simple layout without logs
|
|
1894
1926
|
with Vertical(id="main-container"):
|
|
@@ -1918,19 +1950,27 @@ class ExperimaestroUI(App):
|
|
|
1918
1950
|
experiments_list = self.query_one(ExperimentsList)
|
|
1919
1951
|
experiments_list.refresh_experiments()
|
|
1920
1952
|
|
|
1921
|
-
# Register as listener for
|
|
1953
|
+
# Register as listener for state change notifications
|
|
1954
|
+
# The state provider handles its own notification strategy internally
|
|
1922
1955
|
if self.state_provider:
|
|
1923
1956
|
self.state_provider.add_listener(self._on_state_event)
|
|
1924
1957
|
self._listener_registered = True
|
|
1925
|
-
self.log("Registered state listener for
|
|
1958
|
+
self.log("Registered state listener for notifications")
|
|
1926
1959
|
|
|
1927
1960
|
def _on_state_event(self, event: StateEvent) -> None:
|
|
1928
1961
|
"""Handle state change events from the state provider
|
|
1929
1962
|
|
|
1930
|
-
This
|
|
1931
|
-
|
|
1963
|
+
This may be called from the state provider's thread or the main thread,
|
|
1964
|
+
so we check before using call_from_thread.
|
|
1932
1965
|
"""
|
|
1933
|
-
|
|
1966
|
+
import threading
|
|
1967
|
+
|
|
1968
|
+
if threading.current_thread() is threading.main_thread():
|
|
1969
|
+
# Already in main thread, call directly
|
|
1970
|
+
self._handle_state_event(event)
|
|
1971
|
+
else:
|
|
1972
|
+
# From background thread, use call_from_thread
|
|
1973
|
+
self.call_from_thread(self._handle_state_event, event)
|
|
1934
1974
|
|
|
1935
1975
|
def _handle_state_event(self, event: StateEvent) -> None:
|
|
1936
1976
|
"""Process state event on the main thread"""
|
|
@@ -2081,10 +2121,62 @@ class ExperimaestroUI(App):
|
|
|
2081
2121
|
"""Show orphan jobs screen"""
|
|
2082
2122
|
self.push_screen(OrphanJobsScreen(self.state_provider))
|
|
2083
2123
|
|
|
2124
|
+
@work(thread=True, exclusive=True)
|
|
2125
|
+
def _sync_and_view_logs(self, job_path: Path, task_id: str) -> None:
|
|
2126
|
+
"""Sync logs from remote and then view them (runs in worker thread)"""
|
|
2127
|
+
try:
|
|
2128
|
+
# Sync the job directory
|
|
2129
|
+
local_path = self.state_provider.sync_path(str(job_path))
|
|
2130
|
+
if not local_path:
|
|
2131
|
+
self.post_message(LogsSyncFailed("Failed to sync logs from remote"))
|
|
2132
|
+
return
|
|
2133
|
+
|
|
2134
|
+
job_path = local_path
|
|
2135
|
+
|
|
2136
|
+
# Log files are named after the last part of the task ID
|
|
2137
|
+
task_name = task_id.split(".")[-1]
|
|
2138
|
+
stdout_path = job_path / f"{task_name}.out"
|
|
2139
|
+
stderr_path = job_path / f"{task_name}.err"
|
|
2140
|
+
|
|
2141
|
+
# Collect existing log files
|
|
2142
|
+
log_files = []
|
|
2143
|
+
if stdout_path.exists():
|
|
2144
|
+
log_files.append(str(stdout_path))
|
|
2145
|
+
if stderr_path.exists():
|
|
2146
|
+
log_files.append(str(stderr_path))
|
|
2147
|
+
|
|
2148
|
+
if not log_files:
|
|
2149
|
+
self.post_message(
|
|
2150
|
+
LogsSyncFailed(f"No log files found: {task_name}.out/.err")
|
|
2151
|
+
)
|
|
2152
|
+
return
|
|
2153
|
+
|
|
2154
|
+
# Signal completion via message
|
|
2155
|
+
job_id = job_path.name
|
|
2156
|
+
self.post_message(LogsSyncComplete(log_files, job_id))
|
|
2157
|
+
|
|
2158
|
+
except Exception as e:
|
|
2159
|
+
self.post_message(LogsSyncFailed(str(e)))
|
|
2160
|
+
|
|
2161
|
+
def on_logs_sync_complete(self, message: LogsSyncComplete) -> None:
|
|
2162
|
+
"""Handle successful log sync - show log viewer"""
|
|
2163
|
+
self.push_screen(LogViewerScreen(message.log_files, message.job_id))
|
|
2164
|
+
|
|
2165
|
+
def on_logs_sync_failed(self, message: LogsSyncFailed) -> None:
|
|
2166
|
+
"""Handle failed log sync"""
|
|
2167
|
+
self.notify(message.error, severity="warning")
|
|
2168
|
+
|
|
2084
2169
|
def on_view_job_logs(self, message: ViewJobLogs) -> None:
|
|
2085
2170
|
"""Handle request to view job logs - push LogViewerScreen"""
|
|
2086
2171
|
job_path = Path(message.job_path)
|
|
2087
|
-
|
|
2172
|
+
|
|
2173
|
+
# For remote monitoring, sync the job directory first (in worker thread)
|
|
2174
|
+
if self.state_provider.is_remote:
|
|
2175
|
+
self.notify("Syncing logs from remote...", timeout=5)
|
|
2176
|
+
self._sync_and_view_logs(job_path, message.task_id)
|
|
2177
|
+
return
|
|
2178
|
+
|
|
2179
|
+
# Local monitoring - no sync needed
|
|
2088
2180
|
task_name = message.task_id.split(".")[-1]
|
|
2089
2181
|
stdout_path = job_path / f"{task_name}.out"
|
|
2090
2182
|
stderr_path = job_path / f"{task_name}.err"
|
experimaestro/version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '2.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (2, 0, 0, '
|
|
31
|
+
__version__ = version = '2.0.0b8'
|
|
32
|
+
__version_tuple__ = version_tuple = (2, 0, 0, 'b8')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: experimaestro
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.0b8
|
|
4
4
|
Summary: Experimaestro is a computer science experiment manager
|
|
5
5
|
Project-URL: Homepage, https://github.com/experimaestro/experimaestro-python
|
|
6
6
|
Project-URL: Documentation, https://experimaestro-python.readthedocs.io/
|
|
@@ -82,11 +82,11 @@ The full documentation can be read by going to the following URL: [https://exper
|
|
|
82
82
|
|
|
83
83
|
## Textual interface (new in v2)
|
|
84
84
|
|
|
85
|
-

|
|
85
|
+

|
|
86
86
|
|
|
87
|
-

|
|
87
|
+

|
|
88
88
|
|
|
89
|
-

|
|
89
|
+

|
|
90
90
|
|
|
91
91
|
# Install
|
|
92
92
|
|
|
@@ -20,9 +20,9 @@ experimaestro/settings.py,sha256=ymA-W2-cNOE1W8oc7lPPxOwEz2wXSX9Q5iftw0agKcY,448
|
|
|
20
20
|
experimaestro/taskglobals.py,sha256=A_P49RHu8FLOfoybfwcLzDcDZiUug4mLFKiAzsCof_k,1315
|
|
21
21
|
experimaestro/tokens.py,sha256=IitlWi8CJprTXFTw0GJ3cf-vch-x5IyJztiik5FYC1M,18578
|
|
22
22
|
experimaestro/typingutils.py,sha256=v7wS9xewF3cYOKvaBFxlTB-qplJ8olI1OaO3tAKiwIo,3678
|
|
23
|
-
experimaestro/version.py,sha256=
|
|
23
|
+
experimaestro/version.py,sha256=xb387tRebssohFiC2cBfY1gEG-Ur9UZkojiYpRcNRbA,712
|
|
24
24
|
experimaestro/xpmutils.py,sha256=S21eMbDYsHfvmZ1HmKpq5Pz5O-1HnCLYxKbyTBbASyQ,638
|
|
25
|
-
experimaestro/cli/__init__.py,sha256
|
|
25
|
+
experimaestro/cli/__init__.py,sha256=-ps3-5_fnqH61oRbCYZ1h-bWoLazHjLXIJP2mMYSWFY,17989
|
|
26
26
|
experimaestro/cli/filter.py,sha256=0Lq9B_ZNSjVU1N6sCv-YETjAPtRVwunlfGxtG6aeBpY,5024
|
|
27
27
|
experimaestro/cli/jobs.py,sha256=lnxlISYjVzdOk3lkEhIuV0MRyCO1JprTgg56R5KJ1No,10049
|
|
28
28
|
experimaestro/cli/progress.py,sha256=I6qhVe-vvqA1ym6XJE75q7Hb0jGeFwgodIqfhlTrPKY,8200
|
|
@@ -45,7 +45,7 @@ experimaestro/core/objects/config.py,sha256=YXJ5_B8mmW_tVvjGGhCVQPic3iLbU1xFv6xK
|
|
|
45
45
|
experimaestro/core/objects/config_utils.py,sha256=ZLECGkeIWdzunm8vwWsQhvcSgV1e064BgXbLiZnxSEM,1288
|
|
46
46
|
experimaestro/core/objects/config_walk.py,sha256=lMK7dXMjqfDaqc4NPxenYABozKYusmJ8xhDbDFP8z5U,4980
|
|
47
47
|
experimaestro/experiments/__init__.py,sha256=GcpDUIbCvhnv6rxFdAp4wTffCVNTv-InY6fbQAlTy-o,159
|
|
48
|
-
experimaestro/experiments/cli.py,sha256=
|
|
48
|
+
experimaestro/experiments/cli.py,sha256=WbeK4PNEy9cQoX_mJiLkMuu57lCLURg2I7dC3nECTmY,13345
|
|
49
49
|
experimaestro/experiments/configuration.py,sha256=vVm40BJW5sZNgSDZ0oBzX15jTO9rmOewVYrm0k9iXXY,1466
|
|
50
50
|
experimaestro/launcherfinder/__init__.py,sha256=qRUDyv3B9UsAM8Q31mRrZrTZox0AptwdmOY4f2K-TUo,279
|
|
51
51
|
experimaestro/launcherfinder/base.py,sha256=q47SsF_cXdo5O6ZhFKn5385WVFcx8Wd-BcEpd6tRpbs,515
|
|
@@ -63,19 +63,24 @@ experimaestro/mkdocs/base.py,sha256=qHDZZFdoNRsW6RcjRB1WCSp2sOtRiBk9zFO1acK05BQ,
|
|
|
63
63
|
experimaestro/mkdocs/metaloader.py,sha256=ItchfE3emrzKUrT-8f8WsDHNHisYzs9XDCzhWcu6VaQ,1471
|
|
64
64
|
experimaestro/mkdocs/style.css,sha256=42kJ6Ozq_n4Iw5UfJ4-nO1u-HN3ELvV7Vhvj1Xkn7rQ,66
|
|
65
65
|
experimaestro/scheduler/__init__.py,sha256=HssbogPCuGpKGMPZQP07XCT2-uMFRPANuPM-duMIrq4,422
|
|
66
|
-
experimaestro/scheduler/base.py,sha256=
|
|
66
|
+
experimaestro/scheduler/base.py,sha256=IMVwLUEm0hPJzfX0sb6efI1Ic1-o1Ya56mlxG8FXyqI,28269
|
|
67
67
|
experimaestro/scheduler/dependencies.py,sha256=gQfmIEa8l9mMVMmBuoPfUM30eQzEozFkCQGXkbfXhaU,2406
|
|
68
68
|
experimaestro/scheduler/dynamic_outputs.py,sha256=pKSm73D_XIgUHawf432JJXfQKISO34qEMf5w-nWTl-g,11187
|
|
69
|
-
experimaestro/scheduler/experiment.py,sha256=
|
|
70
|
-
experimaestro/scheduler/interfaces.py,sha256=
|
|
69
|
+
experimaestro/scheduler/experiment.py,sha256=N7-903ADgqlJumgldOdS4BAI2nIcKPFUCDXqW_mHLsQ,22334
|
|
70
|
+
experimaestro/scheduler/interfaces.py,sha256=JG1Z6iGWosiM-TrEkxhsPz-dJ4lfPQL6dnaGjbCn-aA,16008
|
|
71
71
|
experimaestro/scheduler/jobs.py,sha256=h04Vj595zxvpgvJOr-3wK_rFBvVmlYqO68gq1euI4vc,15634
|
|
72
|
-
experimaestro/scheduler/services.py,sha256=
|
|
72
|
+
experimaestro/scheduler/services.py,sha256=CVZ7YDB71qQe86oCEQWPzgRTchEtYUZWx3KxqGykhnc,13053
|
|
73
73
|
experimaestro/scheduler/signal_handler.py,sha256=B4ZeSVB8O41VDdFmV4n2cyBds7wKFG3kH2Fp7cpyxa4,872
|
|
74
74
|
experimaestro/scheduler/state.py,sha256=1ICn1K5gNMCEUb85vwwXLIUF6Lxqa5mbTgMzEz2pnXw,2367
|
|
75
|
-
experimaestro/scheduler/state_db.py,sha256=
|
|
76
|
-
experimaestro/scheduler/state_provider.py,sha256=
|
|
77
|
-
experimaestro/scheduler/state_sync.py,sha256=
|
|
75
|
+
experimaestro/scheduler/state_db.py,sha256=HmM0PCKZoGix_VR571M4ZATag7e52KeWaFhOzBtRgRE,15855
|
|
76
|
+
experimaestro/scheduler/state_provider.py,sha256=X3sqdC8UnUlnveaFjMwjnEhCkHuiLpM9xp1WRpskAiE,94907
|
|
77
|
+
experimaestro/scheduler/state_sync.py,sha256=yrwHdGqUck_QbVCHymP5mnJHN1Z_0dILleV_vDw16KQ,34678
|
|
78
78
|
experimaestro/scheduler/workspace.py,sha256=hIASgxGQtrlN4oPFDqDYXTVnxDbngirGdDyAJxJq4vg,3815
|
|
79
|
+
experimaestro/scheduler/remote/__init__.py,sha256=QBXrl4V09nPbwxKRtV7-uLdZCXtktWBeSAV7kB2ZWOM,1134
|
|
80
|
+
experimaestro/scheduler/remote/client.py,sha256=FX9ZieKfz2s7SBt1KWGOLUqwuey2EAnzasKdAB8Ifsg,31501
|
|
81
|
+
experimaestro/scheduler/remote/protocol.py,sha256=Rc2_nsln-xw9kMnDOMbMXSIIgIjMciYhLCg4caHZgFs,13831
|
|
82
|
+
experimaestro/scheduler/remote/server.py,sha256=T61yaaU-tn3Pmh0wevrozyl20Oj_D5S5S-SpKGy_nQ0,15739
|
|
83
|
+
experimaestro/scheduler/remote/sync.py,sha256=BgPK96EJY3AxjBmrwo53CN5fUmGED-a12ZTODkJ_mQk,4917
|
|
79
84
|
experimaestro/server/__init__.py,sha256=BXLPcDRy7Bxx0xk24SF8OthvcE_rk7Afx7yVvgYvM2o,15920
|
|
80
85
|
experimaestro/sphinx/__init__.py,sha256=DhFRj8MxA9XZH-TCnbl_5bYhGiF4ihiuFwQj74oPEp4,9466
|
|
81
86
|
experimaestro/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -86,7 +91,7 @@ experimaestro/tests/restart.py,sha256=aAizVLvw2DaNfIzuRB13iYXOoX1Q5NkgsngumERlo2
|
|
|
86
91
|
experimaestro/tests/restart_main.py,sha256=iAFzw0H1q9Aq7t6TrSAj236QBnYU52qx0VF-2dz6tx4,295
|
|
87
92
|
experimaestro/tests/task_tokens.py,sha256=vgqUa-S_YC2Id9pGOSv40qFTwq1WGZkFhr556Z5o678,477
|
|
88
93
|
experimaestro/tests/test_checkers.py,sha256=e6Rv2TlePRY__VXs0vUb6a5Aw_KIq_cs4N86VhnYHtw,407
|
|
89
|
-
experimaestro/tests/test_cli_jobs.py,sha256=
|
|
94
|
+
experimaestro/tests/test_cli_jobs.py,sha256=hQimCKsgr44smvX7rxoOUS2knGBpcfvIhuwZWSSawic,19358
|
|
90
95
|
experimaestro/tests/test_dependencies.py,sha256=LvpmMcfnRzQPzUIuFNCIQnJot8YBSxCA827xh9gYlq0,1890
|
|
91
96
|
experimaestro/tests/test_deprecated.py,sha256=SWuc37o9E-9VsWnwNQBHWiWHdn4syeVTouMSPWyqhww,20061
|
|
92
97
|
experimaestro/tests/test_environment.py,sha256=HEIV4OIBaPdGnqi8bdqkwucc2Ezr-VMnNUiA2qYVIHE,6923
|
|
@@ -106,11 +111,12 @@ experimaestro/tests/test_outputs.py,sha256=wO53O6yWVT2sBlRXHTgsv_9i_Y8X5-JnOVfrE
|
|
|
106
111
|
experimaestro/tests/test_param.py,sha256=cmCvzpCGSNpcFAI2lfIQe2lTYBfxO8gr5I0SVXiNafQ,7346
|
|
107
112
|
experimaestro/tests/test_partial_paths.py,sha256=XiYJsqP8IFW-gypvWBrXziMBBk3naXJp2-0OnEgKoUQ,9066
|
|
108
113
|
experimaestro/tests/test_progress.py,sha256=Baz2z749CWmMauldMxfMr8A77w3lRNr8eDpsPn317sc,5968
|
|
114
|
+
experimaestro/tests/test_remote_state.py,sha256=cILubH-dF1iFMmBYLQtVsbpmfJQgDEaK7xHKOe9edGg,23217
|
|
109
115
|
experimaestro/tests/test_resumable_task.py,sha256=H5plRfuQ7bhWzP9TQgGAxm6-GlbtPOTLm9WMZhvRUZ0,17080
|
|
110
116
|
experimaestro/tests/test_serializers.py,sha256=DWe3gbaQP16tQawDz8uSiDpQ_nyTuYjFMvoGEwIWfhU,5302
|
|
111
117
|
experimaestro/tests/test_snippets.py,sha256=rojnyDjtmAMnSuDUj6Bv9XEgdP8oQf2nVc132JF8vsM,3081
|
|
112
118
|
experimaestro/tests/test_ssh.py,sha256=KS1NWltiXrJBSStY9d4mwrexeqgNGWmhxuAU_WLQDAU,1449
|
|
113
|
-
experimaestro/tests/test_state_db.py,sha256=
|
|
119
|
+
experimaestro/tests/test_state_db.py,sha256=4FfMXYCJyZCltnwKf6ITX08_xXozFJxkcCmrLVlTGzQ,14197
|
|
114
120
|
experimaestro/tests/test_subparameters.py,sha256=mDDwPK-KlaZBf0uStxLOhxKElxhp_7mb1DYNJ02yfvg,5792
|
|
115
121
|
experimaestro/tests/test_tags.py,sha256=VTjowJljm8sCGiEuOIDeoNO4NPJNY1pu4b7G8dWqBes,6596
|
|
116
122
|
experimaestro/tests/test_tasks.py,sha256=E4LWKR_6N4bD0iONeGHQ24c4iNcXsp8l1f4jnwq0MH4,9104
|
|
@@ -147,7 +153,7 @@ experimaestro/tools/diff.py,sha256=mrI9QlZAVgMOGfyz3ryQT9wu5JBn9ndAiVk_EpCh0m4,3
|
|
|
147
153
|
experimaestro/tools/documentation.py,sha256=O2UzjzodPqGot3YSe6NYlK7S42XpplakUdqxFpvjqHQ,9184
|
|
148
154
|
experimaestro/tools/jobs.py,sha256=63bXhJ7RGdczLU_nxu2skGn-9dwgr4r5pD23qH4WeBA,3516
|
|
149
155
|
experimaestro/tui/__init__.py,sha256=BTf7I5HtG7AA_vGTSG891Jjz4R3wf-cEnpaEwB6xBA4,197
|
|
150
|
-
experimaestro/tui/app.py,sha256=
|
|
156
|
+
experimaestro/tui/app.py,sha256=YXysC-VZaa-PRUUKyBaVdM_4IeC1SPSM7SFgGoLl5eI,89788
|
|
151
157
|
experimaestro/tui/log_viewer.py,sha256=TFybc1LsCjbaC5sUQ8WMAwP6Uzy92GknpEmYx1u0csI,6938
|
|
152
158
|
experimaestro/utils/__init__.py,sha256=iuBQw4lZT9Z4BIfQg0Yl9JHdbPgkSvkTH24xREeGHiI,3113
|
|
153
159
|
experimaestro/utils/asyncio.py,sha256=9r_vFQs6T6tqmymC_DbHVFhY9YVRO6X48uEuyL_ugP8,726
|
|
@@ -174,8 +180,8 @@ experimaestro/server/data/login.html,sha256=4dvhSOn6DHp_tbmzqIKrqq2uAo0sAUbgLVD0
|
|
|
174
180
|
experimaestro/server/data/manifest.json,sha256=EpzHQZzrGh9c1Kf63nrqvI33H1cm0nLYfdh5lDm8ijI,318
|
|
175
181
|
experimaestro/tui/app.tcss,sha256=KsNvixGexmGld19ztBm-Nt5IH0gbclykfYgblP38Wy4,4556
|
|
176
182
|
experimaestro/sphinx/static/experimaestro.css,sha256=0rEgt1LoDdD-a_R5rVfWZ19zD1gR-1L7q3f4UibIB58,294
|
|
177
|
-
experimaestro-2.0.
|
|
178
|
-
experimaestro-2.0.
|
|
179
|
-
experimaestro-2.0.
|
|
180
|
-
experimaestro-2.0.
|
|
181
|
-
experimaestro-2.0.
|
|
183
|
+
experimaestro-2.0.0b8.dist-info/METADATA,sha256=6xzN8WQQpLaaaTIA4Ujw7Jv4Sa7GP7a-VBYqAxj1eL8,6980
|
|
184
|
+
experimaestro-2.0.0b8.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
185
|
+
experimaestro-2.0.0b8.dist-info/entry_points.txt,sha256=S6AkrX0dM7MWcV-6QN6bazCcL18QAb-uyvmhtlI5hFI,440
|
|
186
|
+
experimaestro-2.0.0b8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
187
|
+
experimaestro-2.0.0b8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|