QuLab 2.10.10__cp313-cp313-macosx_10_13_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.
Files changed (107) hide show
  1. qulab/__init__.py +33 -0
  2. qulab/__main__.py +4 -0
  3. qulab/cli/__init__.py +0 -0
  4. qulab/cli/commands.py +30 -0
  5. qulab/cli/config.py +170 -0
  6. qulab/cli/decorators.py +28 -0
  7. qulab/dicttree.py +523 -0
  8. qulab/executor/__init__.py +5 -0
  9. qulab/executor/analyze.py +188 -0
  10. qulab/executor/cli.py +434 -0
  11. qulab/executor/load.py +563 -0
  12. qulab/executor/registry.py +185 -0
  13. qulab/executor/schedule.py +543 -0
  14. qulab/executor/storage.py +615 -0
  15. qulab/executor/template.py +259 -0
  16. qulab/executor/utils.py +194 -0
  17. qulab/expression.py +827 -0
  18. qulab/fun.cpython-313-darwin.so +0 -0
  19. qulab/monitor/__init__.py +1 -0
  20. qulab/monitor/__main__.py +8 -0
  21. qulab/monitor/config.py +41 -0
  22. qulab/monitor/dataset.py +77 -0
  23. qulab/monitor/event_queue.py +54 -0
  24. qulab/monitor/mainwindow.py +234 -0
  25. qulab/monitor/monitor.py +115 -0
  26. qulab/monitor/ploter.py +123 -0
  27. qulab/monitor/qt_compat.py +16 -0
  28. qulab/monitor/toolbar.py +265 -0
  29. qulab/scan/__init__.py +2 -0
  30. qulab/scan/curd.py +221 -0
  31. qulab/scan/models.py +554 -0
  32. qulab/scan/optimize.py +76 -0
  33. qulab/scan/query.py +387 -0
  34. qulab/scan/record.py +603 -0
  35. qulab/scan/scan.py +1166 -0
  36. qulab/scan/server.py +450 -0
  37. qulab/scan/space.py +213 -0
  38. qulab/scan/utils.py +234 -0
  39. qulab/storage/__init__.py +0 -0
  40. qulab/storage/__main__.py +51 -0
  41. qulab/storage/backend/__init__.py +0 -0
  42. qulab/storage/backend/redis.py +204 -0
  43. qulab/storage/base_dataset.py +352 -0
  44. qulab/storage/chunk.py +60 -0
  45. qulab/storage/dataset.py +127 -0
  46. qulab/storage/file.py +273 -0
  47. qulab/storage/models/__init__.py +22 -0
  48. qulab/storage/models/base.py +4 -0
  49. qulab/storage/models/config.py +28 -0
  50. qulab/storage/models/file.py +89 -0
  51. qulab/storage/models/ipy.py +58 -0
  52. qulab/storage/models/models.py +88 -0
  53. qulab/storage/models/record.py +161 -0
  54. qulab/storage/models/report.py +22 -0
  55. qulab/storage/models/tag.py +93 -0
  56. qulab/storage/storage.py +95 -0
  57. qulab/sys/__init__.py +2 -0
  58. qulab/sys/chat.py +688 -0
  59. qulab/sys/device/__init__.py +3 -0
  60. qulab/sys/device/basedevice.py +255 -0
  61. qulab/sys/device/loader.py +86 -0
  62. qulab/sys/device/utils.py +79 -0
  63. qulab/sys/drivers/FakeInstrument.py +68 -0
  64. qulab/sys/drivers/__init__.py +0 -0
  65. qulab/sys/ipy_events.py +125 -0
  66. qulab/sys/net/__init__.py +0 -0
  67. qulab/sys/net/bencoder.py +205 -0
  68. qulab/sys/net/cli.py +169 -0
  69. qulab/sys/net/dhcp.py +543 -0
  70. qulab/sys/net/dhcpd.py +176 -0
  71. qulab/sys/net/kad.py +1142 -0
  72. qulab/sys/net/kcp.py +192 -0
  73. qulab/sys/net/nginx.py +194 -0
  74. qulab/sys/progress.py +190 -0
  75. qulab/sys/rpc/__init__.py +0 -0
  76. qulab/sys/rpc/client.py +0 -0
  77. qulab/sys/rpc/exceptions.py +96 -0
  78. qulab/sys/rpc/msgpack.py +1052 -0
  79. qulab/sys/rpc/msgpack.pyi +41 -0
  80. qulab/sys/rpc/router.py +35 -0
  81. qulab/sys/rpc/rpc.py +412 -0
  82. qulab/sys/rpc/serialize.py +139 -0
  83. qulab/sys/rpc/server.py +29 -0
  84. qulab/sys/rpc/socket.py +29 -0
  85. qulab/sys/rpc/utils.py +25 -0
  86. qulab/sys/rpc/worker.py +0 -0
  87. qulab/sys/rpc/zmq_socket.py +227 -0
  88. qulab/tools/__init__.py +0 -0
  89. qulab/tools/connection_helper.py +39 -0
  90. qulab/typing.py +2 -0
  91. qulab/utils.py +95 -0
  92. qulab/version.py +1 -0
  93. qulab/visualization/__init__.py +188 -0
  94. qulab/visualization/__main__.py +71 -0
  95. qulab/visualization/_autoplot.py +464 -0
  96. qulab/visualization/plot_circ.py +319 -0
  97. qulab/visualization/plot_layout.py +408 -0
  98. qulab/visualization/plot_seq.py +242 -0
  99. qulab/visualization/qdat.py +152 -0
  100. qulab/visualization/rot3d.py +23 -0
  101. qulab/visualization/widgets.py +86 -0
  102. qulab-2.10.10.dist-info/METADATA +110 -0
  103. qulab-2.10.10.dist-info/RECORD +107 -0
  104. qulab-2.10.10.dist-info/WHEEL +5 -0
  105. qulab-2.10.10.dist-info/entry_points.txt +2 -0
  106. qulab-2.10.10.dist-info/licenses/LICENSE +21 -0
  107. qulab-2.10.10.dist-info/top_level.txt +1 -0
qulab/scan/utils.py ADDED
@@ -0,0 +1,234 @@
1
+ import ast
2
+ import asyncio
3
+ import inspect
4
+ import platform
5
+ import re
6
+ import subprocess
7
+ import sys
8
+ import uuid
9
+ import warnings
10
+ from typing import Any, Callable
11
+
12
+ import dill
13
+
14
+ from ..expression import Env, Expression
15
+
16
+
17
+ class Unpicklable:
18
+
19
+ def __init__(self, obj):
20
+ self.type = str(type(obj))
21
+ self.id = id(obj)
22
+
23
+ def __repr__(self):
24
+ return f'<Unpicklable: {self.type} at 0x{id(self):x}>'
25
+
26
+
27
+ class TooLarge:
28
+
29
+ def __init__(self, obj):
30
+ self.type = str(type(obj))
31
+ self.id = id(obj)
32
+
33
+ def __repr__(self):
34
+ return f'<TooLarge: {self.type} at 0x{id(self):x}>'
35
+
36
+
37
+ def dump_dict(d, keys=[]):
38
+ ret = {}
39
+
40
+ for key, value in d.items():
41
+ if key in keys:
42
+ ret[key] = value
43
+ continue
44
+ if isinstance(value, dict) and isinstance(key, str):
45
+ ret[key] = dump_dict(value,
46
+ keys=[
47
+ k[len(key) + 1:] for k in keys
48
+ if k.startswith(f'{key}.')
49
+ ])
50
+ else:
51
+ try:
52
+ ret[key] = dill.dumps(value)
53
+ except:
54
+ ret[key] = Unpicklable(value)
55
+
56
+ return dill.dumps(ret)
57
+
58
+
59
+ def load_dict(buff):
60
+ if isinstance(buff, dict):
61
+ return {key: load_dict(value) for key, value in buff.items()}
62
+
63
+ if not isinstance(buff, bytes):
64
+ return buff
65
+
66
+ try:
67
+ ret = dill.loads(buff)
68
+ except:
69
+ return buff
70
+
71
+ if isinstance(ret, dict):
72
+ return load_dict(ret)
73
+ else:
74
+ return ret
75
+
76
+
77
+ def dump_globals(ns=None, *, size_limit=10 * 1024 * 1024, warn=False):
78
+ import __main__
79
+
80
+ if ns is None:
81
+ ns = __main__.__dict__
82
+
83
+ namespace = {}
84
+
85
+ for name, value in ns.items():
86
+ try:
87
+ buf = dill.dumps(value)
88
+ except:
89
+ namespace[name] = Unpicklable(value)
90
+ if warn:
91
+ warnings.warn(f'Unpicklable: {name} {type(value)}')
92
+ if len(buf) > size_limit:
93
+ namespace[name] = TooLarge(value)
94
+ if warn:
95
+ warnings.warn(f'TooLarge: {name} {type(value)}')
96
+ else:
97
+ namespace[name] = buf
98
+
99
+ return namespace
100
+
101
+
102
+ def is_valid_identifier(s: str) -> bool:
103
+ """
104
+ Check if a string is a valid identifier.
105
+ """
106
+ try:
107
+ ast.parse(f"f({s}=0)")
108
+ return True
109
+ except SyntaxError:
110
+ return False
111
+
112
+
113
+ async def async_next(aiter):
114
+ try:
115
+ if hasattr(aiter, '__anext__'):
116
+ return await aiter.__anext__()
117
+ else:
118
+ return next(aiter)
119
+ except StopIteration:
120
+ raise StopAsyncIteration from None
121
+
122
+
123
+ async def async_zip(*aiters):
124
+ aiters = [
125
+ ait.__aiter__() if hasattr(ait, '__aiter__') else iter(ait)
126
+ for ait in aiters
127
+ ]
128
+ try:
129
+ while True:
130
+ # 使用 asyncio.gather 等待所有异步生成器返回下一个元素
131
+ result = await asyncio.gather(*(async_next(ait) for ait in aiters))
132
+ yield tuple(result)
133
+ except StopAsyncIteration:
134
+ # 当任一异步生成器耗尽时停止迭代
135
+ return
136
+
137
+
138
+ async def call_function(func: Callable | Expression, variables: dict[str,
139
+ Any]):
140
+ if isinstance(func, Expression):
141
+ env = Env()
142
+ for name in func.symbols():
143
+ if name in variables:
144
+ if inspect.isawaitable(variables[name]):
145
+ variables[name] = await variables[name]
146
+ env.variables[name] = variables[name]
147
+ else:
148
+ raise ValueError(f'{name} is not provided.')
149
+ return func.eval(env)
150
+
151
+ try:
152
+ sig = inspect.signature(func)
153
+ except:
154
+ return func()
155
+ args = []
156
+ for name, param in sig.parameters.items():
157
+ if param.kind == param.POSITIONAL_OR_KEYWORD:
158
+ if name in variables:
159
+ if inspect.isawaitable(variables[name]):
160
+ variables[name] = await variables[name]
161
+ args.append(variables[name])
162
+ elif param.default is not param.empty:
163
+ args.append(param.default)
164
+ else:
165
+ raise ValueError(f'parameter {name} is not provided.')
166
+ elif param.kind == param.VAR_POSITIONAL:
167
+ raise ValueError('not support VAR_POSITIONAL')
168
+ elif param.kind == param.VAR_KEYWORD:
169
+ ret = func(**variables)
170
+ if inspect.isawaitable(ret):
171
+ ret = await ret
172
+ return ret
173
+ ret = func(*args)
174
+ if inspect.isawaitable(ret):
175
+ ret = await ret
176
+ return ret
177
+
178
+
179
+ def yapf_reformat(cell_text):
180
+ try:
181
+ import isort
182
+ import yapf.yapflib.yapf_api
183
+
184
+ fname = f"f{uuid.uuid1().hex}"
185
+
186
+ def wrap(source):
187
+ lines = [f"async def {fname}():"]
188
+ for line in source.split('\n'):
189
+ lines.append(" " + line)
190
+ return '\n'.join(lines)
191
+
192
+ def unwrap(source):
193
+ lines = []
194
+ for line in source.split('\n'):
195
+ if line.startswith(f"async def {fname}():"):
196
+ continue
197
+ lines.append(line[4:])
198
+ return '\n'.join(lines)
199
+
200
+ cell_text = re.sub('^%', '#%#', cell_text, flags=re.M)
201
+ try:
202
+ reformated_text = yapf.yapflib.yapf_api.FormatCode(
203
+ isort.code(cell_text))[0]
204
+ except:
205
+ reformated_text = unwrap(
206
+ yapf.yapflib.yapf_api.FormatCode(wrap(
207
+ isort.code(cell_text)))[0])
208
+ return re.sub('^#%#', '%', reformated_text, flags=re.M)
209
+ except:
210
+ return cell_text
211
+
212
+
213
+ def get_installed_packages():
214
+ result = subprocess.run([sys.executable, '-m', 'pip', 'freeze'],
215
+ stdout=subprocess.PIPE,
216
+ text=True)
217
+
218
+ lines = result.stdout.split('\n')
219
+ packages = []
220
+ for line in lines:
221
+ if line:
222
+ packages.append(line)
223
+ return packages
224
+
225
+
226
+ def get_system_info():
227
+ info = {
228
+ 'OS': platform.uname()._asdict(),
229
+ 'Python': sys.version,
230
+ 'PythonExecutable': sys.executable,
231
+ 'PythonPath': sys.path,
232
+ 'packages': get_installed_packages()
233
+ }
234
+ return info
File without changes
@@ -0,0 +1,51 @@
1
+ import click
2
+
3
+
4
+ @click.command()
5
+ @click.option('--executor', default='', help='Executor address to use.')
6
+ @click.option('--port', default=8080, help='Port to run the server on.')
7
+ @click.option('--host', default='127.0.0.1', help='Host to run the server on.')
8
+ @click.option('--db-url', default=None, help='Database URL to use.')
9
+ @click.option('--data-path',
10
+ default='waveforms/data',
11
+ help='Path to the data directory.')
12
+ @click.option('--debug', is_flag=True, help='Run in debug mode.')
13
+ @click.option('--workers',
14
+ default=1,
15
+ help='Number of workers to run the server with.')
16
+ @click.option('--timeout', default=60, help='Timeout for requests.')
17
+ @click.option('--log-level',
18
+ default='INFO',
19
+ help='Log level to run the server with.')
20
+ @click.option('--log-file',
21
+ default='/var/log/waveforms/server.log',
22
+ help='Log file to run the server with.')
23
+ @click.option('--log-format',
24
+ default='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
25
+ help='Log format to run the server with.')
26
+ def main(executor, port, host, db_url, data_path, debug, workers, timeout,
27
+ log_level, log_file, log_format):
28
+ """
29
+ Main entry point for the server.
30
+ """
31
+ from waveforms.server import create_app
32
+
33
+ app = create_app(
34
+ executor=executor,
35
+ port=port,
36
+ host=host,
37
+ db_url=db_url,
38
+ data_path=data_path,
39
+ debug=debug,
40
+ workers=workers,
41
+ timeout=timeout,
42
+ log_level=log_level,
43
+ log_file=log_file,
44
+ log_format=log_format,
45
+ )
46
+ app.run()
47
+
48
+
49
+ if __name__ == '__main__':
50
+ main()
51
+
File without changes
@@ -0,0 +1,204 @@
1
+ import dill
2
+ import numpy as np
3
+ import redis
4
+
5
+
6
+ def try_dumps(value):
7
+ try:
8
+ value_b = dill.dumps(value)
9
+ except:
10
+ value_b = dill.dumps(str(value))
11
+ finally:
12
+ return value_b
13
+
14
+
15
+ class redisClient(object):
16
+
17
+ def __init__(self,
18
+ name,
19
+ server=None,
20
+ addr='redis://localhost:6379/0',
21
+ expire_time=172800):
22
+ self._r = redis.Redis.from_url(addr) if server is None else server
23
+ self.name = name
24
+ self.expire_time = int(expire_time) # 默认数据两天过期,单位秒
25
+
26
+ def delete(self):
27
+ self._r.delete(self.name)
28
+
29
+
30
+ class redisString(redisClient):
31
+ '''Redis String client'''
32
+
33
+ def set(self, value):
34
+ if value is not None:
35
+ value_b = try_dumps(value)
36
+ self._r.set(self.name, value_b, ex=self.expire_time)
37
+
38
+ def get(self):
39
+ v_b = self._r.get(self.name)
40
+ value = dill.loads(v_b) if v_b is not None else None
41
+ return value
42
+
43
+ @property
44
+ def data(self):
45
+ return self.get()
46
+
47
+
48
+ class redisList(redisClient):
49
+ '''Redis List client'''
50
+
51
+ def add(self, *arg):
52
+ arg_b = [dill.dumps(i) for i in arg]
53
+ self._r.rpush(self.name, *arg_b)
54
+ self._r.expire(self.name, self.expire_time)
55
+
56
+ def read(self, start=0, end=-1):
57
+ data_b = self._r.lrange(self.name, start, end)
58
+ data = [dill.loads(i) for i in data_b]
59
+ return data
60
+
61
+ @property
62
+ def size(self):
63
+ return self._r.llen(self.name)
64
+
65
+ @property
66
+ def data(self):
67
+ return self.read()
68
+
69
+
70
+ class redisSet(redisClient):
71
+ '''Redis Set client'''
72
+
73
+ def add(self, *arg):
74
+ arg_b = {dill.dumps(i) for i in arg}
75
+ self._r.sadd(self.name, *arg_b)
76
+ self._r.expire(self.name, self.expire_time)
77
+
78
+ def read(self):
79
+ data_b = self._r.smembers(self.name)
80
+ data = {dill.loads(i) for i in data_b}
81
+ return data
82
+
83
+ @property
84
+ def size(self):
85
+ return self._r.scard(self.name)
86
+
87
+ @property
88
+ def data(self):
89
+ return self.read()
90
+
91
+
92
+ class redisZSet(redisClient):
93
+ '''有序集合'''
94
+
95
+ def __init__(self,
96
+ name,
97
+ server=None,
98
+ addr='redis://localhost:6379/0',
99
+ expire_time=172800):
100
+ super().__init__(name, server, addr, expire_time)
101
+ self.__score = 0
102
+
103
+ def delete(self):
104
+ super().delete()
105
+ self.__score = 0
106
+
107
+ def add(self, *elements):
108
+ mapping = {}
109
+ for ele in elements:
110
+ ele_b = dill.dumps(ele)
111
+ self.__score += 1
112
+ mapping.update({ele_b: self.__score})
113
+ self._r.zadd(self.name, mapping, nx=True) # 只添加新元素
114
+ self._r.expire(self.name, self.expire_time)
115
+
116
+ def read(self, start=0, end=-1):
117
+ data_b = self._r.zrange(self.name, start, end, withscores=False)
118
+ data = [dill.loads(i) for i in data_b]
119
+ return data
120
+
121
+ @property
122
+ def size(self):
123
+ return self._r.zcard(self.name)
124
+
125
+ @property
126
+ def data(self):
127
+ return self.read()
128
+
129
+
130
+ class redisHash(redisClient):
131
+ '''Redis Hash client'''
132
+
133
+ def add(self, **kw):
134
+ kw_b = {k: try_dumps(v) for k, v in kw.items()}
135
+ self._r.hmset(self.name, kw_b)
136
+ self._r.expire(self.name, self.expire_time)
137
+
138
+ def read(self):
139
+ data_b = self._r.hgetall(self.name)
140
+ data = {k_b.decode(): dill.loads(v_b) for k_b, v_b in data_b.items()}
141
+ return data
142
+
143
+ def get(self, key):
144
+ '''读取Hash中的一个key'''
145
+ v_b = self._r.hget(self.name, key)
146
+ value = dill.loads(v_b) if v_b is not None else None
147
+ return value
148
+
149
+ @property
150
+ def size(self):
151
+ return self._r.hlen(self.name)
152
+
153
+ @property
154
+ def data(self):
155
+ return self.read()
156
+
157
+
158
+ class redisArray(redisClient):
159
+ '''Redis np.array client'''
160
+
161
+ def __init__(self,
162
+ name,
163
+ server=None,
164
+ addr='redis://localhost:6379/0',
165
+ expire_time=172800,
166
+ dtype='complex128'):
167
+ super().__init__(name, server, addr, expire_time)
168
+ _r_dtype = self._r.get(f'{name}.dtype')
169
+ if _r_dtype is None:
170
+ self._r.set(f'{name}.dtype', dtype, ex=self.expire_time)
171
+ self.dtype = dtype
172
+ else:
173
+ self.dtype = _r_dtype
174
+
175
+ def delete(self):
176
+ self._r.delete(self.name)
177
+ self._r.delete(f'{self.name}.dtype')
178
+
179
+ def add(self, *args):
180
+ for arg in args:
181
+ buf = np.asarray(arg).astype(self.dtype).tobytes()
182
+ # self._r.append(self.name, buf)
183
+ self._r.rpush(self.name, buf)
184
+ self._r.expire(self.name, self.expire_time)
185
+
186
+ def read(self):
187
+ # buf = self._r.get(self.name)
188
+ buf_list = self._r.lrange(self.name, 0, -1)
189
+ buf = b''.join(buf_list)
190
+ data = np.frombuffer(buf,
191
+ dtype=self.dtype) if buf is not None else None
192
+ return data
193
+
194
+ @property
195
+ def size(self):
196
+ array = self.data
197
+ if array is None:
198
+ return 0
199
+ else:
200
+ return array.size
201
+
202
+ @property
203
+ def data(self):
204
+ return self.read()