QuLab 2.5.5__cp311-cp311-win_amd64.whl → 2.6.1__cp311-cp311-win_amd64.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.
- {QuLab-2.5.5.dist-info → QuLab-2.6.1.dist-info}/METADATA +1 -1
- {QuLab-2.5.5.dist-info → QuLab-2.6.1.dist-info}/RECORD +15 -15
- qulab/__init__.py +1 -0
- qulab/executor/cli.py +4 -4
- qulab/executor/load.py +8 -8
- qulab/executor/schedule.py +19 -11
- qulab/executor/storage.py +42 -0
- qulab/executor/transform.py +32 -5
- qulab/executor/utils.py +21 -0
- qulab/fun.cp311-win_amd64.pyd +0 -0
- qulab/version.py +1 -1
- {QuLab-2.5.5.dist-info → QuLab-2.6.1.dist-info}/LICENSE +0 -0
- {QuLab-2.5.5.dist-info → QuLab-2.6.1.dist-info}/WHEEL +0 -0
- {QuLab-2.5.5.dist-info → QuLab-2.6.1.dist-info}/entry_points.txt +0 -0
- {QuLab-2.5.5.dist-info → QuLab-2.6.1.dist-info}/top_level.txt +0 -0
@@ -1,19 +1,19 @@
|
|
1
|
-
qulab/__init__.py,sha256=
|
1
|
+
qulab/__init__.py,sha256=F4TiURMBaXkAc0evuYi-aan00II4hzMHrOs0GfooLtg,292
|
2
2
|
qulab/__main__.py,sha256=FL4YsGZL1jEtmcPc5WbleArzhOHLMsWl7OH3O-1d1ss,72
|
3
3
|
qulab/dicttree.py,sha256=ZoSJVWK4VMqfzj42gPb_n5RqLlM6K1Me0WmLIfLEYf8,14195
|
4
|
-
qulab/fun.cp311-win_amd64.pyd,sha256=
|
4
|
+
qulab/fun.cp311-win_amd64.pyd,sha256=94G8dLW-skDKP8pt3v6A9VHHXbMOEqdUAux_9mWZXTM,31744
|
5
5
|
qulab/typing.py,sha256=3c0eKa1avEHIi5wPvh3-4l6Of5mu5Rn1MWPnMeLGNX0,71
|
6
|
-
qulab/version.py,sha256=
|
6
|
+
qulab/version.py,sha256=CxIX_WubB9c4uEWgzV2lPv0dBsuUamxzVZLp62HT2u4,21
|
7
7
|
qulab/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
qulab/cli/commands.py,sha256=6xd2eYw32k1NmfAuYSu__1kaP12Oz1QVqwbkYXdWno4,588
|
9
9
|
qulab/cli/config.py,sha256=tNmH4ggdgrFqcQa2WZKLpidiYTg95_UnT0paDJ4fi4c,3204
|
10
10
|
qulab/executor/__init__.py,sha256=LosPzOMaljSZY1thy_Fxtbrgq7uubJszMABEB7oM7tU,101
|
11
|
-
qulab/executor/cli.py,sha256=
|
12
|
-
qulab/executor/load.py,sha256=
|
13
|
-
qulab/executor/schedule.py,sha256=
|
14
|
-
qulab/executor/storage.py,sha256=
|
15
|
-
qulab/executor/transform.py,sha256=
|
16
|
-
qulab/executor/utils.py,sha256=
|
11
|
+
qulab/executor/cli.py,sha256=MjwXe_ZEolVzNkGYq6G4cp-iHI0TiAlNkSuX2p0ZZQk,6760
|
12
|
+
qulab/executor/load.py,sha256=_XxHHSgQTxaOo6zhY9UZnqPu_wiG8BT6FyBaeH67lvo,17856
|
13
|
+
qulab/executor/schedule.py,sha256=RkhDjwsxXT2RmO6ZTcP7LGsY4M4KY6Acmykq_kQ_wcc,13992
|
14
|
+
qulab/executor/storage.py,sha256=2Kvv7Nk98OLF6ux2PkfTTcZnHDG3g6TKpIb9e7yVbz0,8694
|
15
|
+
qulab/executor/transform.py,sha256=tp7yW8FdISVI6xx1ZIyCiRID1SQXw-bjucaPXPkn6m0,1988
|
16
|
+
qulab/executor/utils.py,sha256=G6hRwvrcIwJwJtcAHV8UaGLdlT0kokWHfV2D922n2mg,4935
|
17
17
|
qulab/monitor/__init__.py,sha256=xEVDkJF8issrsDeLqQmDsvtRmrf-UiViFcGTWuzdlFU,43
|
18
18
|
qulab/monitor/__main__.py,sha256=k2H1H5Zf9LLXTDLISJkbikLH-z0f1e5i5i6wXXYPOrE,105
|
19
19
|
qulab/monitor/config.py,sha256=y_5StMkdrbZO1ziyKBrvIkB7Jclp9RCPK1QbsOhCxnY,785
|
@@ -93,9 +93,9 @@ qulab/visualization/plot_seq.py,sha256=Uo1-dB1YE9IN_A9tuaOs9ZG3S5dKDQ_l98iD2Wbxp
|
|
93
93
|
qulab/visualization/qdat.py,sha256=HubXFu4nfcA7iUzghJGle1C86G6221hicLR0b-GqhKQ,5887
|
94
94
|
qulab/visualization/rot3d.py,sha256=jGHJcqj1lEWBUV-W4GUGONGacqjrYvuFoFCwPse5h1Y,757
|
95
95
|
qulab/visualization/widgets.py,sha256=HcYwdhDtLreJiYaZuN3LfofjJmZcLwjMfP5aasebgDo,3266
|
96
|
-
QuLab-2.
|
97
|
-
QuLab-2.
|
98
|
-
QuLab-2.
|
99
|
-
QuLab-2.
|
100
|
-
QuLab-2.
|
101
|
-
QuLab-2.
|
96
|
+
QuLab-2.6.1.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
|
97
|
+
QuLab-2.6.1.dist-info/METADATA,sha256=Z5mfL3SUzgD-oTkz9OjyQJwm1nRnrEZAFH6N2XWJDlc,3803
|
98
|
+
QuLab-2.6.1.dist-info/WHEEL,sha256=yNnHoQL2GZYIUXm9YvoaBpFjGlUoK9qq9oqYeudrWlE,101
|
99
|
+
QuLab-2.6.1.dist-info/entry_points.txt,sha256=b0v1GXOwmxY-nCCsPN_rHZZvY9CtTbWqrGj8u1m8yHo,45
|
100
|
+
QuLab-2.6.1.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
|
101
|
+
QuLab-2.6.1.dist-info/RECORD,,
|
qulab/__init__.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
from .executor.storage import find_result
|
2
2
|
from .executor.storage import get_result_by_index as get_result
|
3
|
+
from .executor.utils import debug_analyze
|
3
4
|
from .scan import Scan, get_record, load_record, lookup, lookup_list
|
4
5
|
from .version import __version__
|
5
6
|
from .visualization import autoplot
|
qulab/executor/cli.py
CHANGED
@@ -102,7 +102,7 @@ def set(key, value, api):
|
|
102
102
|
from . import transform
|
103
103
|
if api is not None:
|
104
104
|
api = importlib.import_module(api)
|
105
|
-
set_config_api(api.query_config, api.update_config)
|
105
|
+
set_config_api(api.query_config, api.update_config, api.export_config)
|
106
106
|
try:
|
107
107
|
value = eval(value)
|
108
108
|
except:
|
@@ -124,7 +124,7 @@ def get(key, api):
|
|
124
124
|
from . import transform
|
125
125
|
if api is not None:
|
126
126
|
api = importlib.import_module(api)
|
127
|
-
set_config_api(api.query_config, api.update_config)
|
127
|
+
set_config_api(api.query_config, api.update_config, api.export_config)
|
128
128
|
click.echo(transform.query_config(key))
|
129
129
|
|
130
130
|
|
@@ -147,7 +147,7 @@ def run(workflow, code, data, api, plot, no_dependents, update):
|
|
147
147
|
)
|
148
148
|
if api is not None:
|
149
149
|
api = importlib.import_module(api)
|
150
|
-
set_config_api(api.query_config, api.update_config)
|
150
|
+
set_config_api(api.query_config, api.update_config, api.export_config)
|
151
151
|
if code is None:
|
152
152
|
code = Path.cwd()
|
153
153
|
if data is None:
|
@@ -197,7 +197,7 @@ def maintain(workflow, code, data, api, plot):
|
|
197
197
|
)
|
198
198
|
if api is not None:
|
199
199
|
api = importlib.import_module(api)
|
200
|
-
set_config_api(api.query_config, api.update_config)
|
200
|
+
set_config_api(api.query_config, api.update_config, api.export_config)
|
201
201
|
if code is None:
|
202
202
|
code = Path.cwd()
|
203
203
|
if data is None:
|
qulab/executor/load.py
CHANGED
@@ -123,7 +123,7 @@ def verify_check_method(module: WorkflowType):
|
|
123
123
|
|
124
124
|
|
125
125
|
def verify_dependence_key(workflow: str | tuple[str, dict[str, Any]]
|
126
|
-
| tuple[str, str, dict[str, Any]]):
|
126
|
+
| tuple[str, str, dict[str, Any]], base_path: Path):
|
127
127
|
if isinstance(workflow, str):
|
128
128
|
return
|
129
129
|
if not isinstance(workflow, tuple) or len(workflow) not in [2, 3]:
|
@@ -135,7 +135,7 @@ def verify_dependence_key(workflow: str | tuple[str, dict[str, Any]]
|
|
135
135
|
raise FileNotFoundError(f"File not found: {file_name}")
|
136
136
|
elif len(workflow) == 3:
|
137
137
|
template_path, target_path, mapping = workflow
|
138
|
-
if not Path(template_path).exists():
|
138
|
+
if not (Path(base_path) / template_path).exists():
|
139
139
|
raise FileNotFoundError(f"File not found: {template_path}")
|
140
140
|
if not isinstance(target_path, (Path, str)) or target_path == '':
|
141
141
|
raise ValueError(f"Invalid target_path: {target_path}")
|
@@ -165,7 +165,7 @@ def verify_dependence_key(workflow: str | tuple[str, dict[str, Any]]
|
|
165
165
|
return
|
166
166
|
|
167
167
|
|
168
|
-
def verify_depends(module: WorkflowType):
|
168
|
+
def verify_depends(module: WorkflowType, base_path):
|
169
169
|
if not hasattr(module, 'depends'):
|
170
170
|
return
|
171
171
|
|
@@ -184,10 +184,10 @@ def verify_depends(module: WorkflowType):
|
|
184
184
|
f"Workflow {module.__file__} 'depends' should be a callable or a list"
|
185
185
|
)
|
186
186
|
for workflow in deps:
|
187
|
-
verify_dependence_key(workflow)
|
187
|
+
verify_dependence_key(workflow, base_path)
|
188
188
|
|
189
189
|
|
190
|
-
def verify_entries(module: WorkflowType):
|
190
|
+
def verify_entries(module: WorkflowType, base_path):
|
191
191
|
if not hasattr(module, 'entries'):
|
192
192
|
return
|
193
193
|
|
@@ -206,7 +206,7 @@ def verify_entries(module: WorkflowType):
|
|
206
206
|
f"Workflow {module.__file__} 'entries' should be a callable or a list"
|
207
207
|
)
|
208
208
|
for workflow in deps:
|
209
|
-
verify_dependence_key(workflow)
|
209
|
+
verify_dependence_key(workflow, base_path)
|
210
210
|
|
211
211
|
|
212
212
|
def is_workflow(module: ModuleType) -> bool:
|
@@ -307,7 +307,7 @@ def load_workflow_from_file(file_name: str,
|
|
307
307
|
module.__mtime__ = (base_path / path).stat().st_mtime
|
308
308
|
|
309
309
|
if hasattr(module, 'entries'):
|
310
|
-
verify_entries(module)
|
310
|
+
verify_entries(module, base_path)
|
311
311
|
return module
|
312
312
|
|
313
313
|
if not hasattr(module, '__timeout__'):
|
@@ -315,7 +315,7 @@ def load_workflow_from_file(file_name: str,
|
|
315
315
|
|
316
316
|
if not hasattr(module, 'depends'):
|
317
317
|
module.depends = lambda: []
|
318
|
-
verify_depends(module)
|
318
|
+
verify_depends(module, base_path)
|
319
319
|
verify_calibrate_method(module)
|
320
320
|
verify_check_method(module)
|
321
321
|
|
qulab/executor/schedule.py
CHANGED
@@ -9,7 +9,7 @@ from loguru import logger
|
|
9
9
|
from .load import WorkflowType, get_dependents
|
10
10
|
from .storage import (Result, find_result, renew_result, revoke_result,
|
11
11
|
save_result)
|
12
|
-
from .transform import update_parameters
|
12
|
+
from .transform import current_config, update_parameters
|
13
13
|
|
14
14
|
|
15
15
|
class CalibrationFailedError(Exception):
|
@@ -124,7 +124,9 @@ def check_data(workflow: WorkflowType, code_path: str | Path,
|
|
124
124
|
|
125
125
|
if history is None:
|
126
126
|
logger.debug(f'No history found for "{workflow.__workflow_id__}"')
|
127
|
-
result = Result(
|
127
|
+
result = Result(workflow=workflow.__workflow_id__,
|
128
|
+
config_path=current_config(state_path),
|
129
|
+
base_path=state_path)
|
128
130
|
result.in_spec = False
|
129
131
|
result.bad_data = False
|
130
132
|
return result
|
@@ -150,8 +152,10 @@ def check_data(workflow: WorkflowType, code_path: str | Path,
|
|
150
152
|
raise TypeError(
|
151
153
|
f'"{workflow.__workflow_id__}" : "check" return not pickleable data'
|
152
154
|
)
|
153
|
-
result = Result(
|
154
|
-
|
155
|
+
result = Result(workflow=workflow.__workflow_id__,
|
156
|
+
data=data,
|
157
|
+
config_path=current_config(state_path),
|
158
|
+
base_path=state_path)
|
155
159
|
#save_result(workflow.__workflow_id__, result, state_path)
|
156
160
|
|
157
161
|
logger.debug(f'Checked "{workflow.__workflow_id__}" !')
|
@@ -179,8 +183,10 @@ def check_data(workflow: WorkflowType, code_path: str | Path,
|
|
179
183
|
raise TypeError(
|
180
184
|
f'"{workflow.__workflow_id__}" : "calibrate" return not pickleable data'
|
181
185
|
)
|
182
|
-
result = Result(
|
183
|
-
|
186
|
+
result = Result(workflow=workflow.__workflow_id__,
|
187
|
+
data=data,
|
188
|
+
config_path=current_config(state_path),
|
189
|
+
base_path=state_path)
|
184
190
|
save_result(workflow.__workflow_id__, result, state_path)
|
185
191
|
|
186
192
|
logger.debug(f'Calibrated "{workflow}" !')
|
@@ -208,8 +214,10 @@ def calibrate(workflow: WorkflowType, code_path: str | Path,
|
|
208
214
|
raise TypeError(
|
209
215
|
f'"{workflow.__workflow_id__}" : "calibrate" return not pickleable data'
|
210
216
|
)
|
211
|
-
result = Result(
|
212
|
-
|
217
|
+
result = Result(workflow=workflow.__workflow_id__,
|
218
|
+
data=data,
|
219
|
+
config_path=current_config(state_path),
|
220
|
+
base_path=state_path)
|
213
221
|
save_result(workflow.__workflow_id__, result, state_path)
|
214
222
|
logger.debug(f'Calibrated "{workflow.__workflow_id__}" !')
|
215
223
|
result = call_analyzer(workflow, result, history, check=False, plot=plot)
|
@@ -271,7 +279,7 @@ def diagnose(workflow: WorkflowType, code_path: str | Path,
|
|
271
279
|
raise CalibrationFailedError(
|
272
280
|
f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
|
273
281
|
)
|
274
|
-
update_parameters(result)
|
282
|
+
update_parameters(result, state_path)
|
275
283
|
return True
|
276
284
|
|
277
285
|
|
@@ -327,7 +335,7 @@ def maintain(workflow: WorkflowType,
|
|
327
335
|
f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
|
328
336
|
)
|
329
337
|
if update:
|
330
|
-
update_parameters(result)
|
338
|
+
update_parameters(result, state_path)
|
331
339
|
return
|
332
340
|
|
333
341
|
|
@@ -349,5 +357,5 @@ def run(workflow: WorkflowType,
|
|
349
357
|
f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
|
350
358
|
)
|
351
359
|
if update:
|
352
|
-
update_parameters(result)
|
360
|
+
update_parameters(result, state_path)
|
353
361
|
return
|
qulab/executor/storage.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import hashlib
|
1
2
|
import lzma
|
2
3
|
import pickle
|
3
4
|
import uuid
|
@@ -14,6 +15,7 @@ from ..cli.config import get_config_value
|
|
14
15
|
|
15
16
|
@dataclass
|
16
17
|
class Result():
|
18
|
+
workflow: str = ''
|
17
19
|
in_spec: bool = False
|
18
20
|
bad_data: bool = False
|
19
21
|
fully_calibrated: bool = False
|
@@ -26,6 +28,7 @@ class Result():
|
|
26
28
|
index: int = -1
|
27
29
|
previous_path: Path | None = None
|
28
30
|
base_path: Path | None = None
|
31
|
+
config_path: Path | None = None
|
29
32
|
|
30
33
|
@property
|
31
34
|
def previous(self):
|
@@ -46,6 +49,13 @@ class Result():
|
|
46
49
|
state = 'Outdated'
|
47
50
|
return state
|
48
51
|
|
52
|
+
@property
|
53
|
+
def config(self):
|
54
|
+
if self.config_path is not None and self.base_path is not None:
|
55
|
+
return load_config(self.config_path, self.base_path)
|
56
|
+
else:
|
57
|
+
return None
|
58
|
+
|
49
59
|
@state.setter
|
50
60
|
def state(self, state: Literal['OK', 'Bad', 'Outdated', 'In spec',
|
51
61
|
'Out of spec', 'Bad data']):
|
@@ -231,3 +241,35 @@ def get_result_by_index(
|
|
231
241
|
return load_result(path, base_path)
|
232
242
|
except:
|
233
243
|
return None
|
244
|
+
|
245
|
+
|
246
|
+
def save_config(cfg, data_path):
|
247
|
+
i = 0
|
248
|
+
buf = pickle.dumps(cfg)
|
249
|
+
buf = lzma.compress(buf)
|
250
|
+
h = hashlib.md5(buf)
|
251
|
+
|
252
|
+
while True:
|
253
|
+
salt = f"{i}".encode()
|
254
|
+
h.update(salt)
|
255
|
+
hashstr = h.hexdigest()
|
256
|
+
cfg_id = Path(hashstr[:2]) / hashstr[2:4] / hashstr[4:]
|
257
|
+
path = Path(data_path) / 'config' / cfg_id
|
258
|
+
if not path.exists():
|
259
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
260
|
+
with open(path, 'wb') as f:
|
261
|
+
f.write(buf)
|
262
|
+
break
|
263
|
+
elif path.read_bytes() == buf:
|
264
|
+
break
|
265
|
+
i += 1
|
266
|
+
return str(cfg_id)
|
267
|
+
|
268
|
+
|
269
|
+
@lru_cache(maxsize=1024)
|
270
|
+
def load_config(id, data_path):
|
271
|
+
path = Path(data_path) / 'config' / id
|
272
|
+
with open(path, 'rb') as f:
|
273
|
+
buf = f.read()
|
274
|
+
cfg = pickle.loads(lzma.decompress(buf))
|
275
|
+
return cfg
|
qulab/executor/transform.py
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
from .storage import Result
|
1
|
+
from .storage import Result, save_config
|
2
|
+
|
3
|
+
__current_config_id = None
|
2
4
|
|
3
5
|
|
4
6
|
def _query_config(name: str, default=None):
|
@@ -29,15 +31,39 @@ def _update_config(updates):
|
|
29
31
|
pickle.dump(parameters, f)
|
30
32
|
|
31
33
|
|
32
|
-
def
|
34
|
+
def _export_config() -> dict:
|
35
|
+
import pickle
|
36
|
+
|
37
|
+
try:
|
38
|
+
with open('parameters.pkl', 'rb') as f:
|
39
|
+
parameters = pickle.load(f)
|
40
|
+
except:
|
41
|
+
parameters = {}
|
42
|
+
|
43
|
+
return parameters
|
44
|
+
|
45
|
+
|
46
|
+
def update_parameters(result: Result, data_path):
|
47
|
+
global __current_config_id
|
33
48
|
update_config(result.parameters)
|
49
|
+
cfg = export_config()
|
50
|
+
__current_config_id = save_config(cfg, data_path)
|
51
|
+
|
52
|
+
|
53
|
+
def current_config(data_path):
|
54
|
+
global __current_config_id
|
55
|
+
if __current_config_id is None:
|
56
|
+
cfg = export_config()
|
57
|
+
__current_config_id = save_config(cfg, data_path)
|
58
|
+
return __current_config_id
|
34
59
|
|
35
60
|
|
36
61
|
query_config = _query_config
|
37
62
|
update_config = _update_config
|
63
|
+
export_config = _export_config
|
38
64
|
|
39
65
|
|
40
|
-
def set_config_api(query_method, update_method):
|
66
|
+
def set_config_api(query_method, update_method, export_method):
|
41
67
|
"""
|
42
68
|
Set the query and update methods for the config.
|
43
69
|
|
@@ -47,9 +73,10 @@ def set_config_api(query_method, update_method):
|
|
47
73
|
update_method: The update method.
|
48
74
|
the method should take a dict of updates.
|
49
75
|
"""
|
50
|
-
global query_config, update_config
|
76
|
+
global query_config, update_config, export_config
|
51
77
|
|
52
78
|
query_config = query_method
|
53
79
|
update_config = update_method
|
80
|
+
export_config = export_method
|
54
81
|
|
55
|
-
return query_config, update_config
|
82
|
+
return query_config, update_config, export_config
|
qulab/executor/utils.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
from pathlib import Path
|
2
2
|
|
3
|
+
from ..cli.config import get_config_value
|
3
4
|
from .load import load_workflow
|
4
5
|
|
5
6
|
|
@@ -133,3 +134,23 @@ def check_analyze(result: Result, history: Result | None = None) -> Result:
|
|
133
134
|
|
134
135
|
return result
|
135
136
|
"""
|
137
|
+
|
138
|
+
|
139
|
+
def debug_analyze(
|
140
|
+
result_index: int,
|
141
|
+
code_path: str | Path = get_config_value('code', Path),
|
142
|
+
data_path: str | Path = get_config_value('data', Path),
|
143
|
+
) -> None:
|
144
|
+
from .storage import get_result_by_index
|
145
|
+
|
146
|
+
result = get_result_by_index(result_index, data_path)
|
147
|
+
if result is None:
|
148
|
+
raise ValueError(f'Invalid result index: {result_index}')
|
149
|
+
workflow = result.workflow
|
150
|
+
wf = load_workflow(workflow, code_path)
|
151
|
+
if wf is None:
|
152
|
+
raise ValueError(f'Invalid workflow: {workflow}')
|
153
|
+
result = wf.analyze(result, result.previous)
|
154
|
+
if hasattr(wf, 'plot'):
|
155
|
+
wf.plot(result)
|
156
|
+
return result
|
qulab/fun.cp311-win_amd64.pyd
CHANGED
Binary file
|
qulab/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "2.
|
1
|
+
__version__ = "2.6.1"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|