QuLab 2.7.6__tar.gz → 2.7.8__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.
- {qulab-2.7.6 → qulab-2.7.8}/PKG-INFO +1 -1
- {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/PKG-INFO +1 -1
- {qulab-2.7.6 → qulab-2.7.8}/qulab/__init__.py +2 -2
- {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/cli.py +2 -2
- {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/load.py +11 -11
- {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/schedule.py +183 -168
- {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/storage.py +61 -52
- {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/transform.py +5 -5
- {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/utils.py +33 -33
- qulab-2.7.8/qulab/typing.py +2 -0
- qulab-2.7.8/qulab/version.py +1 -0
- qulab-2.7.6/qulab/typing.py +0 -2
- qulab-2.7.6/qulab/version.py +0 -1
- {qulab-2.7.6 → qulab-2.7.8}/LICENSE +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/MANIFEST.in +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/SOURCES.txt +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/dependency_links.txt +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/entry_points.txt +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/requires.txt +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/top_level.txt +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/README.md +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/pyproject.toml +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/__main__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/cli/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/cli/commands.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/cli/config.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/dicttree.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/__main__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/config.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/dataset.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/event_queue.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/mainwindow.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/monitor.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/ploter.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/qt_compat.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/toolbar.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/curd.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/expression.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/models.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/optimize.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/query.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/record.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/scan.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/server.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/space.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/utils.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/__main__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/backend/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/backend/redis.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/base_dataset.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/chunk.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/dataset.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/file.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/base.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/config.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/file.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/ipy.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/models.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/record.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/report.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/tag.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/storage.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/chat.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/device/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/device/basedevice.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/device/loader.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/device/utils.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/drivers/FakeInstrument.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/drivers/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/ipy_events.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/bencoder.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/cli.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/dhcp.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/dhcpd.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/kad.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/kcp.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/nginx.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/progress.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/client.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/exceptions.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/msgpack.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/msgpack.pyi +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/router.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/rpc.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/serialize.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/server.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/socket.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/utils.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/worker.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/zmq_socket.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/utils.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/__init__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/__main__.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/_autoplot.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/plot_circ.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/plot_layout.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/plot_seq.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/qdat.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/rot3d.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/widgets.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/setup.cfg +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/setup.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/src/qulab.h +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/tests/test_kad.py +0 -0
- {qulab-2.7.6 → qulab-2.7.8}/tests/test_scan.py +0 -0
@@ -1,5 +1,5 @@
|
|
1
|
-
from .executor.storage import
|
2
|
-
from .executor.storage import
|
1
|
+
from .executor.storage import find_report
|
2
|
+
from .executor.storage import get_report_by_index as get_report
|
3
3
|
from .executor.utils import debug_analyze
|
4
4
|
from .scan import Scan, get_record, load_record, lookup, lookup_list
|
5
5
|
from .version import __version__
|
@@ -149,7 +149,7 @@ def get(key, api):
|
|
149
149
|
|
150
150
|
@click.command()
|
151
151
|
@click.argument('workflow')
|
152
|
-
@click.option('--plot', '-p', is_flag=True, help='Plot the
|
152
|
+
@click.option('--plot', '-p', is_flag=True, help='Plot the report.')
|
153
153
|
@click.option('--no-dependents',
|
154
154
|
'-n',
|
155
155
|
is_flag=True,
|
@@ -221,7 +221,7 @@ def run(workflow, code, data, api, plot, no_dependents, retry, freeze):
|
|
221
221
|
@click.command()
|
222
222
|
@click.argument('workflow')
|
223
223
|
@click.option('--retry', '-r', default=1, type=int, help='Retry times.')
|
224
|
-
@click.option('--plot', '-p', is_flag=True, help='Plot the
|
224
|
+
@click.option('--plot', '-p', is_flag=True, help='Plot the report.')
|
225
225
|
@log_options
|
226
226
|
@command_option('maintain')
|
227
227
|
def maintain(workflow, code, data, api, retry, plot):
|
@@ -15,7 +15,7 @@ from typing import Any
|
|
15
15
|
|
16
16
|
from loguru import logger
|
17
17
|
|
18
|
-
from .storage import
|
18
|
+
from .storage import Report
|
19
19
|
|
20
20
|
|
21
21
|
class SetConfigWorkflow():
|
@@ -29,7 +29,7 @@ class SetConfigWorkflow():
|
|
29
29
|
def depends(self):
|
30
30
|
return []
|
31
31
|
|
32
|
-
def check_state(self, history:
|
32
|
+
def check_state(self, history: Report) -> bool:
|
33
33
|
from . import transform
|
34
34
|
try:
|
35
35
|
return self._equal(history.parameters[self.key],
|
@@ -45,21 +45,21 @@ class SetConfigWorkflow():
|
|
45
45
|
value = eval(input(f'"{self.key}": '))
|
46
46
|
return value
|
47
47
|
|
48
|
-
def analyze(self,
|
49
|
-
|
50
|
-
|
51
|
-
return
|
48
|
+
def analyze(self, report: Report, history: Report):
|
49
|
+
report.state = 'OK'
|
50
|
+
report.parameters = {self.key: report.data}
|
51
|
+
return report
|
52
52
|
|
53
53
|
def check(self):
|
54
54
|
return self.calibrate()
|
55
55
|
|
56
|
-
def check_analyze(self,
|
56
|
+
def check_analyze(self, report: Report, history: Report | None):
|
57
57
|
if self.check_state(history):
|
58
|
-
|
59
|
-
|
58
|
+
report.state = 'OK'
|
59
|
+
report.parameters = {self.key: history.data}
|
60
60
|
else:
|
61
|
-
|
62
|
-
return
|
61
|
+
report.state = 'Outdated'
|
62
|
+
return report
|
63
63
|
|
64
64
|
@staticmethod
|
65
65
|
def _equal(a, b):
|
@@ -7,28 +7,28 @@ from pathlib import Path
|
|
7
7
|
from loguru import logger
|
8
8
|
|
9
9
|
from .load import WorkflowType, get_dependents
|
10
|
-
from .storage import (
|
11
|
-
|
10
|
+
from .storage import (Report, find_report, get_head, get_heads, renew_report,
|
11
|
+
revoke_report, save_report)
|
12
12
|
from .transform import current_config, obey_the_oracle, update_parameters
|
13
13
|
|
14
14
|
__session_id = None
|
15
15
|
__session_cache = {}
|
16
16
|
|
17
17
|
|
18
|
-
def set_cache(session_id, key,
|
18
|
+
def set_cache(session_id, key, report: Report):
|
19
19
|
global __session_id
|
20
20
|
if __session_id is None:
|
21
21
|
__session_id = session_id
|
22
22
|
if __session_id != session_id:
|
23
23
|
__session_cache.clear()
|
24
|
-
if
|
25
|
-
__session_cache[key] =
|
24
|
+
if report.workflow.startswith('cfg:'):
|
25
|
+
__session_cache[key] = report
|
26
26
|
else:
|
27
|
-
__session_cache[key] =
|
27
|
+
__session_cache[key] = report.base_path, report.path
|
28
28
|
|
29
29
|
|
30
|
-
def get_cache(session_id, key) ->
|
31
|
-
from .storage import
|
30
|
+
def get_cache(session_id, key) -> Report:
|
31
|
+
from .storage import load_report
|
32
32
|
global __session_id
|
33
33
|
if __session_id is None or __session_id != session_id:
|
34
34
|
return None
|
@@ -37,8 +37,8 @@ def get_cache(session_id, key) -> Result:
|
|
37
37
|
return None
|
38
38
|
if isinstance(index, tuple):
|
39
39
|
base_path, path = index
|
40
|
-
return
|
41
|
-
elif isinstance(index,
|
40
|
+
return load_report(base_path, path)
|
41
|
+
elif isinstance(index, Report):
|
42
42
|
return index
|
43
43
|
else:
|
44
44
|
return None
|
@@ -56,14 +56,14 @@ def is_pickleable(obj) -> bool:
|
|
56
56
|
return False
|
57
57
|
|
58
58
|
|
59
|
-
def
|
60
|
-
if not isinstance(
|
61
|
-
raise TypeError(f'"{script}" : "{method}" must return a
|
62
|
-
if not is_pickleable(
|
59
|
+
def veryfy_analyzed_report(report: Report, script: str, method: str):
|
60
|
+
if not isinstance(report, Report):
|
61
|
+
raise TypeError(f'"{script}" : "{method}" must return a Report object')
|
62
|
+
if not is_pickleable(report.parameters):
|
63
63
|
raise TypeError(
|
64
64
|
f'"{script}" : "{method}" return not pickleable data in .parameters'
|
65
65
|
)
|
66
|
-
if not is_pickleable(
|
66
|
+
if not is_pickleable(report.other_infomation):
|
67
67
|
raise TypeError(
|
68
68
|
f'"{script}" : "{method}" return not pickleable data in .other_infomation'
|
69
69
|
)
|
@@ -80,8 +80,8 @@ def check_state(workflow: WorkflowType, code_path: str | Path,
|
|
80
80
|
4. All dependencies pass check state.
|
81
81
|
"""
|
82
82
|
logger.debug(f'check_state: "{workflow.__workflow_id__}"')
|
83
|
-
|
84
|
-
if not
|
83
|
+
report = find_report(workflow.__workflow_id__, state_path)
|
84
|
+
if not report:
|
85
85
|
logger.debug(
|
86
86
|
f'check_state failed: No history found for "{workflow.__workflow_id__}"'
|
87
87
|
)
|
@@ -90,23 +90,23 @@ def check_state(workflow: WorkflowType, code_path: str | Path,
|
|
90
90
|
logger.debug(
|
91
91
|
f'check_state: "{workflow.__workflow_id__}" has custom check_state method'
|
92
92
|
)
|
93
|
-
return workflow.check_state(
|
93
|
+
return workflow.check_state(report)
|
94
94
|
if workflow.__timeout__ is not None and datetime.now(
|
95
|
-
) >
|
95
|
+
) > report.checked_time + timedelta(seconds=workflow.__timeout__):
|
96
96
|
logger.debug(
|
97
97
|
f'check_state failed: "{workflow.__workflow_id__}" has expired')
|
98
98
|
return False
|
99
|
-
if not
|
99
|
+
if not report.in_spec:
|
100
100
|
logger.debug(
|
101
101
|
f'check_state failed: "{workflow.__workflow_id__}" is out of spec')
|
102
102
|
return False
|
103
|
-
if
|
103
|
+
if report.bad_data:
|
104
104
|
logger.debug(
|
105
105
|
f'check_state failed: "{workflow.__workflow_id__}" has bad data')
|
106
106
|
return False
|
107
107
|
for n in get_dependents(workflow, code_path):
|
108
|
-
r =
|
109
|
-
if r is None or r.checked_time >
|
108
|
+
r = find_report(n.__workflow_id__, state_path)
|
109
|
+
if r is None or r.checked_time > report.checked_time:
|
110
110
|
logger.debug(
|
111
111
|
f'check_state failed: "{workflow.__workflow_id__}" has outdated dependencies'
|
112
112
|
)
|
@@ -120,71 +120,134 @@ def check_state(workflow: WorkflowType, code_path: str | Path,
|
|
120
120
|
return True
|
121
121
|
|
122
122
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
123
|
+
@logger.catch()
|
124
|
+
def call_plot(node: WorkflowType, report: Report, check=False):
|
125
|
+
if hasattr(node, 'plot') and callable(node.plot):
|
126
|
+
node.plot(report)
|
127
|
+
|
128
|
+
|
129
|
+
def call_check(workflow: WorkflowType, session_id: str, state_path: Path):
|
130
|
+
report = get_cache(session_id, (workflow, 'check'))
|
131
|
+
if report is not None:
|
132
|
+
logger.debug(f'Cache hit for "{workflow.__workflow_id__}:check"')
|
133
|
+
return report
|
134
|
+
|
135
|
+
data = workflow.check()
|
136
|
+
if not is_pickleable(data):
|
137
|
+
raise TypeError(
|
138
|
+
f'"{workflow.__workflow_id__}" : "check" return not pickleable data'
|
139
|
+
)
|
140
|
+
report = Report(workflow=workflow.__workflow_id__,
|
141
|
+
data=data,
|
142
|
+
config_path=current_config(state_path),
|
143
|
+
base_path=state_path,
|
144
|
+
heads=get_heads(state_path),
|
145
|
+
previous_path=get_head(workflow.__workflow_id__,
|
146
|
+
state_path))
|
147
|
+
|
148
|
+
save_report(workflow.__workflow_id__, report, state_path)
|
149
|
+
|
150
|
+
set_cache(session_id, (workflow, 'check'), report)
|
151
|
+
return report
|
152
|
+
|
153
|
+
|
154
|
+
def call_calibrate(workflow: WorkflowType, session_id: str, state_path: Path):
|
155
|
+
report = get_cache(session_id, (workflow, 'calibrate'))
|
156
|
+
if report is not None:
|
157
|
+
logger.debug(f'Cache hit for "{workflow.__workflow_id__}:calibrate"')
|
158
|
+
return report
|
159
|
+
|
160
|
+
data = workflow.calibrate()
|
161
|
+
if not is_pickleable(data):
|
162
|
+
raise TypeError(
|
163
|
+
f'"{workflow.__workflow_id__}" : "calibrate" return not pickleable data'
|
164
|
+
)
|
165
|
+
report = Report(workflow=workflow.__workflow_id__,
|
166
|
+
data=data,
|
167
|
+
config_path=current_config(state_path),
|
168
|
+
base_path=state_path,
|
169
|
+
heads=get_heads(state_path),
|
170
|
+
previous_path=get_head(workflow.__workflow_id__,
|
171
|
+
state_path))
|
172
|
+
|
173
|
+
save_report(workflow.__workflow_id__, report, state_path)
|
174
|
+
|
175
|
+
set_cache(session_id, (workflow, 'calibrate'), report)
|
176
|
+
return report
|
177
|
+
|
178
|
+
|
179
|
+
def call_check_analyzer(node: WorkflowType,
|
180
|
+
report: Report,
|
181
|
+
history: Report | None,
|
182
|
+
state_path: Path,
|
183
|
+
plot=False) -> Report:
|
184
|
+
report = node.check_analyze(report, history=history)
|
185
|
+
veryfy_analyzed_report(report, node.__workflow_id__, "check_analyze")
|
186
|
+
report.fully_calibrated = False
|
187
|
+
if report.in_spec:
|
188
|
+
logger.debug(
|
189
|
+
f'"{node.__workflow_id__}": checked in spec, renewing report')
|
190
|
+
renew_report(node.__workflow_id__, report.previous, state_path)
|
132
191
|
else:
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
f'"{node.__workflow_id__}" has oracle method, calling ...')
|
138
|
-
try:
|
139
|
-
result = node.oracle(result,
|
140
|
-
history=history,
|
141
|
-
system_state=get_heads(result.base_path))
|
142
|
-
except Exception as e:
|
143
|
-
logger.exception(e)
|
144
|
-
result.oracle = {}
|
145
|
-
if not isinstance(result, Result):
|
146
|
-
raise TypeError(
|
147
|
-
f'"{node.__workflow_id__}" : function "oracle" must return a Result object'
|
148
|
-
)
|
149
|
-
if not is_pickleable(result.oracle):
|
150
|
-
raise TypeError(
|
151
|
-
f'"{node.__workflow_id__}" : function "oracle" return not pickleable data'
|
152
|
-
)
|
153
|
-
result.fully_calibrated = True
|
154
|
-
if plot:
|
155
|
-
call_plot(node, result)
|
156
|
-
return result
|
192
|
+
logger.debug(
|
193
|
+
f'"{node.__workflow_id__}": checked out of spec, revoking report')
|
194
|
+
revoke_report(node.__workflow_id__, report.previous, state_path)
|
195
|
+
return report
|
157
196
|
|
158
197
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
198
|
+
def call_analyzer(node: WorkflowType,
|
199
|
+
report: Report,
|
200
|
+
history: Report | None,
|
201
|
+
state_path: Path,
|
202
|
+
plot=False) -> Report:
|
203
|
+
|
204
|
+
report = node.analyze(report, history=history)
|
205
|
+
veryfy_analyzed_report(report, node.__workflow_id__, "analyze")
|
206
|
+
if hasattr(node, 'oracle') and callable(node.oracle):
|
207
|
+
logger.debug(
|
208
|
+
f'"{node.__workflow_id__}" has oracle method, calling ...')
|
209
|
+
try:
|
210
|
+
report = node.oracle(report,
|
211
|
+
history=history,
|
212
|
+
system_state=get_heads(report.base_path))
|
213
|
+
except Exception as e:
|
214
|
+
logger.exception(e)
|
215
|
+
report.oracle = {}
|
216
|
+
if not isinstance(report, Report):
|
217
|
+
raise TypeError(
|
218
|
+
f'"{node.__workflow_id__}" : function "oracle" must return a Report object'
|
219
|
+
)
|
220
|
+
if not is_pickleable(report.oracle):
|
221
|
+
raise TypeError(
|
222
|
+
f'"{node.__workflow_id__}" : function "oracle" return not pickleable data'
|
223
|
+
)
|
224
|
+
report.fully_calibrated = True
|
225
|
+
save_report(node.__workflow_id__, report, state_path, overwrite=True)
|
226
|
+
if plot:
|
227
|
+
call_plot(node, report)
|
228
|
+
return report
|
163
229
|
|
164
230
|
|
165
|
-
def check_data(workflow: WorkflowType,
|
166
|
-
|
231
|
+
def check_data(workflow: WorkflowType, state_path: str | Path, plot: bool,
|
232
|
+
session_id: str) -> Report:
|
167
233
|
"""
|
168
234
|
check data answers two questions:
|
169
235
|
Is the parameter associated with this cal in spec,
|
170
236
|
and is the cal scan working as expected?
|
171
237
|
"""
|
172
|
-
|
173
|
-
if result is not None:
|
174
|
-
logger.debug(f'Cache hit for "{workflow.__workflow_id__}:check_data"')
|
175
|
-
return result
|
176
|
-
|
177
|
-
history = find_result(workflow.__workflow_id__, state_path)
|
238
|
+
history = find_report(workflow.__workflow_id__, state_path)
|
178
239
|
|
179
240
|
if history is None:
|
180
241
|
logger.debug(f'No history found for "{workflow.__workflow_id__}"')
|
181
|
-
|
242
|
+
report = Report(workflow=workflow.__workflow_id__,
|
182
243
|
config_path=current_config(state_path),
|
183
244
|
base_path=state_path,
|
184
|
-
heads=get_heads(state_path)
|
185
|
-
|
186
|
-
|
187
|
-
|
245
|
+
heads=get_heads(state_path),
|
246
|
+
previous_path=get_head(workflow.__workflow_id__,
|
247
|
+
state_path))
|
248
|
+
report.in_spec = False
|
249
|
+
report.bad_data = False
|
250
|
+
return report
|
188
251
|
|
189
252
|
if history.bad_data:
|
190
253
|
logger.debug(
|
@@ -202,92 +265,48 @@ def check_data(workflow: WorkflowType, code_path: str | Path,
|
|
202
265
|
workflow, 'check_analyze') and callable(workflow.check_analyze):
|
203
266
|
logger.debug(
|
204
267
|
f'Checking "{workflow.__workflow_id__}" with "check" method ...')
|
205
|
-
|
206
|
-
|
207
|
-
raise TypeError(
|
208
|
-
f'"{workflow.__workflow_id__}" : "check" return not pickleable data'
|
209
|
-
)
|
210
|
-
result = Result(workflow=workflow.__workflow_id__,
|
211
|
-
data=data,
|
212
|
-
config_path=current_config(state_path),
|
213
|
-
base_path=state_path,
|
214
|
-
heads=get_heads(state_path))
|
215
|
-
#save_result(workflow.__workflow_id__, result, state_path)
|
268
|
+
|
269
|
+
report = call_check(workflow, session_id, state_path)
|
216
270
|
|
217
271
|
logger.debug(f'Checked "{workflow.__workflow_id__}" !')
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
if result.in_spec:
|
224
|
-
logger.debug(
|
225
|
-
f'"{workflow.__workflow_id__}": checked in spec, renewing result'
|
226
|
-
)
|
227
|
-
renew_result(workflow.__workflow_id__, state_path)
|
228
|
-
else:
|
229
|
-
logger.debug(
|
230
|
-
f'"{workflow.__workflow_id__}": checked out of spec, revoking result'
|
231
|
-
)
|
232
|
-
revoke_result(workflow.__workflow_id__, state_path)
|
272
|
+
report = call_check_analyzer(workflow,
|
273
|
+
report,
|
274
|
+
history,
|
275
|
+
state_path,
|
276
|
+
plot=plot)
|
233
277
|
else:
|
234
278
|
logger.debug(
|
235
279
|
f'Checking "{workflow.__workflow_id__}" with "calibrate" method ...'
|
236
280
|
)
|
237
|
-
|
238
|
-
|
239
|
-
raise TypeError(
|
240
|
-
f'"{workflow.__workflow_id__}" : "calibrate" return not pickleable data'
|
241
|
-
)
|
242
|
-
result = Result(workflow=workflow.__workflow_id__,
|
243
|
-
data=data,
|
244
|
-
config_path=current_config(state_path),
|
245
|
-
base_path=state_path,
|
246
|
-
heads=get_heads(state_path))
|
247
|
-
save_result(workflow.__workflow_id__, result, state_path)
|
281
|
+
|
282
|
+
report = call_calibrate(workflow, session_id, state_path)
|
248
283
|
|
249
284
|
logger.debug(f'Calibrated "{workflow.__workflow_id__}" !')
|
250
|
-
|
251
|
-
|
285
|
+
report = call_analyzer(workflow,
|
286
|
+
report,
|
252
287
|
history,
|
253
|
-
|
288
|
+
state_path,
|
254
289
|
plot=plot)
|
255
|
-
|
256
|
-
result,
|
257
|
-
state_path,
|
258
|
-
overwrite=True)
|
290
|
+
return report
|
259
291
|
|
260
|
-
set_cache(session_id, (workflow, 'check_data'), result)
|
261
|
-
return result
|
262
292
|
|
293
|
+
def calibrate(workflow: WorkflowType, state_path: str | Path, plot: bool,
|
294
|
+
session_id: str) -> Report:
|
295
|
+
history = find_report(workflow.__workflow_id__, state_path)
|
263
296
|
|
264
|
-
|
265
|
-
state_path: str | Path, plot: bool, session_id: str) -> Result:
|
266
|
-
result = get_cache(session_id, (workflow, 'calibrate'))
|
267
|
-
if result is not None:
|
268
|
-
logger.debug(f'Cache hit for "{workflow.__workflow_id__}:calibrate"')
|
269
|
-
return result
|
297
|
+
logger.debug(f'Calibrating "{workflow.__workflow_id__}" ...')
|
270
298
|
|
271
|
-
|
299
|
+
report = call_calibrate(workflow, session_id, state_path)
|
272
300
|
|
273
|
-
logger.debug(f'Calibrating "{workflow.__workflow_id__}" ...')
|
274
|
-
data = workflow.calibrate()
|
275
|
-
if not is_pickleable(data):
|
276
|
-
raise TypeError(
|
277
|
-
f'"{workflow.__workflow_id__}" : "calibrate" return not pickleable data'
|
278
|
-
)
|
279
|
-
result = Result(workflow=workflow.__workflow_id__,
|
280
|
-
data=data,
|
281
|
-
config_path=current_config(state_path),
|
282
|
-
base_path=state_path,
|
283
|
-
heads=get_heads(state_path))
|
284
|
-
save_result(workflow.__workflow_id__, result, state_path)
|
285
301
|
logger.debug(f'Calibrated "{workflow.__workflow_id__}" !')
|
286
|
-
result = call_analyzer(workflow, result, history, check=False, plot=plot)
|
287
|
-
save_result(workflow.__workflow_id__, result, state_path, overwrite=True)
|
288
302
|
|
289
|
-
|
290
|
-
|
303
|
+
report = call_analyzer(workflow,
|
304
|
+
report,
|
305
|
+
history,
|
306
|
+
state_path,
|
307
|
+
check=False,
|
308
|
+
plot=plot)
|
309
|
+
return report
|
291
310
|
|
292
311
|
|
293
312
|
def diagnose(workflow: WorkflowType, code_path: str | Path,
|
@@ -297,16 +316,16 @@ def diagnose(workflow: WorkflowType, code_path: str | Path,
|
|
297
316
|
'''
|
298
317
|
logger.debug(f'diagnose "{workflow.__workflow_id__}"')
|
299
318
|
# check_data
|
300
|
-
|
319
|
+
report = check_data(workflow, state_path, plot, session_id)
|
301
320
|
# in spec case
|
302
|
-
if
|
321
|
+
if report.in_spec:
|
303
322
|
logger.debug(
|
304
323
|
f'"{workflow.__workflow_id__}": Checked! In spec, no need to diagnose'
|
305
324
|
)
|
306
325
|
return False
|
307
326
|
# bad data case
|
308
327
|
recalibrated = []
|
309
|
-
if
|
328
|
+
if report.bad_data:
|
310
329
|
logger.debug(
|
311
330
|
f'"{workflow.__workflow_id__}": Bad data, diagnosing dependents')
|
312
331
|
recalibrated = [
|
@@ -314,7 +333,7 @@ def diagnose(workflow: WorkflowType, code_path: str | Path,
|
|
314
333
|
for n in get_dependents(workflow, code_path)
|
315
334
|
]
|
316
335
|
if not any(recalibrated):
|
317
|
-
if
|
336
|
+
if report.bad_data:
|
318
337
|
raise CalibrationFailedError(
|
319
338
|
f'"{workflow.__workflow_id__}": bad data but no dependents recalibrated.'
|
320
339
|
)
|
@@ -325,27 +344,27 @@ def diagnose(workflow: WorkflowType, code_path: str | Path,
|
|
325
344
|
logger.debug(
|
326
345
|
f'recalibrate "{workflow.__workflow_id__}" because some dependents recalibrated.'
|
327
346
|
)
|
328
|
-
elif not
|
347
|
+
elif not report.in_spec and not report.bad_data:
|
329
348
|
logger.debug(
|
330
349
|
f'recalibrate "{workflow.__workflow_id__}" because out of spec.')
|
331
|
-
elif
|
350
|
+
elif report.in_spec:
|
332
351
|
logger.error(
|
333
352
|
f'Never reach: recalibrate "{workflow.__workflow_id__}" because in spec.'
|
334
353
|
)
|
335
|
-
elif
|
354
|
+
elif report.bad_data:
|
336
355
|
logger.error(
|
337
356
|
f'Never reach: recalibrate "{workflow.__workflow_id__}" because bad data.'
|
338
357
|
)
|
339
358
|
else:
|
340
359
|
logger.error(f'Never reach: recalibrate "{workflow.__workflow_id__}"')
|
341
360
|
|
342
|
-
|
343
|
-
if
|
344
|
-
obey_the_oracle(
|
361
|
+
report = calibrate(workflow, state_path, plot, session_id)
|
362
|
+
if report.bad_data or not report.in_spec:
|
363
|
+
obey_the_oracle(report, state_path)
|
345
364
|
raise CalibrationFailedError(
|
346
365
|
f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
|
347
366
|
)
|
348
|
-
update_parameters(
|
367
|
+
update_parameters(report, state_path)
|
349
368
|
return True
|
350
369
|
|
351
370
|
|
@@ -382,13 +401,13 @@ def maintain(workflow: WorkflowType,
|
|
382
401
|
f'"{workflow.__workflow_id__}": In spec, no need to maintain')
|
383
402
|
return
|
384
403
|
# check_data
|
385
|
-
|
386
|
-
if
|
404
|
+
report = check_data(workflow, state_path, plot, session_id)
|
405
|
+
if report.in_spec:
|
387
406
|
if not run:
|
388
407
|
logger.debug(
|
389
408
|
f'"{workflow.__workflow_id__}": In spec, no need to maintain')
|
390
409
|
return
|
391
|
-
elif
|
410
|
+
elif report.bad_data:
|
392
411
|
logger.debug(
|
393
412
|
f'"{workflow.__workflow_id__}": Bad data, diagnosing dependents')
|
394
413
|
for n in get_dependents(workflow, code_path):
|
@@ -401,15 +420,15 @@ def maintain(workflow: WorkflowType,
|
|
401
420
|
f'"{workflow.__workflow_id__}": All dependents diagnosed')
|
402
421
|
# calibrate
|
403
422
|
logger.debug(f'recalibrate "{workflow.__workflow_id__}"')
|
404
|
-
|
405
|
-
if
|
423
|
+
report = calibrate(workflow, state_path, plot, session_id)
|
424
|
+
if report.bad_data or not report.in_spec:
|
406
425
|
if not freeze:
|
407
|
-
obey_the_oracle(
|
426
|
+
obey_the_oracle(report, state_path)
|
408
427
|
raise CalibrationFailedError(
|
409
428
|
f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
|
410
429
|
)
|
411
430
|
if not freeze:
|
412
|
-
update_parameters(
|
431
|
+
update_parameters(report, state_path)
|
413
432
|
return
|
414
433
|
|
415
434
|
|
@@ -421,17 +440,13 @@ def run(workflow: WorkflowType,
|
|
421
440
|
freeze: bool = False):
|
422
441
|
session_id = uuid.uuid4().hex
|
423
442
|
logger.debug(f'run "{workflow.__workflow_id__}" without dependences.')
|
424
|
-
|
425
|
-
|
426
|
-
state_path,
|
427
|
-
plot,
|
428
|
-
session_id=session_id)
|
429
|
-
if result.bad_data or not result.in_spec:
|
443
|
+
report = calibrate(workflow, state_path, plot, session_id=session_id)
|
444
|
+
if report.bad_data or not report.in_spec:
|
430
445
|
if not freeze:
|
431
|
-
obey_the_oracle(
|
446
|
+
obey_the_oracle(report, state_path)
|
432
447
|
raise CalibrationFailedError(
|
433
448
|
f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
|
434
449
|
)
|
435
450
|
if not freeze:
|
436
|
-
update_parameters(
|
451
|
+
update_parameters(report, state_path)
|
437
452
|
return
|