qlsdk2 0.6.0a2__py3-none-any.whl → 0.6.0a4__py3-none-any.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.
@@ -50,7 +50,8 @@ class RscPacket(Packet):
50
50
  for i in range(ch_num)
51
51
  ]
52
52
 
53
- # logger.trace(self)
53
+ logger.trace(packet)
54
+
54
55
  return packet
55
56
 
56
57
  def __str__(self):
@@ -71,24 +72,34 @@ class RscPacket(Packet):
71
72
  class ImpedancePacket(Packet):
72
73
  def __init__(self):
73
74
  super().__init__()
74
- self.data_len = None
75
75
  self.impedance = None
76
76
 
77
- def transfer(self, body:bytes) -> 'ImpedancePacket':
78
- self.time_stamp = int.from_bytes(body[0:8], 'little')
79
- self.result = body[8]
80
- self.pkg_id = int.from_bytes(body[9: 13], 'little')
81
- self.channels = to_channels(body[13: 45])
82
-
83
- logger.debug(f"impedance: {self}")
77
+ @staticmethod
78
+ def transfer(body:bytes) -> 'ImpedancePacket':
79
+ packet = ImpedancePacket()
80
+ packet.time_stamp = int.from_bytes(body[0:8], 'little')
81
+ # packet.result = body[8]
82
+ packet.pkg_id = int.from_bytes(body[9: 13], 'little')
83
+ packet.channels = to_channels(body[13: 45])
84
+ # packet.sample_rate = int.from_bytes(body[45: 49], 'little')
85
+ # packet.sample_len = int.from_bytes(body[49: 53], 'little')
86
+ # packet.resolution = int(int(body[53]) / 8)
87
+ # packet.filter = int(int(body[54]) / 8)
88
+ # packet.wave_type = int(int(body[55]) / 8)
89
+ # packet.wave_freq = int.from_bytes(body[56: 60], 'little')
90
+ # packet.data_len = int.from_bytes(body[60: 64], 'little')
91
+ b_impedance = body[64:]
92
+ packet.impedance = [int.from_bytes(b_impedance[j * 4 : j * 4 + 4], 'little', signed=False) for j in range(len(packet.channels))]
93
+
94
+ logger.trace(f"impedance: {packet}")
84
95
 
96
+ return packet
97
+
85
98
  def __str__(self):
86
99
  return f"""
87
100
  time_stamp: {self.time_stamp}
88
101
  pkg_id: {self.pkg_id}
89
- result: {self.result}
90
102
  channels: {self.channels}
91
- data len: {self.data_len}
92
103
  impedance: {self.impedance}
93
104
  """
94
105
 
@@ -161,4 +172,40 @@ class C256RSPacket(Packet):
161
172
  offset += 4 + channel_size * packet.resolution
162
173
 
163
174
  logger.trace(packet)
164
- return packet
175
+ return packet
176
+
177
+
178
+ class C256ImpedancePacket(Packet):
179
+ def __init__(self):
180
+ super().__init__()
181
+ self.impedance = None
182
+
183
+ @staticmethod
184
+ def transfer(body:bytes) -> 'ImpedancePacket':
185
+ packet = ImpedancePacket()
186
+ packet.time_stamp = int.from_bytes(body[0:8], 'little')
187
+ # packet.result = body[8]
188
+ packet.pkg_id = int.from_bytes(body[9: 13], 'little')
189
+ packet.channels = to_channels(body[13: 45])
190
+ # packet.sample_rate = int.from_bytes(body[45: 49], 'little')
191
+ # packet.sample_len = int.from_bytes(body[49: 53], 'little')
192
+ # packet.resolution = int(int(body[53]) / 8)
193
+ # packet.filter = int(int(body[54]) / 8)
194
+ # packet.wave_type = int(int(body[55]) / 8)
195
+ # packet.wave_freq = int.from_bytes(body[56: 60], 'little')
196
+ # packet.data_len = int.from_bytes(body[60: 64], 'little')
197
+ b_impedance = body[64:]
198
+ packet.impedance = [int.from_bytes(b_impedance[j : j + 4], 'little', signed=False) for j in range(len(packet.channels))]
199
+
200
+ logger.trace(f"impedance: {packet}")
201
+
202
+ def __str__(self):
203
+ return f"""
204
+ time_stamp: {self.time_stamp}
205
+ pkg_id: {self.pkg_id}
206
+ result: {self.result}
207
+ channels: {self.channels}
208
+ data len: {self.data_len}
209
+ impedance: {self.impedance}
210
+ """
211
+
qlsdk/persist/rsc_edf.py CHANGED
@@ -15,7 +15,7 @@ EDF_FILE_TYPE = {
15
15
  }
16
16
 
17
17
  class EDFStreamWriter(Thread):
18
- def __init__(self, channels, sample_frequency, physical_max, digital_min, file_type, file_path, record_duration=None):
18
+ def __init__(self, channels, sample_frequency, physical_max, physical_min, file_type, file_path, record_duration=None):
19
19
 
20
20
  super().__init__()
21
21
  self._writer : EdfWriter = None
@@ -32,7 +32,7 @@ class EDFStreamWriter(Thread):
32
32
  self._n_channels = len(channels)
33
33
  self.sample_frequency = sample_frequency
34
34
  self.physical_max = physical_max
35
- self.physical_min = digital_min
35
+ self.physical_min = physical_min
36
36
  # 和位数相关,edf 16 bits/bdf 24 bits
37
37
  self.digital_max = 8388607 if file_type == EDF_FILE_TYPE['bdf'] else 32767
38
38
  self.digital_min = -8388608 if file_type == EDF_FILE_TYPE['bdf'] else -32768
@@ -46,6 +46,7 @@ class EDFStreamWriter(Thread):
46
46
  self.equipment = "equipment"
47
47
  self.patient_code = "patient_code"
48
48
  self.patient_name = "patient_name"
49
+ logger.info(f'digital_max:{self.digital_max}, digital_min:{self.digital_min}, physical_max:{self.physical_max}, physical_min:{self.physical_min}')
49
50
 
50
51
  def set_channels(self, channels):
51
52
  self._channels = channels
@@ -127,6 +128,7 @@ class EDFStreamWriter(Thread):
127
128
 
128
129
  # 配置通道参数
129
130
  signal_headers = []
131
+ logger.trace(f"sf: {self.sample_frequency}, pm: {self.physical_max}, pn: {self.physical_min}, dm: {self.digital_max}, dn: {self.digital_min}")
130
132
  for ch in range(self._n_channels):
131
133
  signal_headers.append({
132
134
  "label": f'channels {self._channels[ch]}',
@@ -169,14 +171,16 @@ class EDFStreamWriter(Thread):
169
171
  # 写入1秒的数据
170
172
  def _write_block(self, block):
171
173
  logger.trace(f"写入数据: {block}")
172
- # 转换数据类型为float64
173
- data_float64 = block.astype(np.float64)
174
+ # 转换数据类型为float64-物理信号uV int32-数字信号
175
+ data_input = block.astype(np.int32)
176
+ logger.trace(f"写入数据-real: {data_input}")
174
177
  # 写入时转置为(样本数, 通道数)格式
175
- self._writer.writeSamples(data_float64)
178
+ self._writer.writeSamples(data_input, digital=True)
176
179
  self._duration += 1
177
180
 
178
181
  if self._duration % 10 == 0: # 每10秒打印一次进度
179
182
  logger.info(f"数据记录中... 文件名:{self.file_path}, 已记录时长: {self._duration}秒")
183
+
180
184
 
181
185
  # 用作数据结构一致化处理,通过调用公共类写入edf文件
182
186
  # 入参包含写入edf的全部前置参数
@@ -200,7 +204,7 @@ class RscEDFHandler(object):
200
204
  self.physical_max = physical_max
201
205
  self.physical_min = physical_min
202
206
  self.digital_max = 8388607 if resolution == 24 else 32767
203
- self.digital_min = -8388607 if resolution == 24 else - 32768
207
+ self.digital_min = -8388608 if resolution == 24 else - 32768
204
208
  self.file_type = EDF_FILE_TYPE["bdf"] if resolution == 24 else EDF_FILE_TYPE["edf"]
205
209
  # 点分辨率
206
210
  self.resolution = resolution
@@ -226,8 +230,8 @@ class RscEDFHandler(object):
226
230
  self._end_time = None
227
231
  self._patient_code = "patient_code"
228
232
  self._patient_name = "patient_name"
229
- self._device_type = "24130032"
230
- self._device_no = "24130032"
233
+ self._device_type = "0000"
234
+ self._device_no = "00000000"
231
235
  self._total_packets = 0
232
236
  self._lost_packets = 0
233
237
  self._storage_path = storage_path
@@ -242,7 +246,7 @@ class RscEDFHandler(object):
242
246
  suffix = "bdf" if self.resolution == 24 else "edf"
243
247
 
244
248
  # 文件名称
245
- file_name = f"{self._file_prefix}_{self._device_no}_{self._start_time.strftime('%y%m%d%H%I%M')}.{suffix}" if self._file_prefix else f"{self._device_no}_{self._start_time.strftime('%y%m%d%H%I%M')}.{suffix}"
249
+ file_name = f"{self._file_prefix}_{self._device_no}_{self._start_time.strftime('%y%m%d%H%M%S')}.{suffix}" if self._file_prefix else f"{self._device_no}_{self._start_time.strftime('%y%m%d%H%I%M')}.{suffix}"
246
250
 
247
251
  if self._storage_path:
248
252
  try:
@@ -260,6 +264,8 @@ class RscEDFHandler(object):
260
264
  self._device_type = "C64RS"
261
265
  elif device_type == 0x40:
262
266
  self._device_type = "LJ64S1"
267
+ elif device_type == 0x45:
268
+ self._device_type = "C256RS"
263
269
  elif device_type == 0x51:
264
270
  self._device_type = "C256RS"
265
271
  elif device_type == 0x60:
@@ -312,6 +318,7 @@ class RscEDFHandler(object):
312
318
  self._edf_writer_thread.set_start_time(self._start_time)
313
319
  self._edf_writer_thread.start()
314
320
  logger.info(f"开始写入数据: {self.file_name}")
321
+ self._edf_writer_thread.equipment = f'{self._device_type}_{self._device_no}'
315
322
 
316
323
  self._edf_writer_thread.append(packet.eeg)
317
324
 
@@ -331,5 +338,4 @@ class RscEDFHandler(object):
331
338
  else: onset = 0
332
339
  else:
333
340
  onset = cur_time - self._first_timestamp
334
- self._edf_writer_thread.trigger(onset, desc)
335
-
341
+ self._edf_writer_thread.trigger(onset, desc)
@@ -297,8 +297,7 @@ class ImpedanceDataCommand(DeviceCommand):
297
297
  cmd_desc = "阻抗数据"
298
298
 
299
299
  def parse_body(self, body: bytes):
300
- # logger.info(f"Received impedance data: {body.hex()}")
301
- packet = ImpedancePacket().transfer(body)
300
+ self.device.produce(body, type="impedance")
302
301
 
303
302
  # 信号数据
304
303
  class SignalDataCommand(DeviceCommand):
qlsdk/rsc/device/base.py CHANGED
@@ -5,7 +5,7 @@ from typing import Any, Dict, Literal
5
5
 
6
6
  from loguru import logger
7
7
  import numpy as np
8
- from qlsdk.core.entity import RscPacket
8
+ from qlsdk.core.entity import RscPacket, ImpedancePacket
9
9
  from qlsdk.core.utils import to_bytes
10
10
  from qlsdk.rsc.interface import IDevice, IParser
11
11
  from qlsdk.rsc.command import StartImpedanceCommand, StopImpedanceCommand, StartStimulationCommand, StopStimulationCommand, SetAcquisitionParamCommand, StartAcquisitionCommand, StopAcquisitionCommand
@@ -136,7 +136,24 @@ class QLBaseDevice(IDevice):
136
136
 
137
137
  # 数据包处理
138
138
  def produce(self, body: bytes, type:Literal['signal', 'impedance']="signal"):
139
- if body is None: return
139
+ if body is None: return
140
+
141
+ if type == "signal":
142
+ self._produce_signal(body)
143
+ elif type == "impedance":
144
+ self._produce_impedance(body)
145
+
146
+ def _produce_impedance(self, body: bytes):
147
+ packet = ImpedancePacket.transfer(body)
148
+ # 分发阻抗数据包给订阅者
149
+ if len(self._impedance_consumer) > 0:
150
+ for topic, q in self._impedance_consumer.items():
151
+ try:
152
+ q.put(packet, timeout=1)
153
+ except Exception as e:
154
+ logger.error(f"impedance data put to queue exception: {str(e)}")
155
+
156
+ def _produce_signal(self, body: bytes):
140
157
 
141
158
  # 处理信号数据
142
159
  data = self._signal_wrapper(body)
@@ -152,8 +169,10 @@ class QLBaseDevice(IDevice):
152
169
  self._write_signal(data)
153
170
 
154
171
  if len(self.signal_consumers) > 0 :
172
+ logger.trace(f"dg eeg: {data.eeg}")
155
173
  # 信号数字值转物理值
156
174
  data.eeg = self.eeg2phy(np.array(data.eeg))
175
+ logger.trace(f"ph eeg: {data.eeg}")
157
176
 
158
177
  # 发送数据包到订阅者
159
178
  for q in list(self.signal_consumers.values()):
@@ -161,7 +180,7 @@ class QLBaseDevice(IDevice):
161
180
  if q.full():
162
181
  q.get()
163
182
 
164
- q.put(data)
183
+ q.put(data)
165
184
 
166
185
  # 信号数据转换
167
186
  def _signal_wrapper(self, body: bytes):
@@ -335,7 +354,7 @@ class QLBaseDevice(IDevice):
335
354
  self.stim_paradigm = param
336
355
 
337
356
  # 设置采集参数
338
- def set_acq_param(self, channels, sample_rate = 500, sample_range = 188):
357
+ def set_acq_param(self, channels, sample_rate:Literal[188, 375, 563, 750, 1125, 2250, 4500] = 500, sample_range:Literal[250, 500, 1000, 2000, 4000, 8000, 16000, 32000] = 188):
339
358
  self._acq_param["channels"] = channels
340
359
  self._acq_param["sample_rate"] = sample_rate
341
360
  self._acq_param["sample_range"] = sample_range
@@ -427,7 +446,7 @@ class QLBaseDevice(IDevice):
427
446
 
428
447
  # 数据队列
429
448
  if q is None:
430
- q = Queue(maxsize=1000)
449
+ q = Queue(maxsize=1024 * 1024)
431
450
 
432
451
  # 订阅生理电信号数据
433
452
  if type == "signal":
@@ -189,19 +189,7 @@ class C256RS(QLBaseDevice):
189
189
 
190
190
  # 设置记录文件名称前缀
191
191
  def set_file_prefix(self, prefix):
192
- self._file_prefix = prefix
193
-
194
- # 接收socket消息
195
- def accept(self):
196
- pass
197
- # while True:
198
- # # 缓冲去4M
199
- # data = self.socket.recv(4096*1024)
200
- # if not data:
201
- # logger.warning(f"设备{self.device_name}连接结束")
202
- # break
203
-
204
- # self._parser.append(data)
192
+ self._file_prefix = prefix
205
193
 
206
194
  # socket发送数据
207
195
  def send(self, data):
@@ -211,15 +199,6 @@ class C256RS(QLBaseDevice):
211
199
  def set_stim_param(self, param):
212
200
  self.stim_paradigm = param
213
201
 
214
- # 设置采集参数
215
- def set_acq_param(self, channels, sample_rate = 500, sample_range = 188):
216
- self._acq_param["channels"] = channels
217
- self._acq_param["sample_rate"] = sample_rate
218
- self._acq_param["sample_range"] = sample_range
219
- self._acq_channels = channels
220
- self._sample_rate = sample_rate
221
- self._sample_range = sample_range
222
-
223
202
  def _signal_wrapper(self, body: bytes):
224
203
  return C256RSPacket().transfer(body)
225
204
 
@@ -285,35 +285,7 @@ class C64RS(QLBaseDevice):
285
285
  if self._edf_handler:
286
286
  # 发送结束标识
287
287
  self.edf_handler.write(None)
288
-
289
- # 订阅实时数据
290
- def subscribe(self, topic:str=None, q : Queue=None, type : Literal["signal","impedance"]="signal"):
291
-
292
- # 数据队列
293
- if q is None:
294
- q = Queue(maxsize=1000)
295
-
296
- # 队列名称
297
- if topic is None:
298
- topic = f"{type}_{time_ns()}"
299
-
300
- # 订阅生理电信号数据
301
- if type == "signal":
302
- # topic唯一,用来区分不同的订阅队列(下同)
303
- if topic in list(self.__signal_consumer.keys()):
304
- logger.warning(f"exists {type} subscribe of {topic}")
305
- else:
306
- self.__signal_consumer[topic] = q
307
-
308
- # 订阅阻抗数据
309
- if type == "impedance":
310
- if topic in list(self.__signal_consumer.keys()):
311
- logger.warning(f"exists {type} subscribe of {topic}")
312
- else:
313
- self.__impedance_consumer[topic] = q
314
-
315
- return topic, q
316
-
288
+
317
289
  def trigger(self, desc):
318
290
  if self._edf_handler:
319
291
  self.edf_handler.trigger(desc)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qlsdk2
3
- Version: 0.6.0a2
3
+ Version: 0.6.0a4
4
4
  Summary: SDK for quanlan device
5
5
  Home-page: https://github.com/hehuajun/qlsdk
6
6
  Author: hehuajun
@@ -8,7 +8,7 @@ qlsdk/core/local.py,sha256=vbison4XZtS4SNYLJ9CqBhetEcukdviTWmvtdA1efkQ,811
8
8
  qlsdk/core/utils.py,sha256=yfCiLpufO96I68MLs6Drc6IECRjcQ-If8sXn7RaRHrk,4241
9
9
  qlsdk/core/crc/__init__.py,sha256=kaYSr6KN5g4U49xlxAvT2lnEeGtwX4Dz1ArwKDvUIIY,143
10
10
  qlsdk/core/crc/crctools.py,sha256=sDeE6CMccQX2cRAyMQK0SZUk1fa50XMuwqXau5UX5C8,4242
11
- qlsdk/core/entity/__init__.py,sha256=LOS5k_cIA-NYnvE94KUXCBUU_uu1v8FcXf7L399j8Yg,6610
11
+ qlsdk/core/entity/__init__.py,sha256=TFkm1kZ7SsBZnvsdIAnim-HHSeUC69Nd7rrUUrmk4gw,8615
12
12
  qlsdk/core/filter/__init__.py,sha256=YIWIzDUKN30mq2JTr53ZGblggZfC_rLUp2FSRrsQFgU,36
13
13
  qlsdk/core/filter/norch.py,sha256=5RdIBX5eqs5w5nmVAnCB3ESSuAT_vVBZ2g-dg6HMZdY,1858
14
14
  qlsdk/core/message/__init__.py,sha256=sHuavOyHf4bhH6VdDpTA1EsCh7Q-XsPHcFiItpVz3Rs,51
@@ -30,7 +30,7 @@ qlsdk/interface/store.py,sha256=694WQnnrtXThP44JkQlBXzghvqA0PwHKK3uA640aiUo,23
30
30
  qlsdk/persist/__init__.py,sha256=b8qk1aOU6snEMCQNYDl1ijV3-2gwBmMt76fiAzNk1E8,107
31
31
  qlsdk/persist/ars_edf.py,sha256=_pYtHqucB-utMw-xUXZc9IB8_8ThbLFpTl_-WBQR-Sc,10555
32
32
  qlsdk/persist/edf.py,sha256=ETngb86CfkIUJYWmw86QR445MvTFC7Edk_CH9nyNgtY,7857
33
- qlsdk/persist/rsc_edf.py,sha256=-L8Qv_d39rog6vrIEBnO5yYnxCr6yfL4qUlM72AaFJg,13392
33
+ qlsdk/persist/rsc_edf.py,sha256=SKvVXmQIJB5AA_3qvp0uh3PI-VaUk9cP8NXwsrpY4no,13977
34
34
  qlsdk/persist/stream.py,sha256=TCVF1sqDrHiYBsJC27At66AaCs-_blXeXA_WXdJiIVA,5828
35
35
  qlsdk/rsc/__init__.py,sha256=hOMiN0eYn4jYo7O4_0IPlQT0hD15SqqCQUihOVlTZvs,269
36
36
  qlsdk/rsc/device_manager.py,sha256=1ucd-lzHkNeQPKPzXV6OBkAMqPp_vOcsLyS-9TJ7wRc,4448
@@ -39,14 +39,14 @@ qlsdk/rsc/eegion.py,sha256=lxrktO-3Z_MYdFIwc4NxvgLM5AL5kU3UItjH6tsKmHY,11670
39
39
  qlsdk/rsc/entity.py,sha256=-fRWFkVWp9d8Y1uh6GiacXC5scdeEKNiNFf3aziGdCE,17751
40
40
  qlsdk/rsc/paradigm.py,sha256=DGfwY36sMdPIMRjbGo661GvUTEwsRRi3jrmG405mSTk,12840
41
41
  qlsdk/rsc/proxy.py,sha256=9CPdGNGWremwBUh4GvlXAykYB-x_BEPPLqsNvwuwIDE,2736
42
- qlsdk/rsc/command/__init__.py,sha256=DiuXvKQepVTc5hkHSB_YAAZPxobN2a7tYXpI7kZ3GQM,12296
42
+ qlsdk/rsc/command/__init__.py,sha256=TncLrFyanIvaE106EKd2kqHJloQTZee--XaPnADL-Sc,12233
43
43
  qlsdk/rsc/command/message.py,sha256=nTdG-Vp4MBnltyrgedAWiKD6kzOaPrg58Z_hq6yjhys,12220
44
44
  qlsdk/rsc/device/__init__.py,sha256=BzY9lRfssGPUlJ1ys-v3CWNgGihg7mPa2T4X0tl0Vg4,214
45
45
  qlsdk/rsc/device/arskindling.py,sha256=owci6MEGjyWqohEXzPdKj_ESeVIZKgO53StVj6Tmi18,15002
46
- qlsdk/rsc/device/base.py,sha256=oQ4Ev0LkDiJZXTqqTd6zqzzsn4ijYXkTLDUJKF0mn5U,19157
46
+ qlsdk/rsc/device/base.py,sha256=De0SjD84i0_apwPxdnnpGXaVdUGUGAy7YE1k5zNqdfs,20070
47
47
  qlsdk/rsc/device/c16_rs.py,sha256=BHQRHOnsTMAKgqSXaAS2RjPIklZQAl2CVfe6i_iX-i4,5928
48
- qlsdk/rsc/device/c256_rs.py,sha256=x456zQJH2Q__v9nfgZIf947s0sghR8fCVm-ZetsRaKw,13971
49
- qlsdk/rsc/device/c64_rs.py,sha256=cZIioIRGgd4Ub0ieho4_XujBNo8AQgJEjXcqgcEkyFQ,13644
48
+ qlsdk/rsc/device/c256_rs.py,sha256=hsv2MBDFkK2rfsNTkDdG3TBAfVMAaSnTgnsi_NiQB4o,13222
49
+ qlsdk/rsc/device/c64_rs.py,sha256=AAwYcioJ741b22fifhSHTC3C-ESbRtXTe0b8A8OvNjg,12607
50
50
  qlsdk/rsc/device/c64s1.py,sha256=L7nKmsoMCGj6GMjHYfYkKgkBtrGfP516kQHQ5I1FAUE,13986
51
51
  qlsdk/rsc/device/device_factory.py,sha256=6cPhm3pPGrVXA1s1HePFLjZqmhNI1vOAucFI0VRD_Y0,1317
52
52
  qlsdk/rsc/interface/__init__.py,sha256=xeRzIlQSB7ZSf4r5kLfH5cDQLzCyWeJAReG8Xq5nOE0,70
@@ -70,7 +70,7 @@ qlsdk/sdk/libs/libAr4SDK.dll,sha256=kZp9_DRwPdAJ5OgTFQSqS8tEETxUs7YmmETuBP2g60U,
70
70
  qlsdk/sdk/libs/libwinpthread-1.dll,sha256=W77ySaDQDi0yxpnQu-ifcU6-uHKzmQpcvsyx2J9j5eg,52224
71
71
  qlsdk/x8/__init__.py,sha256=FDpDK7GAYL-g3vzfU9U_V03QzoYoxH9YLm93PjMlANg,4870
72
72
  qlsdk/x8m/__init__.py,sha256=cLeUqEEj65qXw4Qa4REyxoLh6T24anSqPaKe9_lR340,634
73
- qlsdk2-0.6.0a2.dist-info/METADATA,sha256=rwjV8tRXw0XYL8tIHZ2PYLaLWP3aD4R5AXi3TSX8QKU,1882
74
- qlsdk2-0.6.0a2.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
75
- qlsdk2-0.6.0a2.dist-info/top_level.txt,sha256=2CHzn0SY-NIBVyBl07Suh-Eo8oBAQfyNPtqQ_aDatBg,6
76
- qlsdk2-0.6.0a2.dist-info/RECORD,,
73
+ qlsdk2-0.6.0a4.dist-info/METADATA,sha256=BBbbb11OYzAxMMoXHycDv36RDWPBTSQIjSJ0Aw51wL8,1882
74
+ qlsdk2-0.6.0a4.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
75
+ qlsdk2-0.6.0a4.dist-info/top_level.txt,sha256=2CHzn0SY-NIBVyBl07Suh-Eo8oBAQfyNPtqQ_aDatBg,6
76
+ qlsdk2-0.6.0a4.dist-info/RECORD,,