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.
- qulab/__init__.py +33 -0
- qulab/__main__.py +4 -0
- qulab/cli/__init__.py +0 -0
- qulab/cli/commands.py +30 -0
- qulab/cli/config.py +170 -0
- qulab/cli/decorators.py +28 -0
- qulab/dicttree.py +523 -0
- qulab/executor/__init__.py +5 -0
- qulab/executor/analyze.py +188 -0
- qulab/executor/cli.py +434 -0
- qulab/executor/load.py +563 -0
- qulab/executor/registry.py +185 -0
- qulab/executor/schedule.py +543 -0
- qulab/executor/storage.py +615 -0
- qulab/executor/template.py +259 -0
- qulab/executor/utils.py +194 -0
- qulab/expression.py +827 -0
- qulab/fun.cpython-313-darwin.so +0 -0
- qulab/monitor/__init__.py +1 -0
- qulab/monitor/__main__.py +8 -0
- qulab/monitor/config.py +41 -0
- qulab/monitor/dataset.py +77 -0
- qulab/monitor/event_queue.py +54 -0
- qulab/monitor/mainwindow.py +234 -0
- qulab/monitor/monitor.py +115 -0
- qulab/monitor/ploter.py +123 -0
- qulab/monitor/qt_compat.py +16 -0
- qulab/monitor/toolbar.py +265 -0
- qulab/scan/__init__.py +2 -0
- qulab/scan/curd.py +221 -0
- qulab/scan/models.py +554 -0
- qulab/scan/optimize.py +76 -0
- qulab/scan/query.py +387 -0
- qulab/scan/record.py +603 -0
- qulab/scan/scan.py +1166 -0
- qulab/scan/server.py +450 -0
- qulab/scan/space.py +213 -0
- qulab/scan/utils.py +234 -0
- qulab/storage/__init__.py +0 -0
- qulab/storage/__main__.py +51 -0
- qulab/storage/backend/__init__.py +0 -0
- qulab/storage/backend/redis.py +204 -0
- qulab/storage/base_dataset.py +352 -0
- qulab/storage/chunk.py +60 -0
- qulab/storage/dataset.py +127 -0
- qulab/storage/file.py +273 -0
- qulab/storage/models/__init__.py +22 -0
- qulab/storage/models/base.py +4 -0
- qulab/storage/models/config.py +28 -0
- qulab/storage/models/file.py +89 -0
- qulab/storage/models/ipy.py +58 -0
- qulab/storage/models/models.py +88 -0
- qulab/storage/models/record.py +161 -0
- qulab/storage/models/report.py +22 -0
- qulab/storage/models/tag.py +93 -0
- qulab/storage/storage.py +95 -0
- qulab/sys/__init__.py +2 -0
- qulab/sys/chat.py +688 -0
- qulab/sys/device/__init__.py +3 -0
- qulab/sys/device/basedevice.py +255 -0
- qulab/sys/device/loader.py +86 -0
- qulab/sys/device/utils.py +79 -0
- qulab/sys/drivers/FakeInstrument.py +68 -0
- qulab/sys/drivers/__init__.py +0 -0
- qulab/sys/ipy_events.py +125 -0
- qulab/sys/net/__init__.py +0 -0
- qulab/sys/net/bencoder.py +205 -0
- qulab/sys/net/cli.py +169 -0
- qulab/sys/net/dhcp.py +543 -0
- qulab/sys/net/dhcpd.py +176 -0
- qulab/sys/net/kad.py +1142 -0
- qulab/sys/net/kcp.py +192 -0
- qulab/sys/net/nginx.py +194 -0
- qulab/sys/progress.py +190 -0
- qulab/sys/rpc/__init__.py +0 -0
- qulab/sys/rpc/client.py +0 -0
- qulab/sys/rpc/exceptions.py +96 -0
- qulab/sys/rpc/msgpack.py +1052 -0
- qulab/sys/rpc/msgpack.pyi +41 -0
- qulab/sys/rpc/router.py +35 -0
- qulab/sys/rpc/rpc.py +412 -0
- qulab/sys/rpc/serialize.py +139 -0
- qulab/sys/rpc/server.py +29 -0
- qulab/sys/rpc/socket.py +29 -0
- qulab/sys/rpc/utils.py +25 -0
- qulab/sys/rpc/worker.py +0 -0
- qulab/sys/rpc/zmq_socket.py +227 -0
- qulab/tools/__init__.py +0 -0
- qulab/tools/connection_helper.py +39 -0
- qulab/typing.py +2 -0
- qulab/utils.py +95 -0
- qulab/version.py +1 -0
- qulab/visualization/__init__.py +188 -0
- qulab/visualization/__main__.py +71 -0
- qulab/visualization/_autoplot.py +464 -0
- qulab/visualization/plot_circ.py +319 -0
- qulab/visualization/plot_layout.py +408 -0
- qulab/visualization/plot_seq.py +242 -0
- qulab/visualization/qdat.py +152 -0
- qulab/visualization/rot3d.py +23 -0
- qulab/visualization/widgets.py +86 -0
- qulab-2.10.10.dist-info/METADATA +110 -0
- qulab-2.10.10.dist-info/RECORD +107 -0
- qulab-2.10.10.dist-info/WHEEL +5 -0
- qulab-2.10.10.dist-info/entry_points.txt +2 -0
- qulab-2.10.10.dist-info/licenses/LICENSE +21 -0
- qulab-2.10.10.dist-info/top_level.txt +1 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
"""
|
2
|
+
This module provides a simple bencoding implementation in pure Python.
|
3
|
+
Bencoding is a way to specify and organize data in a terse format. It supports
|
4
|
+
the following types: byte strings, integers, lists, and dictionaries.
|
5
|
+
|
6
|
+
Classes:
|
7
|
+
Bencached: A class that holds bencoded data.
|
8
|
+
|
9
|
+
Functions:
|
10
|
+
encode_bencached(x, fp): Encodes a Bencached object.
|
11
|
+
encode_int(x, fp): Encodes an integer.
|
12
|
+
encode_bool(x, fp): Encodes a boolean.
|
13
|
+
encode_string(x, fp): Encodes a string.
|
14
|
+
encode_list(x, fp): Encodes a list.
|
15
|
+
encode_dict(x, fp): Encodes a dictionary.
|
16
|
+
decode_int(x, ptr): Decodes a bencoded integer.
|
17
|
+
decode_string(x, ptr): Decodes a bencoded string.
|
18
|
+
decode_list(x, ptr): Decodes a bencoded list.
|
19
|
+
decode_dict(x, ptr): Decodes a bencoded dictionary.
|
20
|
+
encode(obj, fp): Encodes an object.
|
21
|
+
encodes(obj): Encodes an object and returns the bencoded bytes.
|
22
|
+
decode(fp): Decodes a file-like object.
|
23
|
+
decodes(s): Decodes a bencoded bytes object.
|
24
|
+
dump = encode: Alias for encode function.
|
25
|
+
load = decodes: Alias for decode function.
|
26
|
+
dumps = encodes: Alias for encodes function.
|
27
|
+
loads = decodes: Alias for decodes function.
|
28
|
+
|
29
|
+
Examples:
|
30
|
+
>>> encode(42) == b'i42e'
|
31
|
+
True
|
32
|
+
>>> decode(b'i42e')
|
33
|
+
42
|
34
|
+
"""
|
35
|
+
import io
|
36
|
+
|
37
|
+
|
38
|
+
class Bencached():
|
39
|
+
|
40
|
+
__slots__ = ['bencoded']
|
41
|
+
|
42
|
+
def __init__(self, s):
|
43
|
+
self.bencoded = s
|
44
|
+
|
45
|
+
|
46
|
+
def encode_bencached(x, fp):
|
47
|
+
fp.write(x.bencoded)
|
48
|
+
|
49
|
+
|
50
|
+
def encode_int(x, fp):
|
51
|
+
fp.write(f"i{x}e".encode())
|
52
|
+
|
53
|
+
|
54
|
+
def encode_bool(x, fp):
|
55
|
+
if x:
|
56
|
+
encode_int(1, fp)
|
57
|
+
else:
|
58
|
+
encode_int(0, fp)
|
59
|
+
|
60
|
+
|
61
|
+
def encode_string(x, fp):
|
62
|
+
if isinstance(x, str):
|
63
|
+
x = x.encode()
|
64
|
+
fp.write(f"{len(x):d}:".encode())
|
65
|
+
fp.write(x)
|
66
|
+
|
67
|
+
|
68
|
+
def encode_list(x, fp):
|
69
|
+
fp.write(b'l')
|
70
|
+
for i in x:
|
71
|
+
encode_func[type(i)](i, fp)
|
72
|
+
fp.write(b'e')
|
73
|
+
|
74
|
+
|
75
|
+
def encode_dict(x, fp):
|
76
|
+
fp.write(b'd')
|
77
|
+
for k, v in sorted(x.items()):
|
78
|
+
if isinstance(k, str):
|
79
|
+
k = k.encode()
|
80
|
+
fp.write(f"{len(k):d}:".encode())
|
81
|
+
fp.write(k)
|
82
|
+
encode_func[type(v)](v, fp)
|
83
|
+
fp.write(b'e')
|
84
|
+
|
85
|
+
|
86
|
+
encode_func = {
|
87
|
+
Bencached: encode_bencached,
|
88
|
+
int: encode_int,
|
89
|
+
str: encode_string,
|
90
|
+
bytes: encode_string,
|
91
|
+
list: encode_list,
|
92
|
+
tuple: encode_list,
|
93
|
+
dict: encode_dict,
|
94
|
+
bool: encode_bool
|
95
|
+
}
|
96
|
+
|
97
|
+
|
98
|
+
def decode_int(x, ptr):
|
99
|
+
ptr += 1
|
100
|
+
end = x.index(b'e', ptr)
|
101
|
+
if x[ptr] == b'-'[0]:
|
102
|
+
if x[ptr + 1] == b'0'[0]:
|
103
|
+
raise ValueError
|
104
|
+
elif x[ptr] == b'0'[0] and end != ptr + 1:
|
105
|
+
raise ValueError
|
106
|
+
n = int(x[ptr:end])
|
107
|
+
return n, end + 1
|
108
|
+
|
109
|
+
|
110
|
+
def decode_string(x, ptr):
|
111
|
+
colon = x.index(b':', ptr)
|
112
|
+
n = int(x[ptr:colon])
|
113
|
+
if x[ptr] == b'0'[0] and colon != ptr + 1:
|
114
|
+
raise ValueError
|
115
|
+
colon += 1
|
116
|
+
return x[colon:colon + n], colon + n
|
117
|
+
|
118
|
+
|
119
|
+
def decode_list(x, ptr):
|
120
|
+
r, ptr = [], ptr + 1
|
121
|
+
while x[ptr] != b'e'[0]:
|
122
|
+
v, ptr = decode_func[x[ptr]](x, ptr)
|
123
|
+
r.append(v)
|
124
|
+
return r, ptr + 1
|
125
|
+
|
126
|
+
|
127
|
+
def decode_dict(x, ptr):
|
128
|
+
r, ptr = {}, ptr + 1
|
129
|
+
while x[ptr] != b'e'[0]:
|
130
|
+
k, ptr = decode_string(x, ptr)
|
131
|
+
if isinstance(k, bytes):
|
132
|
+
k = k.decode()
|
133
|
+
r[k], ptr = decode_func[x[ptr]](x, ptr)
|
134
|
+
return r, ptr + 1
|
135
|
+
|
136
|
+
|
137
|
+
decode_func = {b'l'[0]: decode_list, b'd'[0]: decode_dict, b'i'[0]: decode_int}
|
138
|
+
|
139
|
+
for i in range(10):
|
140
|
+
decode_func[f"{i}".encode()[0]] = decode_string
|
141
|
+
|
142
|
+
|
143
|
+
def encode(obj, fp):
|
144
|
+
try:
|
145
|
+
encode_func[type(obj)](obj, fp)
|
146
|
+
except KeyError:
|
147
|
+
raise ValueError("Allowed types: int, bytes, list, dict; not %s",
|
148
|
+
type(obj))
|
149
|
+
|
150
|
+
|
151
|
+
def encodes(obj):
|
152
|
+
"""
|
153
|
+
bencodes given object. Given object should be a int,
|
154
|
+
bytes, list or dict. If a str is given, it'll be
|
155
|
+
encoded as ASCII.
|
156
|
+
>>> [encode(i) for i in (-2, 42, b"answer", b"")] \
|
157
|
+
== [b'i-2e', b'i42e', b'6:answer', b'0:']
|
158
|
+
True
|
159
|
+
>>> encode([b'a', 42, [13, 14]]) == b'l1:ai42eli13ei14eee'
|
160
|
+
True
|
161
|
+
>>> encode({'bar': b'spam', 'foo': 42, 'mess': [1, b'c']}) \
|
162
|
+
== b'd3:bar4:spam3:fooi42e4:messli1e1:cee'
|
163
|
+
True
|
164
|
+
"""
|
165
|
+
buff = io.BytesIO()
|
166
|
+
encode(obj, buff)
|
167
|
+
return buff.getvalue()
|
168
|
+
|
169
|
+
|
170
|
+
def decodes(s):
|
171
|
+
"""
|
172
|
+
Decodes given bencoded bytes object.
|
173
|
+
>>> decode(b'i-42e')
|
174
|
+
-42
|
175
|
+
>>> decode(b'4:utku') == b'utku'
|
176
|
+
True
|
177
|
+
>>> decode(b'li1eli2eli3eeee')
|
178
|
+
[1, [2, [3]]]
|
179
|
+
>>> decode(b'd3:bar4:spam3:fooi42ee') == {'bar': b'spam', 'foo': 42}
|
180
|
+
True
|
181
|
+
"""
|
182
|
+
if isinstance(s, str):
|
183
|
+
s = s.encode()
|
184
|
+
try:
|
185
|
+
r, l = decode_func[s[0]](s, 0)
|
186
|
+
except (IndexError, KeyError, ValueError):
|
187
|
+
raise ValueError("not a valid bencoded string")
|
188
|
+
if l != len(s):
|
189
|
+
raise ValueError("invalid bencoded value (data after valid prefix)")
|
190
|
+
return r
|
191
|
+
|
192
|
+
|
193
|
+
def decode(fp):
|
194
|
+
"""
|
195
|
+
Decodes given file-like object.
|
196
|
+
"""
|
197
|
+
return decodes(fp.read())
|
198
|
+
|
199
|
+
|
200
|
+
dump = encode
|
201
|
+
load = decodes
|
202
|
+
dumps = encodes
|
203
|
+
loads = decodes
|
204
|
+
|
205
|
+
__all__ = ['decodes', 'encodes', 'dump', 'load', 'dumps', 'loads']
|
qulab/sys/net/cli.py
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
import asyncio
|
2
|
+
import pathlib
|
3
|
+
import pickle
|
4
|
+
|
5
|
+
import click
|
6
|
+
|
7
|
+
from .kad import Server
|
8
|
+
|
9
|
+
|
10
|
+
async def client_get(key, server, port, timeout=5):
|
11
|
+
reader, writer = await asyncio.wait_for(asyncio.open_connection(
|
12
|
+
server, port),
|
13
|
+
timeout=timeout)
|
14
|
+
writer.write(pickle.dumps(('get', key)))
|
15
|
+
await asyncio.wait_for(writer.drain(), timeout=timeout)
|
16
|
+
data = await asyncio.wait_for(reader.read(1600), timeout=timeout)
|
17
|
+
value = pickle.loads(data)
|
18
|
+
writer.close()
|
19
|
+
await writer.wait_closed()
|
20
|
+
return value
|
21
|
+
|
22
|
+
|
23
|
+
async def client_set(key, value, server, port, timeout=5):
|
24
|
+
reader, writer = await asyncio.wait_for(asyncio.open_connection(
|
25
|
+
server, port),
|
26
|
+
timeout=timeout)
|
27
|
+
writer.write(pickle.dumps(('set', key, value)))
|
28
|
+
await asyncio.wait_for(writer.drain(), timeout=timeout)
|
29
|
+
writer.close()
|
30
|
+
await writer.wait_closed()
|
31
|
+
|
32
|
+
|
33
|
+
async def client_bootstrap(address, server, port, timeout=5):
|
34
|
+
reader, writer = await asyncio.wait_for(asyncio.open_connection(
|
35
|
+
server, port),
|
36
|
+
timeout=timeout)
|
37
|
+
addr, p = address.split(':')
|
38
|
+
writer.write(pickle.dumps(('bootstrap', (addr, int(p)))))
|
39
|
+
await asyncio.wait_for(writer.drain(), timeout=timeout)
|
40
|
+
writer.close()
|
41
|
+
await writer.wait_closed()
|
42
|
+
|
43
|
+
|
44
|
+
@click.group()
|
45
|
+
def dht():
|
46
|
+
pass
|
47
|
+
|
48
|
+
|
49
|
+
@dht.command()
|
50
|
+
@click.option('--interface',
|
51
|
+
default='127.0.0.1',
|
52
|
+
help='Interface to listen on')
|
53
|
+
@click.option('--port', default=8467, help='Port to listen on')
|
54
|
+
@click.option('--dht-only', default=False, is_flag=True, help='DHT only')
|
55
|
+
@click.option('--dht-interface',
|
56
|
+
default='0.0.0.0',
|
57
|
+
help='DHT interface to listen on')
|
58
|
+
@click.option('--dht-port', default=8468, help='DHT port to listen on')
|
59
|
+
@click.option('--bootstrap', default=None, help='Address of bootstrap node')
|
60
|
+
@click.option('--interval', default=300, help='Refresh interval')
|
61
|
+
@click.option('--state-file', default=None, help='State file')
|
62
|
+
def server(interface, port, dht_only, dht_interface, dht_port, bootstrap,
|
63
|
+
interval, state_file):
|
64
|
+
|
65
|
+
async def main(interface, port, dht_only, dht_interface, dht_port,
|
66
|
+
bootstrap, state_file):
|
67
|
+
|
68
|
+
if state_file is None:
|
69
|
+
state_file = pathlib.Path.home() / '.waveforms' / 'dht.pickle'
|
70
|
+
else:
|
71
|
+
state_file = pathlib.Path(state_file)
|
72
|
+
|
73
|
+
if state_file.exists():
|
74
|
+
node = await Server.load_state(state_file, dht_port, dht_interface,
|
75
|
+
interval)
|
76
|
+
else:
|
77
|
+
node = Server()
|
78
|
+
state_file.parent.mkdir(parents=True, exist_ok=True)
|
79
|
+
await node.listen(dht_port, dht_interface, interval)
|
80
|
+
if bootstrap:
|
81
|
+
addr, p = bootstrap.split(':')
|
82
|
+
await node.bootstrap([(addr, int(p))])
|
83
|
+
|
84
|
+
loop = asyncio.get_running_loop()
|
85
|
+
loop.call_later(min(interval / 2, 30), node.save_state_regularly,
|
86
|
+
state_file, interval)
|
87
|
+
|
88
|
+
async def handle_cmds(reader, writer):
|
89
|
+
data = await reader.read(1600)
|
90
|
+
cmd, *args = pickle.loads(data)
|
91
|
+
match cmd:
|
92
|
+
case 'get':
|
93
|
+
value = await node.get(*args)
|
94
|
+
data = pickle.dumps(value)
|
95
|
+
case 'set':
|
96
|
+
value = await node.set(*args)
|
97
|
+
data = pickle.dumps(value)
|
98
|
+
case 'ping':
|
99
|
+
data = pickle.dumps(node.node.id)
|
100
|
+
case 'bootstrap':
|
101
|
+
await node.bootstrap(args)
|
102
|
+
data = pickle.dumps(None)
|
103
|
+
case _:
|
104
|
+
data = pickle.dumps(None)
|
105
|
+
|
106
|
+
writer.write(data)
|
107
|
+
await writer.drain()
|
108
|
+
writer.close()
|
109
|
+
await writer.wait_closed()
|
110
|
+
|
111
|
+
if dht_only:
|
112
|
+
try:
|
113
|
+
while True:
|
114
|
+
await asyncio.sleep(1)
|
115
|
+
except asyncio.CancelledError:
|
116
|
+
pass
|
117
|
+
else:
|
118
|
+
server = await asyncio.start_server(handle_cmds, interface, port)
|
119
|
+
|
120
|
+
async with server:
|
121
|
+
try:
|
122
|
+
await server.serve_forever()
|
123
|
+
except asyncio.CancelledError:
|
124
|
+
pass
|
125
|
+
|
126
|
+
asyncio.run(
|
127
|
+
main(interface, port, dht_only, dht_interface, dht_port, bootstrap,
|
128
|
+
state_file))
|
129
|
+
|
130
|
+
|
131
|
+
@dht.command('get')
|
132
|
+
@click.argument('key')
|
133
|
+
@click.option('--server', default='127.0.0.1', help='Server to connect to')
|
134
|
+
@click.option('--port', default=8467, help='Port to connect to')
|
135
|
+
@click.option('--timeout', default=5, help='Timeout')
|
136
|
+
def get(key, server, port, timeout):
|
137
|
+
|
138
|
+
async def client():
|
139
|
+
value = await client_get(key, server, port, timeout)
|
140
|
+
print(value)
|
141
|
+
|
142
|
+
asyncio.run(client())
|
143
|
+
|
144
|
+
|
145
|
+
@dht.command('set')
|
146
|
+
@click.argument('key')
|
147
|
+
@click.argument('value')
|
148
|
+
@click.option('--server', default='127.0.0.1', help='Server to connect to')
|
149
|
+
@click.option('--port', default=8467, help='Port to connect to')
|
150
|
+
@click.option('--timeout', default=5, help='Timeout')
|
151
|
+
def set_(key, value, server, port, timeout):
|
152
|
+
|
153
|
+
async def client():
|
154
|
+
await client_set(key, value, server, port, timeout)
|
155
|
+
|
156
|
+
asyncio.run(client())
|
157
|
+
|
158
|
+
|
159
|
+
@dht.command('bootstrap')
|
160
|
+
@click.argument('address')
|
161
|
+
@click.option('--server', default='127.0.0.1', help='Server to connect to')
|
162
|
+
@click.option('--port', default=8467, help='Port to connect to')
|
163
|
+
@click.option('--timeout', default=5, help='Timeout')
|
164
|
+
def bootstrap(address, server, port, timeout):
|
165
|
+
|
166
|
+
async def client():
|
167
|
+
await client_bootstrap(address, server, port, timeout)
|
168
|
+
|
169
|
+
asyncio.run(client())
|