QuLab 2.0.1__cp310-cp310-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.0.1.dist-info/LICENSE +21 -0
- QuLab-2.0.1.dist-info/METADATA +95 -0
- QuLab-2.0.1.dist-info/RECORD +82 -0
- QuLab-2.0.1.dist-info/WHEEL +5 -0
- QuLab-2.0.1.dist-info/entry_points.txt +2 -0
- QuLab-2.0.1.dist-info/top_level.txt +1 -0
- qulab/__init__.py +1 -0
- qulab/__main__.py +24 -0
- qulab/fun.cp310-win_amd64.pyd +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 +93 -0
- qulab/monitor/ploter.py +123 -0
- qulab/monitor/qt_compat.py +16 -0
- qulab/monitor/toolbar.py +265 -0
- qulab/scan/__init__.py +4 -0
- qulab/scan/base.py +548 -0
- qulab/scan/dataset.py +0 -0
- qulab/scan/expression.py +472 -0
- qulab/scan/optimize.py +0 -0
- qulab/scan/scanner.py +270 -0
- qulab/scan/transforms.py +16 -0
- qulab/scan/utils.py +37 -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 +0 -0
- qulab/sys/chat.py +688 -0
- qulab/sys/device/__init__.py +3 -0
- qulab/sys/device/basedevice.py +221 -0
- qulab/sys/device/loader.py +86 -0
- qulab/sys/device/utils.py +46 -0
- qulab/sys/drivers/FakeInstrument.py +52 -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 +192 -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/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/version.py +1 -0
- qulab/visualization/__init__.py +188 -0
- qulab/visualization/__main__.py +71 -0
- qulab/visualization/_autoplot.py +457 -0
- qulab/visualization/plot_layout.py +408 -0
- qulab/visualization/plot_seq.py +90 -0
- qulab/visualization/qdat.py +152 -0
- qulab/visualization/widgets.py +86 -0
qulab/scan/scanner.py
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import itertools
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from .base import scan_iters
|
|
7
|
+
from .expression import Env, Expression, Symbol, _empty
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def is_valid_identifier(s: str) -> bool:
|
|
11
|
+
try:
|
|
12
|
+
ast.parse(f"f({s}=0)")
|
|
13
|
+
return True
|
|
14
|
+
except SyntaxError:
|
|
15
|
+
return False
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Atom():
|
|
19
|
+
__slots__ = ('value', )
|
|
20
|
+
|
|
21
|
+
def __init__(self, value):
|
|
22
|
+
self.value = value
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class MappedSymbol(Symbol):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class OptimizeSpace():
|
|
30
|
+
|
|
31
|
+
def __init__(self, optimizer, space):
|
|
32
|
+
self.optimizer = optimizer
|
|
33
|
+
self.space = space
|
|
34
|
+
self.name = None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Optimizer():
|
|
38
|
+
|
|
39
|
+
def __init__(self, cls, *args, **kwds):
|
|
40
|
+
self.cls = cls
|
|
41
|
+
self.args = args
|
|
42
|
+
self.kwds = kwds
|
|
43
|
+
self.dimensions = {}
|
|
44
|
+
self.function = None
|
|
45
|
+
|
|
46
|
+
def Categorical(self, *args, **kwds):
|
|
47
|
+
from skopt.space import Categorical
|
|
48
|
+
return OptimizeSpace(self, Categorical(*args, **kwds))
|
|
49
|
+
|
|
50
|
+
def Integer(self, *args, **kwds):
|
|
51
|
+
from skopt.space import Integer
|
|
52
|
+
return OptimizeSpace(self, Integer(*args, **kwds))
|
|
53
|
+
|
|
54
|
+
def Real(self, *args, **kwds):
|
|
55
|
+
from skopt.space import Real
|
|
56
|
+
return OptimizeSpace(self, Real(*args, **kwds))
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def target(self):
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
@target.setter
|
|
63
|
+
def target(self, fun):
|
|
64
|
+
if isinstance(fun, Symbol):
|
|
65
|
+
self.function = fun.name
|
|
66
|
+
elif isinstance(fun, Expression):
|
|
67
|
+
self.function = fun
|
|
68
|
+
else:
|
|
69
|
+
raise ValueError("Invalid function")
|
|
70
|
+
|
|
71
|
+
def create_optimizer(self):
|
|
72
|
+
dimensions = list(self.dimensions.values())
|
|
73
|
+
return tuple(self.dimensions.keys()), self.cls(dimensions, *self.args,
|
|
74
|
+
**self.kwds)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Action():
|
|
78
|
+
|
|
79
|
+
__slots__ = ('name', 'args', 'kwds')
|
|
80
|
+
|
|
81
|
+
def __init__(self, name, *args, **kwds):
|
|
82
|
+
self.name = name
|
|
83
|
+
self.args = args
|
|
84
|
+
self.kwds = kwds
|
|
85
|
+
|
|
86
|
+
def __repr__(self):
|
|
87
|
+
return f"Action({self.name!r}, {self.args}, {self.kwds})"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class Scan():
|
|
91
|
+
|
|
92
|
+
def __new__(cls, *args, mixin=None, **kwds):
|
|
93
|
+
if mixin is None:
|
|
94
|
+
return super().__new__(cls)
|
|
95
|
+
for k in dir(mixin):
|
|
96
|
+
if not hasattr(cls, k):
|
|
97
|
+
try:
|
|
98
|
+
setattr(cls, k, getattr(mixin, k))
|
|
99
|
+
except:
|
|
100
|
+
pass
|
|
101
|
+
return super().__new__(cls)
|
|
102
|
+
|
|
103
|
+
def __init__(self, name, *args, env=None, mixin=None, **kwds):
|
|
104
|
+
super().__init__(*args, **kwds)
|
|
105
|
+
self._name = name.replace(' ', '_')
|
|
106
|
+
self.env = Env() if env is None else env
|
|
107
|
+
self.functions = {}
|
|
108
|
+
self.consts = {}
|
|
109
|
+
self.loops = {}
|
|
110
|
+
self.mapping = {}
|
|
111
|
+
self.optimizers = {}
|
|
112
|
+
self._mapping_i = 0
|
|
113
|
+
self.filter = None
|
|
114
|
+
self.scan_info = {'loops': {}}
|
|
115
|
+
self._tmp = {}
|
|
116
|
+
self.actions = {}
|
|
117
|
+
self.iteration = 0
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def name(self):
|
|
121
|
+
return f"Scan.{self._name}"
|
|
122
|
+
|
|
123
|
+
def get(self, key, default=_empty):
|
|
124
|
+
if key in self.consts:
|
|
125
|
+
return self.consts[key]
|
|
126
|
+
if key in self.functions:
|
|
127
|
+
return self.functions[key]
|
|
128
|
+
if default is _empty:
|
|
129
|
+
raise KeyError(f"Key {key} not found")
|
|
130
|
+
return default
|
|
131
|
+
|
|
132
|
+
def set(self, key, value):
|
|
133
|
+
self.add_action(Action('set', key, value))
|
|
134
|
+
|
|
135
|
+
def _mapping(self, key, value):
|
|
136
|
+
tmpkey = f"__tmp_{self._mapping_i}__"
|
|
137
|
+
self._mapping_i += 1
|
|
138
|
+
self.__setitem(tmpkey, value)
|
|
139
|
+
self.mapping[key] = tmpkey
|
|
140
|
+
|
|
141
|
+
def __setitem__(self, key, value):
|
|
142
|
+
if is_valid_identifier(key):
|
|
143
|
+
if isinstance(value, Atom):
|
|
144
|
+
self.consts[key] = value.value
|
|
145
|
+
return
|
|
146
|
+
elif isinstance(value, (str, int, float, complex, tuple)):
|
|
147
|
+
self.consts[key] = value
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
if isinstance(value, Expression):
|
|
151
|
+
env = Env()
|
|
152
|
+
env.consts = self.consts
|
|
153
|
+
value = value.value(env)
|
|
154
|
+
if not isinstance(value, Expression):
|
|
155
|
+
self.__setitem__(key, value)
|
|
156
|
+
return
|
|
157
|
+
|
|
158
|
+
self._tmp[key] = value
|
|
159
|
+
|
|
160
|
+
def __setitem(self, key, value):
|
|
161
|
+
if not is_valid_identifier(key):
|
|
162
|
+
self._mapping(key, value)
|
|
163
|
+
return
|
|
164
|
+
if isinstance(value, Expression) or callable(value):
|
|
165
|
+
self.functions[key] = value
|
|
166
|
+
elif isinstance(value, OptimizeSpace):
|
|
167
|
+
self.optimizers[key] = value.optimizer
|
|
168
|
+
value.name = key
|
|
169
|
+
value.optimizer.dimensions[key] = value.space
|
|
170
|
+
self.loops[key] = value.optimizer
|
|
171
|
+
elif isinstance(value, (np.ndarray, list, range)):
|
|
172
|
+
self.loops[key] = value
|
|
173
|
+
elif isinstance(value, Atom):
|
|
174
|
+
self.consts[key] = value.value
|
|
175
|
+
else:
|
|
176
|
+
self.consts[key] = value
|
|
177
|
+
|
|
178
|
+
def __getitem__(self, key):
|
|
179
|
+
if key in self.consts:
|
|
180
|
+
return self.consts[key]
|
|
181
|
+
if is_valid_identifier(key):
|
|
182
|
+
return Symbol(key)
|
|
183
|
+
else:
|
|
184
|
+
if key in self.mapping:
|
|
185
|
+
return Symbol(self.mapping[key])
|
|
186
|
+
return MappedSymbol(key)
|
|
187
|
+
|
|
188
|
+
def assemble(self):
|
|
189
|
+
for key, value in self._tmp.items():
|
|
190
|
+
self.__setitem(key, value)
|
|
191
|
+
|
|
192
|
+
variables = {}
|
|
193
|
+
loops = {}
|
|
194
|
+
|
|
195
|
+
for k, v in self.functions.items():
|
|
196
|
+
if isinstance(v, MappedSymbol):
|
|
197
|
+
variables[k] = eval(
|
|
198
|
+
f"lambda {self.mapping[k]}: {self.mapping[k]}")
|
|
199
|
+
elif isinstance(v, Expression):
|
|
200
|
+
args = v.symbols()
|
|
201
|
+
for x in args:
|
|
202
|
+
if x in self.mapping:
|
|
203
|
+
args.remove(x)
|
|
204
|
+
v = v.value({x: Symbol(self.mapping[x])})
|
|
205
|
+
x = self.mapping[x]
|
|
206
|
+
if x in self.consts:
|
|
207
|
+
args.remove(x)
|
|
208
|
+
v = v.value({x: self.consts[x]})
|
|
209
|
+
if args:
|
|
210
|
+
variables[k] = eval(
|
|
211
|
+
f"lambda {','.join(args)}: expr.value({{{','.join([f'{x!r}:{x}' for x in args])}}})",
|
|
212
|
+
{'expr': v})
|
|
213
|
+
else:
|
|
214
|
+
self.consts[k] = v
|
|
215
|
+
else:
|
|
216
|
+
variables[k] = v
|
|
217
|
+
|
|
218
|
+
for key, value in self.loops.items():
|
|
219
|
+
if isinstance(value, Optimizer):
|
|
220
|
+
#variables[key] = value.create_optimizer()
|
|
221
|
+
pass
|
|
222
|
+
else:
|
|
223
|
+
loops[key] = value
|
|
224
|
+
|
|
225
|
+
self.scan_info = {
|
|
226
|
+
'loops': loops,
|
|
227
|
+
'functions': variables,
|
|
228
|
+
'constants': self.consts
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if self.filter is not None:
|
|
232
|
+
self.scan_info['filter'] = self.filter
|
|
233
|
+
|
|
234
|
+
def main(self):
|
|
235
|
+
self.assemble()
|
|
236
|
+
for step in self.scan():
|
|
237
|
+
for k, v in self.mapping.items():
|
|
238
|
+
if v in set(
|
|
239
|
+
itertools.chain.from_iterable(
|
|
240
|
+
step.vars[step.unchanged:])
|
|
241
|
+
) or step.iteration == 0:
|
|
242
|
+
self.set(k, step.kwds[v])
|
|
243
|
+
self.process(step)
|
|
244
|
+
|
|
245
|
+
def process(self, step):
|
|
246
|
+
for k, v in step.kwds.items():
|
|
247
|
+
if not k.startswith('__tmp_') and not k.startswith('__'):
|
|
248
|
+
self.add_action(Action('write', k, v))
|
|
249
|
+
|
|
250
|
+
def scan(self):
|
|
251
|
+
for step in scan_iters(**self.scan_info):
|
|
252
|
+
for k, v in self.mapping.items():
|
|
253
|
+
step.kwds[k] = step.kwds[v]
|
|
254
|
+
yield step
|
|
255
|
+
self.iteration += 1
|
|
256
|
+
|
|
257
|
+
def add_action(self, action: Action):
|
|
258
|
+
self.actions.setdefault(self.iteration, []).append(action)
|
|
259
|
+
|
|
260
|
+
def run(self, dry_run=False):
|
|
261
|
+
pass
|
|
262
|
+
|
|
263
|
+
def plot(self,
|
|
264
|
+
result=None,
|
|
265
|
+
fig=None,
|
|
266
|
+
axis=None,
|
|
267
|
+
data='population',
|
|
268
|
+
T=False,
|
|
269
|
+
**kwds):
|
|
270
|
+
pass
|
qulab/scan/transforms.py
ADDED
qulab/scan/utils.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from concurrent.futures import Future
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def call_func_with_kwds(func, args, kwds, log=None):
|
|
6
|
+
funcname = getattr(func, '__name__', repr(func))
|
|
7
|
+
sig = inspect.signature(func)
|
|
8
|
+
for p in sig.parameters.values():
|
|
9
|
+
if p.kind == p.VAR_KEYWORD:
|
|
10
|
+
return func(*args, **kwds)
|
|
11
|
+
kw = {
|
|
12
|
+
k: v
|
|
13
|
+
for k, v in kwds.items()
|
|
14
|
+
if k in list(sig.parameters.keys())[len(args):]
|
|
15
|
+
}
|
|
16
|
+
try:
|
|
17
|
+
args = [
|
|
18
|
+
arg.result() if isinstance(arg, Future) else arg for arg in args
|
|
19
|
+
]
|
|
20
|
+
kw = {
|
|
21
|
+
k: v.result() if isinstance(v, Future) else v
|
|
22
|
+
for k, v in kw.items()
|
|
23
|
+
}
|
|
24
|
+
return func(*args, **kw)
|
|
25
|
+
except:
|
|
26
|
+
if log:
|
|
27
|
+
log.exception(f'Call {funcname} with {args} and {kw}')
|
|
28
|
+
raise
|
|
29
|
+
finally:
|
|
30
|
+
if log:
|
|
31
|
+
log.debug(f'Call {funcname} with {args} and {kw}')
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def try_to_call(x, args, kwds, log=None):
|
|
35
|
+
if callable(x):
|
|
36
|
+
return call_func_with_kwds(x, args, kwds, log)
|
|
37
|
+
return x
|
|
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()
|