QuLab 2.10.6__tar.gz → 2.10.8__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 (119) hide show
  1. {qulab-2.10.6 → qulab-2.10.8}/PKG-INFO +1 -1
  2. {qulab-2.10.6 → qulab-2.10.8}/QuLab.egg-info/PKG-INFO +1 -1
  3. {qulab-2.10.6 → qulab-2.10.8}/QuLab.egg-info/SOURCES.txt +1 -0
  4. {qulab-2.10.6 → qulab-2.10.8}/qulab/expression.py +36 -8
  5. {qulab-2.10.6 → qulab-2.10.8}/qulab/scan/query.py +13 -0
  6. {qulab-2.10.6 → qulab-2.10.8}/qulab/scan/scan.py +0 -1
  7. {qulab-2.10.6 → qulab-2.10.8}/qulab/scan/server.py +11 -9
  8. {qulab-2.10.6 → qulab-2.10.8}/qulab/scan/utils.py +7 -2
  9. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/zmq_socket.py +9 -2
  10. qulab-2.10.8/qulab/version.py +1 -0
  11. qulab-2.10.8/tests/test_dicttree.py +163 -0
  12. {qulab-2.10.6 → qulab-2.10.8}/tests/test_expression.py +2 -2
  13. qulab-2.10.6/qulab/version.py +0 -1
  14. {qulab-2.10.6 → qulab-2.10.8}/LICENSE +0 -0
  15. {qulab-2.10.6 → qulab-2.10.8}/MANIFEST.in +0 -0
  16. {qulab-2.10.6 → qulab-2.10.8}/QuLab.egg-info/dependency_links.txt +0 -0
  17. {qulab-2.10.6 → qulab-2.10.8}/QuLab.egg-info/entry_points.txt +0 -0
  18. {qulab-2.10.6 → qulab-2.10.8}/QuLab.egg-info/requires.txt +0 -0
  19. {qulab-2.10.6 → qulab-2.10.8}/QuLab.egg-info/top_level.txt +0 -0
  20. {qulab-2.10.6 → qulab-2.10.8}/README.md +0 -0
  21. {qulab-2.10.6 → qulab-2.10.8}/pyproject.toml +0 -0
  22. {qulab-2.10.6 → qulab-2.10.8}/qulab/__init__.py +0 -0
  23. {qulab-2.10.6 → qulab-2.10.8}/qulab/__main__.py +0 -0
  24. {qulab-2.10.6 → qulab-2.10.8}/qulab/cli/__init__.py +0 -0
  25. {qulab-2.10.6 → qulab-2.10.8}/qulab/cli/commands.py +0 -0
  26. {qulab-2.10.6 → qulab-2.10.8}/qulab/cli/config.py +0 -0
  27. {qulab-2.10.6 → qulab-2.10.8}/qulab/cli/decorators.py +0 -0
  28. {qulab-2.10.6 → qulab-2.10.8}/qulab/dicttree.py +0 -0
  29. {qulab-2.10.6 → qulab-2.10.8}/qulab/executor/__init__.py +0 -0
  30. {qulab-2.10.6 → qulab-2.10.8}/qulab/executor/analyze.py +0 -0
  31. {qulab-2.10.6 → qulab-2.10.8}/qulab/executor/cli.py +0 -0
  32. {qulab-2.10.6 → qulab-2.10.8}/qulab/executor/load.py +0 -0
  33. {qulab-2.10.6 → qulab-2.10.8}/qulab/executor/registry.py +0 -0
  34. {qulab-2.10.6 → qulab-2.10.8}/qulab/executor/schedule.py +0 -0
  35. {qulab-2.10.6 → qulab-2.10.8}/qulab/executor/storage.py +0 -0
  36. {qulab-2.10.6 → qulab-2.10.8}/qulab/executor/template.py +0 -0
  37. {qulab-2.10.6 → qulab-2.10.8}/qulab/executor/utils.py +0 -0
  38. {qulab-2.10.6 → qulab-2.10.8}/qulab/monitor/__init__.py +0 -0
  39. {qulab-2.10.6 → qulab-2.10.8}/qulab/monitor/__main__.py +0 -0
  40. {qulab-2.10.6 → qulab-2.10.8}/qulab/monitor/config.py +0 -0
  41. {qulab-2.10.6 → qulab-2.10.8}/qulab/monitor/dataset.py +0 -0
  42. {qulab-2.10.6 → qulab-2.10.8}/qulab/monitor/event_queue.py +0 -0
  43. {qulab-2.10.6 → qulab-2.10.8}/qulab/monitor/mainwindow.py +0 -0
  44. {qulab-2.10.6 → qulab-2.10.8}/qulab/monitor/monitor.py +0 -0
  45. {qulab-2.10.6 → qulab-2.10.8}/qulab/monitor/ploter.py +0 -0
  46. {qulab-2.10.6 → qulab-2.10.8}/qulab/monitor/qt_compat.py +0 -0
  47. {qulab-2.10.6 → qulab-2.10.8}/qulab/monitor/toolbar.py +0 -0
  48. {qulab-2.10.6 → qulab-2.10.8}/qulab/scan/__init__.py +0 -0
  49. {qulab-2.10.6 → qulab-2.10.8}/qulab/scan/curd.py +0 -0
  50. {qulab-2.10.6 → qulab-2.10.8}/qulab/scan/models.py +0 -0
  51. {qulab-2.10.6 → qulab-2.10.8}/qulab/scan/optimize.py +0 -0
  52. {qulab-2.10.6 → qulab-2.10.8}/qulab/scan/record.py +0 -0
  53. {qulab-2.10.6 → qulab-2.10.8}/qulab/scan/space.py +0 -0
  54. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/__init__.py +0 -0
  55. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/__main__.py +0 -0
  56. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/backend/__init__.py +0 -0
  57. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/backend/redis.py +0 -0
  58. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/base_dataset.py +0 -0
  59. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/chunk.py +0 -0
  60. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/dataset.py +0 -0
  61. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/file.py +0 -0
  62. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/models/__init__.py +0 -0
  63. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/models/base.py +0 -0
  64. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/models/config.py +0 -0
  65. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/models/file.py +0 -0
  66. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/models/ipy.py +0 -0
  67. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/models/models.py +0 -0
  68. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/models/record.py +0 -0
  69. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/models/report.py +0 -0
  70. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/models/tag.py +0 -0
  71. {qulab-2.10.6 → qulab-2.10.8}/qulab/storage/storage.py +0 -0
  72. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/__init__.py +0 -0
  73. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/chat.py +0 -0
  74. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/device/__init__.py +0 -0
  75. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/device/basedevice.py +0 -0
  76. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/device/loader.py +0 -0
  77. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/device/utils.py +0 -0
  78. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/drivers/FakeInstrument.py +0 -0
  79. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/drivers/__init__.py +0 -0
  80. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/ipy_events.py +0 -0
  81. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/net/__init__.py +0 -0
  82. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/net/bencoder.py +0 -0
  83. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/net/cli.py +0 -0
  84. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/net/dhcp.py +0 -0
  85. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/net/dhcpd.py +0 -0
  86. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/net/kad.py +0 -0
  87. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/net/kcp.py +0 -0
  88. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/net/nginx.py +0 -0
  89. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/progress.py +0 -0
  90. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/__init__.py +0 -0
  91. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/client.py +0 -0
  92. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/exceptions.py +0 -0
  93. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/msgpack.py +0 -0
  94. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/msgpack.pyi +0 -0
  95. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/router.py +0 -0
  96. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/rpc.py +0 -0
  97. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/serialize.py +0 -0
  98. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/server.py +0 -0
  99. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/socket.py +0 -0
  100. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/utils.py +0 -0
  101. {qulab-2.10.6 → qulab-2.10.8}/qulab/sys/rpc/worker.py +0 -0
  102. {qulab-2.10.6 → qulab-2.10.8}/qulab/tools/__init__.py +0 -0
  103. {qulab-2.10.6 → qulab-2.10.8}/qulab/tools/connection_helper.py +0 -0
  104. {qulab-2.10.6 → qulab-2.10.8}/qulab/typing.py +0 -0
  105. {qulab-2.10.6 → qulab-2.10.8}/qulab/utils.py +0 -0
  106. {qulab-2.10.6 → qulab-2.10.8}/qulab/visualization/__init__.py +0 -0
  107. {qulab-2.10.6 → qulab-2.10.8}/qulab/visualization/__main__.py +0 -0
  108. {qulab-2.10.6 → qulab-2.10.8}/qulab/visualization/_autoplot.py +0 -0
  109. {qulab-2.10.6 → qulab-2.10.8}/qulab/visualization/plot_circ.py +0 -0
  110. {qulab-2.10.6 → qulab-2.10.8}/qulab/visualization/plot_layout.py +0 -0
  111. {qulab-2.10.6 → qulab-2.10.8}/qulab/visualization/plot_seq.py +0 -0
  112. {qulab-2.10.6 → qulab-2.10.8}/qulab/visualization/qdat.py +0 -0
  113. {qulab-2.10.6 → qulab-2.10.8}/qulab/visualization/rot3d.py +0 -0
  114. {qulab-2.10.6 → qulab-2.10.8}/qulab/visualization/widgets.py +0 -0
  115. {qulab-2.10.6 → qulab-2.10.8}/setup.cfg +0 -0
  116. {qulab-2.10.6 → qulab-2.10.8}/setup.py +0 -0
  117. {qulab-2.10.6 → qulab-2.10.8}/src/qulab.h +0 -0
  118. {qulab-2.10.6 → qulab-2.10.8}/tests/test_kad.py +0 -0
  119. {qulab-2.10.6 → qulab-2.10.8}/tests/test_scan.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: QuLab
3
- Version: 2.10.6
3
+ Version: 2.10.8
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.4
2
2
  Name: QuLab
3
- Version: 2.10.6
3
+ Version: 2.10.8
4
4
  Summary: contral instruments and manage data
5
5
  Author-email: feihoo87 <feihoo87@gmail.com>
6
6
  Maintainer-email: feihoo87 <feihoo87@gmail.com>
@@ -110,6 +110,7 @@ qulab/visualization/qdat.py
110
110
  qulab/visualization/rot3d.py
111
111
  qulab/visualization/widgets.py
112
112
  src/qulab.h
113
+ tests/test_dicttree.py
113
114
  tests/test_expression.py
114
115
  tests/test_kad.py
115
116
  tests/test_scan.py
@@ -4,10 +4,11 @@ import operator
4
4
 
5
5
  import numpy as np
6
6
  from pyparsing import (CaselessKeyword, Combine, Forward, Group, Keyword,
7
- Literal, Optional, ParserElement, ParseResults,
8
- Suppress, Word, alphanums, alphas, delimitedList,
9
- infixNotation, nums, oneOf, opAssoc, pyparsing_common,
10
- restOfLine, srange, stringEnd, stringStart)
7
+ Literal, MatchFirst, Optional, ParserElement,
8
+ ParseResults, Regex, Suppress, Word, ZeroOrMore,
9
+ alphanums, alphas, delimitedList, infixNotation, nums,
10
+ oneOf, opAssoc, pyparsing_common, restOfLine, srange,
11
+ stringEnd, stringStart)
11
12
  from scipy import special
12
13
 
13
14
  # 启用 Packrat 优化以提高解析效率
@@ -37,7 +38,23 @@ def symbol_parse_action(t):
37
38
  return Symbol(t[0])
38
39
 
39
40
 
40
- SYMBOL = Word(alphas, alphanums + "_").setParseAction(symbol_parse_action)
41
+ SYMBOL = Word(alphas + "_",
42
+ alphanums + "_").setParseAction(symbol_parse_action)
43
+
44
+
45
+ # 定义查询语法:$a.b.c 或 $a.b 或 $a
46
+ def query_parse_action(t):
47
+ return Query(t[0])
48
+
49
+
50
+ attr_chain = ZeroOrMore(Combine(Literal('.') + SYMBOL))
51
+ dollar_named_chain = Combine(Literal('$') + SYMBOL + attr_chain)
52
+ dollar_dotN_chain = Combine(
53
+ Literal('$') + Regex(r'\.{1,}') + SYMBOL + attr_chain)
54
+ dollar_simple = Combine(Literal('$') + SYMBOL)
55
+
56
+ QUERY = MatchFirst([dollar_dotN_chain, dollar_named_chain,
57
+ dollar_simple]).setParseAction(lambda s, l, t: Query(t[0]))
41
58
 
42
59
  #------------------------------------------------------------------------------
43
60
  # 定义运算表达式的解析动作转换函数
@@ -97,7 +114,7 @@ expr = Forward()
97
114
  #------------------------------------------------------------------------------
98
115
  # 构造基元表达式:包括数值、标识符、括号内表达式
99
116
  atom = (
100
- FLOAT | INT | OCT | HEX | SYMBOL |
117
+ FLOAT | INT | OCT | HEX | SYMBOL | QUERY |
101
118
  (LPAREN + expr + RPAREN) # 注意:后面我们将使用递归定义 expr
102
119
  )
103
120
 
@@ -173,6 +190,7 @@ class Env():
173
190
  self.consts = {}
174
191
  self.variables = {}
175
192
  self.refs = {}
193
+ self.nested = {}
176
194
  self.functions = {
177
195
  'sin': np.sin,
178
196
  'cos': np.cos,
@@ -745,6 +763,15 @@ class Symbol(Expression):
745
763
  return self.name
746
764
 
747
765
 
766
+ class Query(Symbol):
767
+
768
+ def derivative(self, x):
769
+ return 0
770
+
771
+ def eval(self, env):
772
+ return super().eval(env)
773
+
774
+
748
775
  sin = Symbol('sin')
749
776
  cos = Symbol('cos')
750
777
  tan = Symbol('tan')
@@ -773,7 +800,7 @@ erf = Symbol('erf')
773
800
  erfc = Symbol('erfc')
774
801
 
775
802
 
776
- def calc(exp: str | Expression, **kwargs) -> Expression:
803
+ def calc(exp: str | Expression, env: Env = None, **kwargs) -> Expression:
777
804
  """
778
805
  Calculate the expression.
779
806
 
@@ -791,7 +818,8 @@ def calc(exp: str | Expression, **kwargs) -> Expression:
791
818
  Expression
792
819
  The calculated expression.
793
820
  """
794
- env = Env()
821
+ if env is None:
822
+ env = Env()
795
823
  for k, v in kwargs.items():
796
824
  env[k] = v
797
825
  if isinstance(exp, str):
@@ -372,3 +372,16 @@ def lookup_list(*, full=False):
372
372
  return __query_state.table['body']
373
373
  else:
374
374
  return [r[0] for r in __query_state.table['body']]
375
+
376
+
377
+ def ping(database=default_server, timeout=1, socket=None):
378
+ with ZMQContextManager(zmq.DEALER,
379
+ connect=database,
380
+ socket=socket,
381
+ timeout=timeout) as socket:
382
+
383
+ socket.send_pyobj({'method': 'ping'})
384
+ try:
385
+ return socket.recv_pyobj()
386
+ except zmq.Again:
387
+ raise TimeoutError(f"No response from server within {timeout} s")
@@ -1164,4 +1164,3 @@ def assymbly(description):
1164
1164
  _make_axis(description)
1165
1165
 
1166
1166
  return description
1167
- return description
@@ -23,15 +23,16 @@ from .models import Session, create_engine, create_tables, sessionmaker, utcnow
23
23
  from .record import BufferList, Record, random_path
24
24
  from .utils import dump_dict, load_dict
25
25
 
26
- try:
27
- default_record_port = int(os.getenv('QULAB_RECORD_PORT', 6789))
28
- except:
29
- default_record_port = 6789
30
-
31
- if os.getenv('QULAB_RECORD_PATH'):
32
- datapath = Path(os.getenv('QULAB_RECORD_PATH'))
33
- else:
34
- datapath = Path.home() / 'qulab' / 'data'
26
+ default_record_port = get_config_value('port',
27
+ int,
28
+ command_name='server',
29
+ default=6789)
30
+
31
+ datapath = get_config_value('data',
32
+ Path,
33
+ command_name='server',
34
+ default=Path.home() / 'qulab' / 'data')
35
+
35
36
  datapath.mkdir(parents=True, exist_ok=True)
36
37
 
37
38
  namespace = uuid.uuid4()
@@ -376,6 +377,7 @@ async def serv(port,
376
377
  url='',
377
378
  buffer_size=1024 * 1024 * 1024,
378
379
  interval=60):
380
+ datapath.mkdir(parents=True, exist_ok=True)
379
381
  logger.debug('Creating socket...')
380
382
  async with ZMQContextManager(zmq.ROUTER, bind=f"tcp://*:{port}") as sock:
381
383
  logger.info(f'Server started at port {port}.')
@@ -198,8 +198,13 @@ def yapf_reformat(cell_text):
198
198
  return '\n'.join(lines)
199
199
 
200
200
  cell_text = re.sub('^%', '#%#', cell_text, flags=re.M)
201
- reformated_text = unwrap(
202
- yapf.yapflib.yapf_api.FormatCode(wrap(isort.code(cell_text)))[0])
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])
203
208
  return re.sub('^#%#', '%', reformated_text, flags=re.M)
204
209
  except:
205
210
  return cell_text
@@ -99,7 +99,8 @@ class ZMQContextManager:
99
99
  secret_key: Optional[bytes] = None,
100
100
  public_key: Optional[bytes] = None,
101
101
  server_public_key: Optional[bytes] = None,
102
- socket: Optional[zmq.Socket] = None):
102
+ socket: Optional[zmq.Socket] = None,
103
+ timeout: Optional[float] = None):
103
104
  self.socket_type = socket_type
104
105
  if bind is None and connect is None:
105
106
  raise ValueError("Either 'bind' or 'connect' must be specified.")
@@ -110,6 +111,7 @@ class ZMQContextManager:
110
111
  self.secret_key = secret_key
111
112
  self.public_key = public_key
112
113
  self.server_public_key = server_public_key
114
+ self.timeout = timeout
113
115
 
114
116
  if secret_key_file:
115
117
  self.public_key, self.secret_key = zmq.auth.load_certificate(
@@ -150,7 +152,7 @@ class ZMQContextManager:
150
152
  if asyncio:
151
153
  self.context = zmq.asyncio.Context()
152
154
  else:
153
- self.context = zmq.Context.instance()
155
+ self.context = zmq.Context()
154
156
 
155
157
  self.socket = self.context.socket(self.socket_type)
156
158
  self.auth = None
@@ -175,6 +177,11 @@ class ZMQContextManager:
175
177
  if self.server_public_key:
176
178
  self.socket.curve_serverkey = self.server_public_key
177
179
  self.socket.connect(self.connect)
180
+ if self.timeout:
181
+ timeout_ms = int(self.timeout * 1000)
182
+ self.socket.setsockopt(zmq.RCVTIMEO, timeout_ms)
183
+ self.socket.setsockopt(zmq.SNDTIMEO, timeout_ms)
184
+ self.socket.setsockopt(zmq.LINGER, 0)
178
185
  return self.socket
179
186
 
180
187
  def reload_certificates(self):
@@ -0,0 +1 @@
1
+ __version__ = "2.10.8"
@@ -0,0 +1,163 @@
1
+ from qulab.dicttree import *
2
+
3
+ step1 = {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}}
4
+ step2 = {'a': {'x': 2}, 'b': {'x': 3, 'y': 5}, 'c': {'x': 15}, 'd': 1, 'e': 1}
5
+ step3 = {'a': {'x': 3, 'y': 2, 'p': {'w': 10}}, 'c': {'x': 16}, 'd': 1, 'e': 2}
6
+ step4 = {'a': {'x': 4, 'y': 2}, 'b': {'x': 6, 'y': 4}, 'c': {'x': 17}}
7
+
8
+ data = {
9
+ 'qubits': {
10
+ 'Q1': {
11
+ 'frequency': 3.5,
12
+ },
13
+ 'Q2': {
14
+ 'frequency': 3.6,
15
+ },
16
+ },
17
+ 'gate': {
18
+ 'pi2': {
19
+ 'Q1': {
20
+ 'freq': '$qubits.Q1.frequency',
21
+ 'amp': 0.5,
22
+ 'duration': '& 1/$.amp',
23
+ },
24
+ 'Q2': {
25
+ 'freq': '$....qubits.Q2.frequency',
26
+ 'amp': 0.6,
27
+ 'duration': '& sin(1/$.amp)',
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+
34
+ def test_flattenDict():
35
+ assert flattenDict({}) == {}
36
+ assert flattenDict(step1) == {'a.x': 1, 'a.y': 2, 'b.x': 3, 'b.y': 4}
37
+
38
+
39
+ def test_foldDict():
40
+ assert foldDict({}) == {}
41
+ assert foldDict(flattenDict(step1)) == step1
42
+
43
+
44
+ def test_diff():
45
+ assert diff({}, {}) == {}
46
+ assert diff(step1, step1) == {}
47
+ assert diff(step1, {}) == {'a': DELETE, 'b': DELETE}
48
+
49
+ d1 = diff({}, step1)
50
+ assert isinstance(d1['a'], Create) and d1['a'].n == {
51
+ 'x': 1,
52
+ 'y': 2
53
+ } and d1['a'].replace == False
54
+ assert isinstance(d1['b'], Create) and d1['b'].n == {
55
+ 'x': 3,
56
+ 'y': 4
57
+ } and d1['b'].replace == False
58
+
59
+
60
+ def test_patch():
61
+ assert patch(step1, {}) == step1
62
+ assert patch(step1, diff(step1, {})) == {}
63
+ assert patch({}, diff({}, step1)) == step1
64
+
65
+ test = {
66
+ 'a': 1,
67
+ 'b': 2,
68
+ 'c': {
69
+ 'x': 3
70
+ },
71
+ 'd': {
72
+ 'y': 4
73
+ },
74
+ 'e': {
75
+ 'x': 1,
76
+ 'y': 4
77
+ }
78
+ }
79
+ patch(test, {
80
+ 'a': Update(1, 10),
81
+ 'b': DELETE,
82
+ 'c': Create({'z': 12}, replace=True),
83
+ 'd': {
84
+ 'x': Create(5),
85
+ 'y': Update(4, 40)
86
+ },
87
+ 'e': Create({
88
+ 'x': 2,
89
+ 'z': 13
90
+ })
91
+ },
92
+ in_place=True)
93
+
94
+ assert test == {
95
+ 'a': 10,
96
+ 'c': {
97
+ 'z': 12
98
+ },
99
+ 'd': {
100
+ 'x': 5,
101
+ 'y': 40
102
+ },
103
+ 'e': {
104
+ 'x': 2,
105
+ 'y': 4,
106
+ 'z': 13
107
+ }
108
+ }
109
+
110
+ d1 = diff(step1, step2)
111
+ d2 = diff(step2, step3)
112
+ d3 = diff(step3, step4)
113
+
114
+ assert patch(step1, d1) == step2
115
+ assert patch(step2, d2) == step3
116
+ assert patch(step3, d3) == step4
117
+
118
+
119
+ def test_merge():
120
+ d1 = diff(step1, step2)
121
+ d2 = diff(step2, step3)
122
+ d3 = diff(step3, step4)
123
+
124
+ assert merge(d1, d2, origin=step1) == diff(step1, step3)
125
+ assert merge(d2, d3, origin=step2) == diff(step2, step4)
126
+
127
+ assert patch(step1, merge(d1, d2)) == step3
128
+ assert patch(step1, merge(merge(d1, d2), d3)) == step4
129
+ assert patch(step1, merge(d1, merge(d2, d3))) == step4
130
+
131
+
132
+ def test_query():
133
+ assert query_tree('a', step3) == {'x': 3, 'y': 2, 'p': {'w': 10}}
134
+ assert query_tree('a.p', step3) == {'w': 10}
135
+ assert query_tree('a.p.w', step3) == 10
136
+ assert query_tree('a.p.w', step1) == (NOTSET, 'a.p')
137
+
138
+
139
+ def test_ref():
140
+ assert query_tree('gate.pi2.Q1.freq', data) == 3.5
141
+ assert query_tree('gate.pi2.Q2.freq', data) == 3.6
142
+
143
+
144
+ # def test_eval():
145
+ # assert query_tree('gate.pi2.Q1.duration', data) == 2.0
146
+ # assert query_tree('gate.pi2.Q2.duration', data) == 0.9954079577517649
147
+
148
+
149
+ def test_print():
150
+ import io
151
+ buf = io.StringIO()
152
+
153
+ d1 = diff(step1, step3)
154
+ print_diff(d1, file=buf)
155
+
156
+ buf.seek(0)
157
+ assert buf.read() == (
158
+ "a.x Update: 1 ==> 3\n"
159
+ "a.p Create: {'w': 10}\n"
160
+ "c Create: {'x': 16}\n"
161
+ "d Create: 1\n"
162
+ "e Create: 2\n"
163
+ "b Delete\n")
@@ -162,10 +162,10 @@ def test_environment():
162
162
  env = Env()
163
163
  # 在自定义环境中绑定变量
164
164
  env["x"] = 10
165
- result = calc("x+5", x=env["x"])
165
+ result = calc("x+5", env)
166
166
  assert result == 15, "通过环境变量传值x=10,应得15"
167
167
 
168
168
  # 绑定新变量并验证其值
169
169
  env["y"] = 20
170
- result = calc("x+y", x=env["x"], y=env["y"])
170
+ result = calc("x+y", env)
171
171
  assert result == 30, "x+y 应为30,当x=10且y=20"
@@ -1 +0,0 @@
1
- __version__ = "2.10.6"
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