QuLab 2.5.1__cp311-cp311-macosx_10_9_universal2.whl → 2.5.3__cp311-cp311-macosx_10_9_universal2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: QuLab
3
- Version: 2.5.1
3
+ Version: 2.5.3
4
4
  Summary: contral instruments and manage data
5
5
  Author-email: feihoo87 <feihoo87@gmail.com>
6
6
  Maintainer-email: feihoo87 <feihoo87@gmail.com>
@@ -1,17 +1,17 @@
1
1
  qulab/__init__.py,sha256=XnSePkDDgfbmEpu5uXK6spygxaqVt9emMubHYKIjSwc,244
2
2
  qulab/__main__.py,sha256=fjaRSL_uUjNIzBGNgjlGswb9TJ2VD5qnkZHW3hItrD4,68
3
3
  qulab/dicttree.py,sha256=tRRMpGZYVOLw0TEByE3_2Ss8FdOmzuGL9e1DWbs8qoY,13684
4
- qulab/fun.cpython-311-darwin.so,sha256=RXy3TEHNhRnT155GmyOwcFM-gVktlGaICCyoTbi0IAc,126848
4
+ qulab/fun.cpython-311-darwin.so,sha256=_o-zs9ZbzrQF7jkAceBocsxaqiLmkVdxeL3qAaCCHp0,126848
5
5
  qulab/typing.py,sha256=5xCLfrp1aZpKpDy4p2arbFszw2eK3hGUjZa-XSvC_-8,69
6
- qulab/version.py,sha256=LBVD6Y5IKVHVmwynNRJsCm7zBTye77uIsmOVQJQUroE,21
6
+ qulab/version.py,sha256=Znn1LprC8WFThPHcZ2uVYHDtCMP4LIy30e8v1CDWFvU,21
7
7
  qulab/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  qulab/cli/commands.py,sha256=tgDIkkeIoasQXAifJZ6NU8jDgpNgb2a-B0C4nF0evrE,559
9
9
  qulab/cli/config.py,sha256=SdNmWzweWAdyk8M2oKYhMxnkaJ0qIayPlsLGCNlVqME,3108
10
10
  qulab/executor/__init__.py,sha256=LosPzOMaljSZY1thy_Fxtbrgq7uubJszMABEB7oM7tU,101
11
- qulab/executor/cli.py,sha256=owdDSaSuzTPQA5SlNCxX4nHWITU1BF0VZMj7tLqCZhM,5781
12
- qulab/executor/load.py,sha256=i2MKxE5kflAGLt3e9LjME59K7IO7s68EUApP9228LhQ,12125
11
+ qulab/executor/cli.py,sha256=5rbAOnG8Me46qeWh9LbutE3zIcPD-MZVqmYoWUY4l3o,6674
12
+ qulab/executor/load.py,sha256=OZmE_Pj2XcHzRDw5-1lF-ZDoMVqpaR-dWXf1K39ThXQ,12925
13
13
  qulab/executor/schedule.py,sha256=4D8o68Cx6vCkpSTMHzULTwuuq1tS8unc2n8WdBA9oB0,12013
14
- qulab/executor/storage.py,sha256=Ms4euSGrMnFJPwcs70sg5-ZOOm1B6kGULcZOipsFLk4,7242
14
+ qulab/executor/storage.py,sha256=s1xrI4bPTnyM4Nj0CkPxr3NdmnSp18LKnwm-ZoxR-Q0,7191
15
15
  qulab/executor/transform.py,sha256=AazWdlkEoOBaUJpTYsT5J4f0RanzCEeo-ThwEg8BB4Y,1262
16
16
  qulab/executor/utils.py,sha256=RNDEo17M-n_tge7uLITHxmoNNYSTm9OES75wQygR8dM,4065
17
17
  qulab/monitor/__init__.py,sha256=nTHelnDpxRS_fl_B38TsN0njgq8eVTEz9IAnN3NbDlM,42
@@ -93,9 +93,9 @@ qulab/visualization/plot_seq.py,sha256=UWTS6p9nfX_7B8ehcYo6UnSTUCjkBsNU9jiOeW2ca
93
93
  qulab/visualization/qdat.py,sha256=ZeevBYWkzbww4xZnsjHhw7wRorJCBzbG0iEu-XQB4EA,5735
94
94
  qulab/visualization/rot3d.py,sha256=lMrEJlRLwYe6NMBlGkKYpp_V9CTipOAuDy6QW_cQK00,734
95
95
  qulab/visualization/widgets.py,sha256=6KkiTyQ8J-ei70LbPQZAK35wjktY47w2IveOa682ftA,3180
96
- QuLab-2.5.1.dist-info/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
97
- QuLab-2.5.1.dist-info/METADATA,sha256=D1Hfbn_3O29SadX5FYrKdMC4KywT_izEWppHG1CSWbI,3698
98
- QuLab-2.5.1.dist-info/WHEEL,sha256=K10eKSN6_vzvMOgXxWbVOQNR7Orfl6gBTCpCI8bcYx4,114
99
- QuLab-2.5.1.dist-info/entry_points.txt,sha256=b0v1GXOwmxY-nCCsPN_rHZZvY9CtTbWqrGj8u1m8yHo,45
100
- QuLab-2.5.1.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
101
- QuLab-2.5.1.dist-info/RECORD,,
96
+ QuLab-2.5.3.dist-info/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
97
+ QuLab-2.5.3.dist-info/METADATA,sha256=3Q3eK40_NlhnO2IeI2Ok-tPG7aEkDMQWj88cKwErDR0,3698
98
+ QuLab-2.5.3.dist-info/WHEEL,sha256=K10eKSN6_vzvMOgXxWbVOQNR7Orfl6gBTCpCI8bcYx4,114
99
+ QuLab-2.5.3.dist-info/entry_points.txt,sha256=b0v1GXOwmxY-nCCsPN_rHZZvY9CtTbWqrGj8u1m8yHo,45
100
+ QuLab-2.5.3.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
101
+ QuLab-2.5.3.dist-info/RECORD,,
qulab/executor/cli.py CHANGED
@@ -1,20 +1,35 @@
1
1
  import functools
2
+ import graphlib
2
3
  import importlib
3
4
  import os
4
- import sys
5
5
  from pathlib import Path
6
6
 
7
7
  import click
8
8
  from loguru import logger
9
9
 
10
- from ..cli.config import ENV_PREFIX, get_config_value, log_options
11
- from .load import find_unreferenced_workflows, get_entries, load_workflow
10
+ from ..cli.config import get_config_value, log_options
11
+ from .load import (WorkflowType, find_unreferenced_workflows, get_entries,
12
+ load_workflow, make_graph)
12
13
  from .schedule import maintain as maintain_workflow
13
14
  from .schedule import run as run_workflow
14
15
  from .transform import set_config_api
15
16
  from .utils import workflow_template
16
17
 
17
18
 
19
+ @logger.catch(reraise=True)
20
+ def check_toplogy(workflow: WorkflowType, code_path: str | Path) -> dict:
21
+ graph = {}
22
+ try:
23
+ graphlib.TopologicalSorter(make_graph(workflow, graph,
24
+ code_path)).static_order()
25
+ except graphlib.CycleError as e:
26
+ logger.error(
27
+ f"Workflow {workflow.__workflow_id__} has a circular dependency: {e}"
28
+ )
29
+ raise e
30
+ return graph
31
+
32
+
18
33
  def command_option(command_name):
19
34
  """命令专属配置装饰器工厂"""
20
35
 
@@ -142,6 +157,7 @@ def run(workflow, code, data, api, plot, no_dependents, update):
142
157
  data = Path(os.path.expanduser(data))
143
158
 
144
159
  wf = load_workflow(workflow, code)
160
+ check_toplogy(wf, code)
145
161
 
146
162
  if no_dependents:
147
163
  if hasattr(wf, 'entries'):
@@ -152,9 +168,19 @@ def run(workflow, code, data, api, plot, no_dependents, update):
152
168
  else:
153
169
  if hasattr(wf, 'entries'):
154
170
  for entry in get_entries(wf, code):
155
- maintain_workflow(entry, code, data, run=True, plot=plot, update=update)
171
+ maintain_workflow(entry,
172
+ code,
173
+ data,
174
+ run=True,
175
+ plot=plot,
176
+ update=update)
156
177
  else:
157
- maintain_workflow(wf, code, data, run=True, plot=plot, update=update)
178
+ maintain_workflow(wf,
179
+ code,
180
+ data,
181
+ run=True,
182
+ plot=plot,
183
+ update=update)
158
184
 
159
185
 
160
186
  @click.command()
@@ -181,6 +207,8 @@ def maintain(workflow, code, data, api, plot):
181
207
  data = Path(os.path.expanduser(data))
182
208
 
183
209
  wf = load_workflow(workflow, code)
210
+ check_toplogy(wf, code)
211
+
184
212
  if hasattr(wf, 'entries'):
185
213
  for entry in get_entries(wf, code):
186
214
  maintain_workflow(entry, code, data, run=False, plot=plot)
qulab/executor/load.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import base64
2
+ import graphlib
2
3
  import hashlib
3
4
  import inspect
4
5
  import lzma
@@ -259,7 +260,7 @@ def load_workflow_from_template(template_path: str,
259
260
  with open(base_path / path) as f:
260
261
  content = f.read()
261
262
 
262
- mtime = max(Path(template_path).stat().st_mtime, mtime)
263
+ mtime = max((base_path / template_path).stat().st_mtime, mtime)
263
264
  hash_str, mapping_code = encode_mapping(mapping)
264
265
 
265
266
  def replace(text):
@@ -360,8 +361,27 @@ def get_dependents(workflow: WorkflowType,
360
361
  ]
361
362
 
362
363
 
363
- def get_entries(workflow: WorkflowType, code_path: str | Path) -> WorkflowType:
364
+ def get_entries(workflow: WorkflowType,
365
+ code_path: str | Path) -> list[WorkflowType]:
364
366
  return [
365
367
  load_workflow(n, code_path, mtime=workflow.__mtime__)
366
368
  for n in workflow.entries()
367
369
  ]
370
+
371
+
372
+ def make_graph(workflow: WorkflowType, graph: dict, code_path: str | Path):
373
+ if workflow.__workflow_id__ in graph:
374
+ raise graphlib.CycleError(
375
+ f"Workflow {workflow.__workflow_id__} has a circular dependency")
376
+ graph[workflow.__workflow_id__] = []
377
+
378
+ if hasattr(workflow, 'entries'):
379
+ for w in get_entries(workflow, code_path):
380
+ graph[workflow.__workflow_id__].append(w.__workflow_id__)
381
+ make_graph(w, graph=graph, code_path=code_path)
382
+ elif hasattr(workflow, 'depends'):
383
+ for w in get_dependents(workflow, code_path):
384
+ graph[workflow.__workflow_id__].append(w.__workflow_id__)
385
+ make_graph(w, graph=graph, code_path=code_path)
386
+
387
+ return graph
qulab/executor/storage.py CHANGED
@@ -140,8 +140,7 @@ def revoke_result(workflow: str, base_path: str | Path):
140
140
  base_path = Path(base_path)
141
141
  path = get_head(workflow, base_path)
142
142
  if path is not None:
143
- with open(base_path / 'objects' / path, "rb") as f:
144
- result = pickle.load(f)
143
+ result = load_result(path, base_path)
145
144
  result.in_spec = False
146
145
  return save_result(workflow, result, base_path)
147
146
 
Binary file
qulab/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "2.5.1"
1
+ __version__ = "2.5.3"
File without changes
File without changes