QuLab 2.2.5__cp310-cp310-win_amd64.whl → 2.2.7__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: QuLab
3
- Version: 2.2.5
3
+ Version: 2.2.7
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,7 +1,7 @@
1
1
  qulab/__init__.py,sha256=vkFybY8YSsQilYdThPRD83-btPAR41sy_WCXiM-6mME,141
2
2
  qulab/__main__.py,sha256=V7iokU7awstgjCeiF_hoOdFyrqJwC_4QetiLe7cWvOQ,454
3
- qulab/fun.cp310-win_amd64.pyd,sha256=d4aqvLqQ5WVKcuN66HtihBH0jArVgGq8j5CYYQ1YLls,31744
4
- qulab/version.py,sha256=zyH0HuxKprjHeDzaU3CDFspw9f0RqC0qcLriAPqWD_M,21
3
+ qulab/fun.cp310-win_amd64.pyd,sha256=HhDHwlovmbtFML-GZmXElJ4iouH5WffpId7e6GRBf1s,31744
4
+ qulab/version.py,sha256=I501tBgxLlOMpveUyk065aIcjgpxqCi7zjY3gqoar7c,21
5
5
  qulab/monitor/__init__.py,sha256=xEVDkJF8issrsDeLqQmDsvtRmrf-UiViFcGTWuzdlFU,43
6
6
  qulab/monitor/__main__.py,sha256=k2H1H5Zf9LLXTDLISJkbikLH-z0f1e5i5i6wXXYPOrE,105
7
7
  qulab/monitor/config.py,sha256=y_5StMkdrbZO1ziyKBrvIkB7Jclp9RCPK1QbsOhCxnY,785
@@ -17,10 +17,10 @@ qulab/scan/curd.py,sha256=yaTglGiS6mlk0GqDHi_w8T02XGBMvDZtXSdML7zDywk,7117
17
17
  qulab/scan/expression.py,sha256=vwUM9E0OFQal4bljlUtLR3NJu4zGRyuWYrdyZSs3QTU,16199
18
18
  qulab/scan/models.py,sha256=ZvXkJEt5Yz3Sjx0JKzYka-q2Uo-w_iVzHgH8A6DbjF0,18236
19
19
  qulab/scan/optimize.py,sha256=MlT4y422CnP961IR384UKryyZh8riNvrPSd2z_MXLEg,2356
20
- qulab/scan/query.py,sha256=z94Ofbii4HZ4ZyZ7nos9-y37bH8-Xg4mA3QsF_aWx-c,11907
21
- qulab/scan/record.py,sha256=crlNIm1ki6td2Z284D78M276aso7KhMnr4qjCCOj1Kk,21644
22
- qulab/scan/scan.py,sha256=CNX2Z6vWMax9SqBWWYLghkz6TwIaLNnKypeyS7UCTfA,35773
23
- qulab/scan/server.py,sha256=ZWTnlK_YMfPTCoq6GnGpsZzSFGyoO4qF7aEGW9wCwhM,14542
20
+ qulab/scan/query.py,sha256=RM8bG4Tcx_PaNk8tv9HdlTZ1dGuuSr3sZVkYVq2BtfQ,12183
21
+ qulab/scan/record.py,sha256=aBpUllhKsBRhPOwZwsp3rcw2HB-3ne9yLYHLBeXXM-M,21669
22
+ qulab/scan/scan.py,sha256=hYTEEa4frIN6HraNleoytnCZjZ0c_XWOI1DSLchkpuE,37589
23
+ qulab/scan/server.py,sha256=GTV9wzlFTmG6YUj_8WwR4e6uvaq9AgdearLh3i3YAfw,14569
24
24
  qulab/scan/space.py,sha256=fWsY99HDauk89f5ygqnJYBoeNFGTUkAGFssrw-YMHok,5453
25
25
  qulab/scan/utils.py,sha256=30qnYvyFyctwcWxOCUpCNxXgGysA7xdIDzYbjwxGUzA,3744
26
26
  qulab/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -70,7 +70,7 @@ qulab/sys/rpc/server.py,sha256=W3bPwe8um1IeR_3HLx-ad6iCcbeuUQcSg11Ze4w6DJg,742
70
70
  qulab/sys/rpc/socket.py,sha256=W3bPwe8um1IeR_3HLx-ad6iCcbeuUQcSg11Ze4w6DJg,742
71
71
  qulab/sys/rpc/utils.py,sha256=BurIcqh8CS-Hsk1dYP6IiefK4qHivaEqD9_rBY083SA,619
72
72
  qulab/sys/rpc/worker.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
- qulab/sys/rpc/zmq_socket.py,sha256=SHMCp5oawYglfawuvDDTJJrQtxFpErlBtvoEwd61OO0,8362
73
+ qulab/sys/rpc/zmq_socket.py,sha256=aoIm-C-IdJjm9_PQXckvbqTxc9kCeJrT4PyYytoDIHo,8492
74
74
  qulab/visualization/__init__.py,sha256=Bkt9AK5c45d6HFLlT-f8cIppywXziHtJqhDtVxOoKKo,6317
75
75
  qulab/visualization/__main__.py,sha256=WduINFl21B-XMsi2rg2cVhIyU11hKKX3zOsjc56QLiQ,1710
76
76
  qulab/visualization/_autoplot.py,sha256=JFLR3e71bryPaUkOCWFzD9C4Nk-ulqIdBb1YN4QnZic,14562
@@ -78,9 +78,9 @@ qulab/visualization/plot_layout.py,sha256=yAnMONOms7_szCdng-8wPpUMPis5UnbaNNzV4K
78
78
  qulab/visualization/plot_seq.py,sha256=h9D0Yl_yO64IwlvBgzMu9EBKr9gg6y8QE55gu2PfTns,2783
79
79
  qulab/visualization/qdat.py,sha256=HubXFu4nfcA7iUzghJGle1C86G6221hicLR0b-GqhKQ,5887
80
80
  qulab/visualization/widgets.py,sha256=HcYwdhDtLreJiYaZuN3LfofjJmZcLwjMfP5aasebgDo,3266
81
- QuLab-2.2.5.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
82
- QuLab-2.2.5.dist-info/METADATA,sha256=BspoYai-nQ5IQpf_AqvzYlKLZ3QZwUfDbw9Cz_73yME,3609
83
- QuLab-2.2.5.dist-info/WHEEL,sha256=lO6CqtLHCAi38X3Es1a4R1lAjZFvN010IMRCFo2S7Mc,102
84
- QuLab-2.2.5.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
85
- QuLab-2.2.5.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
86
- QuLab-2.2.5.dist-info/RECORD,,
81
+ QuLab-2.2.7.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
82
+ QuLab-2.2.7.dist-info/METADATA,sha256=uMz3KTAANhe7RMJa0Y-Q0LXISTG98aYohmRRA05bSK4,3609
83
+ QuLab-2.2.7.dist-info/WHEEL,sha256=lO6CqtLHCAi38X3Es1a4R1lAjZFvN010IMRCFo2S7Mc,102
84
+ QuLab-2.2.7.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
85
+ QuLab-2.2.7.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
86
+ QuLab-2.2.7.dist-info/RECORD,,
Binary file
qulab/scan/query.py CHANGED
@@ -16,9 +16,13 @@ from .scan import default_server
16
16
  from .server import get_local_record
17
17
 
18
18
 
19
- def get_record(id, database=default_server) -> Record:
19
+ def get_record(id,
20
+ database=default_server,
21
+ socket=None,
22
+ session=None) -> Record:
20
23
  if isinstance(database, str) and database.startswith('tcp://'):
21
- with ZMQContextManager(zmq.DEALER, connect=database) as socket:
24
+ with ZMQContextManager(zmq.DEALER, connect=database,
25
+ socket=socket) as socket:
22
26
  socket.send_pyobj({
23
27
  'method': 'record_description',
24
28
  'record_id': id
@@ -29,12 +33,16 @@ def get_record(id, database=default_server) -> Record:
29
33
  d.id = id
30
34
  d.database = database
31
35
  d._file = None
36
+ d._sock = socket
32
37
  return d
33
38
  else:
34
- db_file = Path(database) / 'data.db'
35
- engine = create_engine(f'sqlite:///{db_file}')
36
- Session = sessionmaker(bind=engine)
37
- with Session() as session:
39
+ if session is None:
40
+ db_file = Path(database) / 'data.db'
41
+ engine = create_engine(f'sqlite:///{db_file}')
42
+ Session = sessionmaker(bind=engine)
43
+ with Session() as session:
44
+ return get_local_record(session, id, database)
45
+ else:
38
46
  return get_local_record(session, id, database)
39
47
 
40
48
 
qulab/scan/record.py CHANGED
@@ -56,6 +56,7 @@ class BufferList():
56
56
  self._slice = slice
57
57
  self._lock = Lock()
58
58
  self._data_id = None
59
+ self._sock = None
59
60
 
60
61
  def __repr__(self):
61
62
  return f"<BufferList: shape={self.shape}, lu={self.lu}, rd={self.rd}, slice={self._slice}>"
@@ -82,6 +83,7 @@ class BufferList():
82
83
  self._slice = None
83
84
  self._lock = Lock()
84
85
  self._data_id = None
86
+ self._sock = None
85
87
 
86
88
  @property
87
89
  def shape(self):
@@ -156,7 +158,9 @@ class BufferList():
156
158
  yield pos, value
157
159
  else:
158
160
  server, record_id, key = self._data_id
159
- with ZMQContextManager(zmq.DEALER, connect=server) as socket:
161
+ with ZMQContextManager(zmq.DEALER,
162
+ connect=server,
163
+ socket=self._sock) as socket:
160
164
  iter_id = b''
161
165
  start = 0
162
166
  try:
@@ -200,7 +204,7 @@ class BufferList():
200
204
  d.append(value)
201
205
  return p, d
202
206
 
203
- def array(self):
207
+ def toarray(self):
204
208
  pos, data = self.items()
205
209
  if self._slice:
206
210
  pos = np.asarray(pos)
@@ -294,7 +298,7 @@ class BufferList():
294
298
  def __getitem__(self, slice_tuple: slice | EllipsisType
295
299
  | tuple[slice | int | EllipsisType, ...]):
296
300
  self._slice, contract, reversed = self._full_slice(slice_tuple)
297
- ret = self.array()
301
+ ret = self.toarray()
298
302
  slices = []
299
303
  for i, s in enumerate(self._slice):
300
304
  if i in contract:
@@ -319,6 +323,7 @@ class Record():
319
323
  self._pos = []
320
324
  self._last_vars = set()
321
325
  self._file = None
326
+ self._sock = None
322
327
 
323
328
  for name, value in self.description['intrinsic_loops'].items():
324
329
  self._items[name] = value
@@ -348,6 +353,7 @@ class Record():
348
353
  self._last_vars = set()
349
354
  self.database = None
350
355
  self._file = None
356
+ self._sock = None
351
357
 
352
358
  @property
353
359
  def axis(self):
@@ -361,7 +367,8 @@ class Record():
361
367
  return cls(config_id)
362
368
  if self.is_remote_record():
363
369
  with ZMQContextManager(zmq.DEALER,
364
- connect=self.database) as socket:
370
+ connect=self.database,
371
+ socket=self._sock) as socket:
365
372
  socket.send_pyobj({
366
373
  'method': 'config_get',
367
374
  'config_id': config_id
@@ -375,6 +382,31 @@ class Record():
375
382
  session.commit()
376
383
  return cls(config)
377
384
 
385
+ def scripts(self, session=None):
386
+ scripts = self.description['entry']['scripts']
387
+ if isinstance(scripts, list):
388
+ return scripts
389
+ else:
390
+ cell_id = scripts
391
+
392
+ if self.is_remote_record():
393
+ with ZMQContextManager(zmq.DEALER,
394
+ connect=self.database,
395
+ socket=self._sock) as socket:
396
+ socket.send_pyobj({
397
+ 'method': 'notebook_history',
398
+ 'cell_id': cell_id
399
+ })
400
+ return socket.recv_pyobj()
401
+ elif self.is_local_record():
402
+ from .models import Cell
403
+ assert session is not None, "session is required for local record"
404
+ cell = session.get(Cell, cell_id)
405
+ return [
406
+ cell.input.text
407
+ for cell in cell.notebook.cells[1:cell.index + 2]
408
+ ]
409
+
378
410
  def is_local_record(self):
379
411
  return not self.is_cache_record() and not self.is_remote_record()
380
412
 
@@ -389,15 +421,13 @@ class Record():
389
421
  self.flush()
390
422
 
391
423
  def __getitem__(self, key):
392
- ret = self.get(key, buffer_to_array=True)
393
- if isinstance(ret, Space):
394
- ret = ret.toarray()
395
- return ret
424
+ return self.get(key, buffer_to_array=True)
396
425
 
397
- def get(self, key, default=_not_given, buffer_to_array=False, slice=None):
426
+ def get(self, key, default=_not_given, buffer_to_array=False):
398
427
  if self.is_remote_record():
399
428
  with ZMQContextManager(zmq.DEALER,
400
- connect=self.database) as socket:
429
+ connect=self.database,
430
+ socket=self._sock) as socket:
401
431
  socket.send_pyobj({
402
432
  'method': 'record_getitem',
403
433
  'record_id': self.id,
@@ -405,25 +435,14 @@ class Record():
405
435
  })
406
436
  ret = socket.recv_pyobj()
407
437
  if isinstance(ret, BufferList):
408
- if buffer_to_array:
409
- socket.send_pyobj({
410
- 'method': 'bufferlist_slice',
411
- 'record_id': self.id,
412
- 'key': key,
413
- 'slice': slice
414
- })
415
- lst = socket.recv_pyobj()
416
- ret._list = lst
417
- ret._slice = slice
418
- return ret.array()
419
- else:
420
- ret._data_id = self.database, self.id, key
421
- return ret
422
- elif isinstance(ret, Space):
438
+ ret._data_id = self.database, self.id, key
439
+ ret._sock = socket
423
440
  if buffer_to_array:
424
441
  return ret.toarray()
425
442
  else:
426
443
  return ret
444
+ elif isinstance(ret, Space) and buffer_to_array:
445
+ return ret.toarray()
427
446
  else:
428
447
  return ret
429
448
  else:
@@ -434,9 +453,8 @@ class Record():
434
453
  if isinstance(d, BufferList):
435
454
  if isinstance(d.file, str):
436
455
  d.file = self._file.parent.parent.parent.parent / d.file
437
- d._slice = slice
438
456
  if buffer_to_array:
439
- return d.array()
457
+ return d.toarray()
440
458
  else:
441
459
  return d
442
460
  elif isinstance(d, Space):
@@ -450,7 +468,8 @@ class Record():
450
468
  def keys(self):
451
469
  if self.is_remote_record():
452
470
  with ZMQContextManager(zmq.DEALER,
453
- connect=self.database) as socket:
471
+ connect=self.database,
472
+ socket=self._sock) as socket:
454
473
  socket.send_pyobj({
455
474
  'method': 'record_keys',
456
475
  'record_id': self.id
@@ -517,7 +536,8 @@ class Record():
517
536
  def delete(self):
518
537
  if self.is_remote_record():
519
538
  with ZMQContextManager(zmq.DEALER,
520
- connect=self.database) as socket:
539
+ connect=self.database,
540
+ socket=self._sock) as socket:
521
541
  socket.send_pyobj({
522
542
  'method': 'record_delete',
523
543
  'record_id': self.id
@@ -553,35 +573,14 @@ class Record():
553
573
  with z.open('config.pkl', 'w') as f:
554
574
  f.write(dill.dumps(self.config()))
555
575
 
556
- def scripts(self, session=None):
557
- scripts = self.description['entry']['scripts']
558
- if isinstance(scripts, list):
559
- return scripts
560
- else:
561
- cell_id = scripts
562
-
563
- if self.is_remote_record():
564
- with ZMQContextManager(zmq.DEALER,
565
- connect=self.database) as socket:
566
- socket.send_pyobj({
567
- 'method': 'notebook_history',
568
- 'cell_id': cell_id
569
- })
570
- return socket.recv_pyobj()
571
- elif self.is_local_record():
572
- from .models import Cell
573
- assert session is not None, "session is required for local record"
574
- cell = session.get(Cell, cell_id)
575
- return [
576
- cell.input.text
577
- for cell in cell.notebook.cells[1:cell.index + 2]
578
- ]
579
-
580
576
  @classmethod
581
577
  def load(cls, file: str):
582
578
  with zipfile.ZipFile(file, 'r') as z:
583
579
  with z.open('record.pkl', 'r') as f:
584
580
  description, items = dill.load(f)
581
+ with z.open('config.pkl', 'r') as f:
582
+ config = dill.load(f)
583
+ description['config'] = config
585
584
  record = cls(None, None, description)
586
585
  for key, value in items.items():
587
586
  if isinstance(value, BufferList):
qulab/scan/scan.py CHANGED
@@ -310,7 +310,10 @@ class Scan():
310
310
  self._main_task.cancel()
311
311
  except:
312
312
  pass
313
- self._executors.shutdown()
313
+ try:
314
+ self._executors.shutdown()
315
+ except:
316
+ pass
314
317
 
315
318
  @property
316
319
  def current_level(self):
@@ -323,7 +326,7 @@ class Scan():
323
326
  async def _emit(self, current_level, step, position, variables: dict[str,
324
327
  Any]):
325
328
  for key, value in list(variables.items()):
326
- if key.startswith('*'):
329
+ if key.startswith('*') or ',' in key:
327
330
  await _unpack(key, variables)
328
331
  elif inspect.isawaitable(value) and not self.hiden(key):
329
332
  variables[key] = await value
@@ -356,8 +359,8 @@ class Scan():
356
359
  self._hide_pattern_re = re.compile('|'.join(self.description['hiden']))
357
360
 
358
361
  def hiden(self, name: str) -> bool:
359
- return bool(
360
- self._hide_pattern_re.match(name)) and not name.startswith('*')
362
+ return bool(self._hide_pattern_re.match(name)) or name.startswith(
363
+ '*') or ',' in name
361
364
 
362
365
  async def _filter(self, variables: dict[str, Any], level: int = 0):
363
366
  try:
@@ -444,6 +447,11 @@ class Scan():
444
447
  except:
445
448
  pass
446
449
  self.description['consts'][name] = value
450
+
451
+ if ',' in name:
452
+ for key in name.split(','):
453
+ if not key.startswith('*'):
454
+ self.add_depends(key, [name])
447
455
  if setter:
448
456
  self.description['setters'][name] = setter
449
457
 
@@ -555,9 +563,9 @@ class Scan():
555
563
  if isinstance(
556
564
  self.description['database'],
557
565
  str) and self.description['database'].startswith("tcp://"):
558
- async with ZMQContextManager(
559
- zmq.DEALER,
560
- connect=self.description['database']) as socket:
566
+ async with ZMQContextManager(zmq.DEALER,
567
+ connect=self.description['database'],
568
+ socket=self._sock) as socket:
561
569
  self._sock = socket
562
570
  await self._run()
563
571
  else:
@@ -624,7 +632,9 @@ class Scan():
624
632
 
625
633
  async def submit(self, server=default_executor):
626
634
  assymbly(self.description)
627
- async with ZMQContextManager(zmq.DEALER, connect=server) as socket:
635
+ async with ZMQContextManager(zmq.DEALER,
636
+ connect=server,
637
+ socket=self._sock) as socket:
628
638
  await socket.send_pyobj({
629
639
  'method': 'task_submit',
630
640
  'description': dill.dumps(self.description)
@@ -901,7 +911,10 @@ def assymbly(description):
901
911
  axis[name] = tuple(sorted(d))
902
912
  else:
903
913
  axis[name] = tuple(sorted(set(axis[name]) | d))
904
- description['axis'] = axis
914
+ description['axis'] = {
915
+ k: tuple([x for x in v if x >= 0])
916
+ for k, v in axis.items()
917
+ }
905
918
  description['independent_variables'] = independent_variables
906
919
 
907
920
  return description
@@ -972,7 +985,7 @@ async def _iter_level(variables,
972
985
 
973
986
  if opts:
974
987
  for key in list(variables.keys()):
975
- if key.startswith('*'):
988
+ if key.startswith('*') or ',' in key:
976
989
  await _unpack(key, variables)
977
990
 
978
991
  for name, opt in opts.items():
@@ -1024,7 +1037,8 @@ async def _unpack(key, variables):
1024
1037
  if inspect.isawaitable(x):
1025
1038
  x = await x
1026
1039
  if key.startswith('**'):
1027
- assert isinstance(x, dict), f"Should promise a dict for `**` symbol."
1040
+ assert isinstance(
1041
+ x, dict), f"Should promise a dict for `**` symbol. {key}"
1028
1042
  if "{key}" in key:
1029
1043
  for k, v in x.items():
1030
1044
  variables[key[2:].format(key=k)] = v
@@ -1033,10 +1047,44 @@ async def _unpack(key, variables):
1033
1047
  elif key.startswith('*'):
1034
1048
  assert isinstance(
1035
1049
  x, (list, tuple,
1036
- np.ndarray)), f"Should promise a list for `*` symbol."
1050
+ np.ndarray)), f"Should promise a list for `*` symbol. {key}"
1037
1051
  for i, v in enumerate(x):
1038
1052
  k = key[1:].format(i=i)
1039
1053
  variables[k] = v
1054
+ elif ',' in key:
1055
+ keys1, keys2 = [], []
1056
+ args = None
1057
+ for k in key.split(','):
1058
+ if k.startswith('*'):
1059
+ if args is None:
1060
+ args = k
1061
+ else:
1062
+ raise ValueError(f'Only one `*` symbol is allowed. {key}')
1063
+ elif args is None:
1064
+ keys1.append(k)
1065
+ else:
1066
+ keys2.append(k)
1067
+ assert isinstance(
1068
+ x,
1069
+ (list, tuple,
1070
+ np.ndarray)), f"Should promise a list for multiple symbols. {key}"
1071
+ if args is None:
1072
+ assert len(keys1) == len(
1073
+ x), f"Length of keys and values should be equal. {key}"
1074
+ for k, v in zip(keys1, x):
1075
+ variables[k] = v
1076
+ else:
1077
+ assert len(keys1) + len(keys2) <= len(
1078
+ x), f"Too many values for unpacking. {key}"
1079
+ for k, v in zip(keys1, x[:len(keys1)]):
1080
+ variables[k] = v
1081
+ end = -len(keys2) if keys2 else None
1082
+ for i, v in enumerate(x[len(keys1):end]):
1083
+ k = args[1:].format(i=i)
1084
+ variables[k] = v
1085
+ if keys2:
1086
+ for k, v in zip(keys2, x[end:]):
1087
+ variables[k] = v
1040
1088
  else:
1041
1089
  return
1042
1090
  del variables[key]
qulab/scan/server.py CHANGED
@@ -161,8 +161,9 @@ async def handle(session: Session, request: Request, datapath: Path):
161
161
  iter_id = uuid.uuid3(namespace, str(time.time_ns())).bytes
162
162
  record = get_record(session, msg['record_id'], datapath)
163
163
  bufferlist = record.get(msg['key'],
164
- buffer_to_array=False,
165
- slice=msg['slice'])
164
+ buffer_to_array=False)
165
+ if msg['slice']:
166
+ bufferlist._slice = msg['slice']
166
167
  it = bufferlist.iter()
167
168
  for _, _ in zip(range(msg['start']), it):
168
169
  pass
@@ -130,7 +130,12 @@ class ZMQContextManager:
130
130
  self.auth = None
131
131
  self.context = None
132
132
  self.socket = None
133
- self._external_socket = socket
133
+ self._external_socket = None
134
+ try:
135
+ if not socket.closed:
136
+ self._external_socket = socket
137
+ except:
138
+ pass
134
139
 
135
140
  def _create_socket(self, asyncio=False) -> zmq.Socket:
136
141
  """
qulab/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "2.2.5"
1
+ __version__ = "2.2.7"
File without changes
File without changes