QuLab 2.5.2__tar.gz → 2.5.4__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.
Files changed (111) hide show
  1. {qulab-2.5.2 → qulab-2.5.4}/PKG-INFO +1 -1
  2. {qulab-2.5.2 → qulab-2.5.4}/QuLab.egg-info/PKG-INFO +1 -1
  3. {qulab-2.5.2 → qulab-2.5.4}/qulab/executor/cli.py +34 -6
  4. {qulab-2.5.2 → qulab-2.5.4}/qulab/executor/load.py +62 -10
  5. {qulab-2.5.2 → qulab-2.5.4}/qulab/executor/schedule.py +8 -0
  6. {qulab-2.5.2 → qulab-2.5.4}/qulab/executor/utils.py +7 -5
  7. qulab-2.5.4/qulab/version.py +1 -0
  8. qulab-2.5.2/qulab/version.py +0 -1
  9. {qulab-2.5.2 → qulab-2.5.4}/LICENSE +0 -0
  10. {qulab-2.5.2 → qulab-2.5.4}/MANIFEST.in +0 -0
  11. {qulab-2.5.2 → qulab-2.5.4}/QuLab.egg-info/SOURCES.txt +0 -0
  12. {qulab-2.5.2 → qulab-2.5.4}/QuLab.egg-info/dependency_links.txt +0 -0
  13. {qulab-2.5.2 → qulab-2.5.4}/QuLab.egg-info/entry_points.txt +0 -0
  14. {qulab-2.5.2 → qulab-2.5.4}/QuLab.egg-info/requires.txt +0 -0
  15. {qulab-2.5.2 → qulab-2.5.4}/QuLab.egg-info/top_level.txt +0 -0
  16. {qulab-2.5.2 → qulab-2.5.4}/README.md +0 -0
  17. {qulab-2.5.2 → qulab-2.5.4}/pyproject.toml +0 -0
  18. {qulab-2.5.2 → qulab-2.5.4}/qulab/__init__.py +0 -0
  19. {qulab-2.5.2 → qulab-2.5.4}/qulab/__main__.py +0 -0
  20. {qulab-2.5.2 → qulab-2.5.4}/qulab/cli/__init__.py +0 -0
  21. {qulab-2.5.2 → qulab-2.5.4}/qulab/cli/commands.py +0 -0
  22. {qulab-2.5.2 → qulab-2.5.4}/qulab/cli/config.py +0 -0
  23. {qulab-2.5.2 → qulab-2.5.4}/qulab/dicttree.py +0 -0
  24. {qulab-2.5.2 → qulab-2.5.4}/qulab/executor/__init__.py +0 -0
  25. {qulab-2.5.2 → qulab-2.5.4}/qulab/executor/storage.py +0 -0
  26. {qulab-2.5.2 → qulab-2.5.4}/qulab/executor/transform.py +0 -0
  27. {qulab-2.5.2 → qulab-2.5.4}/qulab/monitor/__init__.py +0 -0
  28. {qulab-2.5.2 → qulab-2.5.4}/qulab/monitor/__main__.py +0 -0
  29. {qulab-2.5.2 → qulab-2.5.4}/qulab/monitor/config.py +0 -0
  30. {qulab-2.5.2 → qulab-2.5.4}/qulab/monitor/dataset.py +0 -0
  31. {qulab-2.5.2 → qulab-2.5.4}/qulab/monitor/event_queue.py +0 -0
  32. {qulab-2.5.2 → qulab-2.5.4}/qulab/monitor/mainwindow.py +0 -0
  33. {qulab-2.5.2 → qulab-2.5.4}/qulab/monitor/monitor.py +0 -0
  34. {qulab-2.5.2 → qulab-2.5.4}/qulab/monitor/ploter.py +0 -0
  35. {qulab-2.5.2 → qulab-2.5.4}/qulab/monitor/qt_compat.py +0 -0
  36. {qulab-2.5.2 → qulab-2.5.4}/qulab/monitor/toolbar.py +0 -0
  37. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/__init__.py +0 -0
  38. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/curd.py +0 -0
  39. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/expression.py +0 -0
  40. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/models.py +0 -0
  41. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/optimize.py +0 -0
  42. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/query.py +0 -0
  43. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/record.py +0 -0
  44. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/scan.py +0 -0
  45. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/server.py +0 -0
  46. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/space.py +0 -0
  47. {qulab-2.5.2 → qulab-2.5.4}/qulab/scan/utils.py +0 -0
  48. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/__init__.py +0 -0
  49. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/__main__.py +0 -0
  50. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/backend/__init__.py +0 -0
  51. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/backend/redis.py +0 -0
  52. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/base_dataset.py +0 -0
  53. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/chunk.py +0 -0
  54. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/dataset.py +0 -0
  55. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/file.py +0 -0
  56. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/models/__init__.py +0 -0
  57. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/models/base.py +0 -0
  58. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/models/config.py +0 -0
  59. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/models/file.py +0 -0
  60. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/models/ipy.py +0 -0
  61. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/models/models.py +0 -0
  62. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/models/record.py +0 -0
  63. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/models/report.py +0 -0
  64. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/models/tag.py +0 -0
  65. {qulab-2.5.2 → qulab-2.5.4}/qulab/storage/storage.py +0 -0
  66. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/__init__.py +0 -0
  67. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/chat.py +0 -0
  68. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/device/__init__.py +0 -0
  69. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/device/basedevice.py +0 -0
  70. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/device/loader.py +0 -0
  71. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/device/utils.py +0 -0
  72. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/drivers/FakeInstrument.py +0 -0
  73. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/drivers/__init__.py +0 -0
  74. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/ipy_events.py +0 -0
  75. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/net/__init__.py +0 -0
  76. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/net/bencoder.py +0 -0
  77. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/net/cli.py +0 -0
  78. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/net/dhcp.py +0 -0
  79. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/net/dhcpd.py +0 -0
  80. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/net/kad.py +0 -0
  81. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/net/kcp.py +0 -0
  82. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/net/nginx.py +0 -0
  83. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/progress.py +0 -0
  84. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/__init__.py +0 -0
  85. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/client.py +0 -0
  86. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/exceptions.py +0 -0
  87. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/msgpack.py +0 -0
  88. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/msgpack.pyi +0 -0
  89. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/router.py +0 -0
  90. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/rpc.py +0 -0
  91. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/serialize.py +0 -0
  92. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/server.py +0 -0
  93. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/socket.py +0 -0
  94. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/utils.py +0 -0
  95. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/worker.py +0 -0
  96. {qulab-2.5.2 → qulab-2.5.4}/qulab/sys/rpc/zmq_socket.py +0 -0
  97. {qulab-2.5.2 → qulab-2.5.4}/qulab/typing.py +0 -0
  98. {qulab-2.5.2 → qulab-2.5.4}/qulab/visualization/__init__.py +0 -0
  99. {qulab-2.5.2 → qulab-2.5.4}/qulab/visualization/__main__.py +0 -0
  100. {qulab-2.5.2 → qulab-2.5.4}/qulab/visualization/_autoplot.py +0 -0
  101. {qulab-2.5.2 → qulab-2.5.4}/qulab/visualization/plot_circ.py +0 -0
  102. {qulab-2.5.2 → qulab-2.5.4}/qulab/visualization/plot_layout.py +0 -0
  103. {qulab-2.5.2 → qulab-2.5.4}/qulab/visualization/plot_seq.py +0 -0
  104. {qulab-2.5.2 → qulab-2.5.4}/qulab/visualization/qdat.py +0 -0
  105. {qulab-2.5.2 → qulab-2.5.4}/qulab/visualization/rot3d.py +0 -0
  106. {qulab-2.5.2 → qulab-2.5.4}/qulab/visualization/widgets.py +0 -0
  107. {qulab-2.5.2 → qulab-2.5.4}/setup.cfg +0 -0
  108. {qulab-2.5.2 → qulab-2.5.4}/setup.py +0 -0
  109. {qulab-2.5.2 → qulab-2.5.4}/src/qulab.h +0 -0
  110. {qulab-2.5.2 → qulab-2.5.4}/tests/test_kad.py +0 -0
  111. {qulab-2.5.2 → qulab-2.5.4}/tests/test_scan.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: QuLab
3
- Version: 2.5.2
3
+ Version: 2.5.4
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,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: QuLab
3
- Version: 2.5.2
3
+ Version: 2.5.4
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,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
 
@@ -68,7 +83,7 @@ def create(workflow, code):
68
83
  deps = find_unreferenced_workflows(code)
69
84
 
70
85
  with open(fname, 'w') as f:
71
- f.write(workflow_template(list(deps)))
86
+ f.write(workflow_template(workflow, list(deps)))
72
87
  click.echo(f'{workflow} created')
73
88
 
74
89
 
@@ -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)
@@ -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):
@@ -354,14 +355,65 @@ def load_workflow(workflow: str | tuple[str, dict],
354
355
 
355
356
  def get_dependents(workflow: WorkflowType,
356
357
  code_path: str | Path) -> list[WorkflowType]:
357
- return [
358
- load_workflow(n, code_path, mtime=workflow.__mtime__)
359
- for n in workflow.depends()
360
- ]
358
+ if callable(getattr(workflow, 'depends', None)):
359
+ if not can_call_without_args(workflow.depends):
360
+ raise AttributeError(
361
+ f'Workflow {workflow.__workflow_id__} "depends" function should not have any parameters'
362
+ )
363
+ return [
364
+ load_workflow(n, code_path, mtime=workflow.__mtime__)
365
+ for n in workflow.depends()
366
+ ]
367
+ elif isinstance(getattr(workflow, 'depends', None), (list, tuple)):
368
+ return [
369
+ load_workflow(n, code_path, mtime=workflow.__mtime__)
370
+ for n in workflow.depends
371
+ ]
372
+ elif getattr(workflow, 'entries', None) is None:
373
+ return []
374
+ else:
375
+ raise AttributeError(
376
+ f'Workflow {workflow.__workflow_id__} "depends" should be a callable or a list'
377
+ )
361
378
 
362
379
 
363
- def get_entries(workflow: WorkflowType, code_path: str | Path) -> WorkflowType:
364
- return [
365
- load_workflow(n, code_path, mtime=workflow.__mtime__)
366
- for n in workflow.entries()
367
- ]
380
+ def get_entries(workflow: WorkflowType,
381
+ code_path: str | Path) -> list[WorkflowType]:
382
+ if callable(getattr(workflow, 'entries', None)):
383
+ if not can_call_without_args(workflow.entries):
384
+ raise AttributeError(
385
+ f'Workflow {workflow.__workflow_id__} "entries" function should not have any parameters'
386
+ )
387
+ return [
388
+ load_workflow(n, code_path, mtime=workflow.__mtime__)
389
+ for n in workflow.entries()
390
+ ]
391
+ elif isinstance(getattr(workflow, 'entries', None), (list, tuple)):
392
+ return [
393
+ load_workflow(n, code_path, mtime=workflow.__mtime__)
394
+ for n in workflow.entries
395
+ ]
396
+ elif getattr(workflow, 'entries', None) is None:
397
+ return []
398
+ else:
399
+ raise AttributeError(
400
+ f'Workflow {workflow.__workflow_id__} "entries" should be a callable or a list'
401
+ )
402
+
403
+
404
+ def make_graph(workflow: WorkflowType, graph: dict, code_path: str | Path):
405
+ if workflow.__workflow_id__ in graph:
406
+ raise graphlib.CycleError(
407
+ f"Workflow {workflow.__workflow_id__} has a circular dependency")
408
+ graph[workflow.__workflow_id__] = []
409
+
410
+ if hasattr(workflow, 'entries'):
411
+ for w in get_entries(workflow, code_path):
412
+ graph[workflow.__workflow_id__].append(w.__workflow_id__)
413
+ make_graph(w, graph=graph, code_path=code_path)
414
+ elif hasattr(workflow, 'depends'):
415
+ for w in get_dependents(workflow, code_path):
416
+ graph[workflow.__workflow_id__].append(w.__workflow_id__)
417
+ make_graph(w, graph=graph, code_path=code_path)
418
+
419
+ return graph
@@ -73,9 +73,17 @@ def call_analyzer(node,
73
73
  plot=False) -> Result:
74
74
  if check:
75
75
  result = node.check_analyze(result, history=history)
76
+ if not isinstance(result, Result):
77
+ raise TypeError(
78
+ f'"{node.__workflow_id__}" : "check_analyze" must return a Result object'
79
+ )
76
80
  result.fully_calibrated = False
77
81
  else:
78
82
  result = node.analyze(result, history=history)
83
+ if not isinstance(result, Result):
84
+ raise TypeError(
85
+ f'"{node.__workflow_id__}" : "analyze" must return a Result object'
86
+ )
79
87
  result.fully_calibrated = True
80
88
  if plot:
81
89
  call_plot(node, result)
@@ -30,7 +30,7 @@ def dependent_tree(node: str, code_path: str | Path) -> dict[str, list[str]]:
30
30
  return tree
31
31
 
32
32
 
33
- def workflow_template(deps: list[str]) -> str:
33
+ def workflow_template(workflow: str, deps: list[str]) -> str:
34
34
  return f"""def VAR(s): pass # 没有实际作用,只是用来抑制编辑器的警告。
35
35
 
36
36
  import numpy as np
@@ -47,7 +47,7 @@ def depends():
47
47
 
48
48
 
49
49
  def calibrate():
50
- logger.info(f"run {{__name__}}")
50
+ logger.info(f"running {workflow} ...")
51
51
 
52
52
  # calibrate 是一个完整的校准实验,如power Rabi,Ramsey等。
53
53
  # 你需要足够的扫描点,以使得后续的 analyze 可以拟合出合适的参数。
@@ -58,10 +58,11 @@ def calibrate():
58
58
  for i in x:
59
59
  y.append(np.sin(i))
60
60
 
61
+ logger.info(f"running {workflow} ... finished!")
61
62
  return x, y
62
63
 
63
64
 
64
- def analyze(result: Result, history: Result | None) -> Result:
65
+ def analyze(result: Result, history: Result | None = None) -> Result:
65
66
  \"\"\"
66
67
  分析校准结果。
67
68
 
@@ -93,7 +94,7 @@ def analyze(result: Result, history: Result | None) -> Result:
93
94
 
94
95
 
95
96
  def check():
96
- logger.info(f"check {{__name__}}")
97
+ logger.info(f"checking {workflow} ...")
97
98
 
98
99
  # check 是一个快速检查实验,用于检查校准是否过时。
99
100
  # 你只需要少数扫描点,让后续的 check_analyze 知道参数是否漂移,数据
@@ -105,10 +106,11 @@ def check():
105
106
  for i in x:
106
107
  y.append(np.sin(i))
107
108
 
109
+ logger.info(f"checking {workflow} ... finished!")
108
110
  return x, y
109
111
 
110
112
 
111
- def check_analyze(result: Result, history: Result) -> Result:
113
+ def check_analyze(result: Result, history: Result | None = None) -> Result:
112
114
  \"\"\"
113
115
  分析检查结果。
114
116
 
@@ -0,0 +1 @@
1
+ __version__ = "2.5.4"
@@ -1 +0,0 @@
1
- __version__ = "2.5.2"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes