oep-client-python 0.0.48__py3-none-any.whl → 0.0.49__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.
- oep_client/__init__.py +1 -1
- oep_client/acquire.py +2 -2
- oep_client/virtual_bench_capture.py +140 -20
- {oep_client_python-0.0.48.dist-info → oep_client_python-0.0.49.dist-info}/METADATA +1 -1
- {oep_client_python-0.0.48.dist-info → oep_client_python-0.0.49.dist-info}/RECORD +8 -8
- {oep_client_python-0.0.48.dist-info → oep_client_python-0.0.49.dist-info}/WHEEL +0 -0
- {oep_client_python-0.0.48.dist-info → oep_client_python-0.0.49.dist-info}/entry_points.txt +0 -0
- {oep_client_python-0.0.48.dist-info → oep_client_python-0.0.49.dist-info}/licenses/LICENSE +0 -0
oep_client/__init__.py
CHANGED
oep_client/acquire.py
CHANGED
|
@@ -1660,9 +1660,9 @@ class _Spool:
|
|
|
1660
1660
|
self._open(p, x)
|
|
1661
1661
|
data = bytes(self.pending[p - self.at:nxt - self.at])
|
|
1662
1662
|
cols = _segment_columns(self.cap, data, samples, len(self.names), self.cfg)
|
|
1663
|
-
for
|
|
1663
|
+
for c, (col, f, ev) in enumerate(zip(cols, self.cur["files"], self.cur["events"])):
|
|
1664
1664
|
if isinstance(col, bytes): # joined bit by bit: a segment need not end on a whole byte
|
|
1665
|
-
self.cur["carry"][
|
|
1665
|
+
self.cur["carry"][c] = _write_bits(f, self.cur["carry"][c], col, samples)
|
|
1666
1666
|
else:
|
|
1667
1667
|
ev[0].append(col[0] + self.cur["samples"] // col[4])
|
|
1668
1668
|
ev[1].append(col[1])
|
|
@@ -82,11 +82,11 @@ BITS = 12 # the analog value's b (layout)
|
|
|
82
82
|
BLOCK_TOP = 4096 # its own: the longest block L it makes (§1.3)
|
|
83
83
|
STREAM_BUFFER_BYTES = 1 << 20 # its own: what a stream holds unsent, said in the answer (stream_buffer, §3.3)
|
|
84
84
|
UNKNOWN_END = 1 << 62 # streaming format 1: a segment dropped whole whose end is not taken yet
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
85
|
+
FAST_A_TICK = 1 << 17 # streaming: the most one tick makes when numpy makes them at once (a_tick)
|
|
86
|
+
BLOCKS_A_TICK = 1 << 14 # streaming: the most samples one tick makes sample by sample - catching up on all
|
|
87
|
+
# the time passed at once fell further behind every tick until the bench answered
|
|
88
|
+
# nothing (wireskein: format 1 at 2 MHz x 4 lines; format 0 at 1 MHz x 2 lines,
|
|
89
|
+
# stop answered after 12.8 s): it catches up over ticks (held_most)
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
TIMEBASE_HZ = 100_000_000 # its own: format 3's delta tick (the answer's timebase, §3.8)
|
|
@@ -206,6 +206,38 @@ def logic_block(raw: list[list[int]], events: list[list[int]], ds: list[int], be
|
|
|
206
206
|
return fallback + start + struct.pack("<I", len(ev)) + body + b"".join(ev)
|
|
207
207
|
|
|
208
208
|
|
|
209
|
+
def logic_block_np(np, raw: list, events: list, ds: list[int], before: list[int], L: int) -> bytes:
|
|
210
|
+
"""logic_block with each channel's levels a numpy array: the same bytes, made at once."""
|
|
211
|
+
r = len((raw + events)[0])
|
|
212
|
+
E = len(events)
|
|
213
|
+
fb, ev = [], []
|
|
214
|
+
for e, lv in enumerate(events):
|
|
215
|
+
d = ds[e]
|
|
216
|
+
q = -(-r // d)
|
|
217
|
+
prev = np.concatenate([np.array([before[e]], np.uint8), lv[:-1]])
|
|
218
|
+
changed = np.zeros(q * d, np.int64)
|
|
219
|
+
changed[:r] = lv != prev
|
|
220
|
+
counts = changed.reshape(q, d).sum(axis=1)
|
|
221
|
+
last = lv[np.minimum((np.arange(q) + 1) * d, r) - 1].astype(np.int64)
|
|
222
|
+
t = np.nonzero(counts)[0]
|
|
223
|
+
rec = np.zeros(len(t), dtype=[("t", "<u2"), ("e", "u1"), ("v", "u1")])
|
|
224
|
+
rec["t"], rec["e"], rec["v"] = t, e, (last[t] << 7) | np.minimum(counts[t], 127)
|
|
225
|
+
if len(t) * 4 > L // 8:
|
|
226
|
+
fb.append(e)
|
|
227
|
+
else:
|
|
228
|
+
ev.append(rec.tobytes())
|
|
229
|
+
nb = (E + 7) // 8
|
|
230
|
+
fallback = sum(1 << e for e in fb).to_bytes(nb, "little")
|
|
231
|
+
start = sum(before[e] << e for e in range(E)).to_bytes(nb, "little")
|
|
232
|
+
cols = raw + [events[e] for e in fb]
|
|
233
|
+
body = b""
|
|
234
|
+
if cols:
|
|
235
|
+
bits = np.stack(cols, axis=1).astype(np.uint8)
|
|
236
|
+
body = np.packbits(bits.reshape(-1), bitorder="little").tobytes()
|
|
237
|
+
n_ev = sum(len(x) // 4 for x in ev)
|
|
238
|
+
return fallback + start + struct.pack("<I", n_ev) + body + b"".join(ev)
|
|
239
|
+
|
|
240
|
+
|
|
209
241
|
def analog_part(values: list[int], kind: int, d: int, b: int) -> bytes:
|
|
210
242
|
"""One channel's part of a format 2 block (§1.4): packed the r values of b bits; else for every interval of d
|
|
211
243
|
(the last one partial) min and max (b bits each) and / or the sum (b + ceil(log2 d) bits), in that order - bits by
|
|
@@ -230,6 +262,15 @@ def analog_part(values: list[int], kind: int, d: int, b: int) -> bytes:
|
|
|
230
262
|
return acc.to_bytes((at + 7) // 8, "little")
|
|
231
263
|
|
|
232
264
|
|
|
265
|
+
class _wave:
|
|
266
|
+
"""A logic wave: wave(i, rate) for one sample, wave.many(np, samples, rate) for an array of them (numpy)."""
|
|
267
|
+
def __init__(self, one, many):
|
|
268
|
+
self.one, self.many = one, many
|
|
269
|
+
|
|
270
|
+
def __call__(self, i, rate):
|
|
271
|
+
return self.one(i, rate)
|
|
272
|
+
|
|
273
|
+
|
|
233
274
|
def logic_wave(spec: str):
|
|
234
275
|
"""A logic channel's waveform instead of the counter's bit: `counter`; `quiet[:LEVEL]` (never changes, default
|
|
235
276
|
high); `square:PERIOD` (samples); `uart:BAUD[:TEXT]` - 8N1 characters of TEXT (default "OEP\\n") one after another
|
|
@@ -239,10 +280,10 @@ def logic_wave(spec: str):
|
|
|
239
280
|
return None
|
|
240
281
|
if kind == "quiet":
|
|
241
282
|
level = int(args[0]) if args else 1
|
|
242
|
-
return lambda i, rate: level
|
|
283
|
+
return _wave(lambda i, rate: level, lambda np, i, rate: np.full(len(i), level, np.uint8))
|
|
243
284
|
if kind == "square":
|
|
244
285
|
half = max(1, int(args[0]) // 2)
|
|
245
|
-
return lambda i, rate: (i // half) & 1
|
|
286
|
+
return _wave(lambda i, rate: (i // half) & 1, lambda np, i, rate: ((i // half) & 1).astype(np.uint8))
|
|
246
287
|
if kind == "uart":
|
|
247
288
|
baud = int(args[0])
|
|
248
289
|
text = (args[1] if len(args) > 1 else "OEP\n").encode()
|
|
@@ -255,7 +296,14 @@ def logic_wave(spec: str):
|
|
|
255
296
|
if at <= 8:
|
|
256
297
|
return text[char % len(text)] >> (at - 1) & 1 # LSB first
|
|
257
298
|
return 1 # stop, idle
|
|
258
|
-
|
|
299
|
+
|
|
300
|
+
def many(np, i, rate): # the same, for an array of samples
|
|
301
|
+
r = Fraction(rate) # the track's rate is exact: so is the bit time
|
|
302
|
+
bit = (i * (baud * r.denominator)) // r.numerator
|
|
303
|
+
char, at = np.divmod(bit, 20)
|
|
304
|
+
data = (np.frombuffer(text, np.uint8)[char % len(text)] >> np.clip(at - 1, 0, 7)) & 1
|
|
305
|
+
return np.where(at == 0, 0, np.where(at <= 8, data, 1)).astype(np.uint8)
|
|
306
|
+
return _wave(uart, many)
|
|
259
307
|
raise ValueError(f"logic wave {spec!r}: counter, quiet[:LEVEL], square:PERIOD or uart:BAUD[:TEXT]")
|
|
260
308
|
|
|
261
309
|
|
|
@@ -702,8 +750,39 @@ class VirtualCapture:
|
|
|
702
750
|
slot = "H" if self.width == 2 * self.channels else "I"
|
|
703
751
|
return b"".join(struct.pack(f"<{self.channels}{slot}", *(self.value(k, first + i) for k in self.analog_roles))
|
|
704
752
|
for i in range(n))
|
|
753
|
+
levels = self._levels(first, n)
|
|
754
|
+
if levels is not None: # numpy: the samples at once
|
|
755
|
+
import numpy as np
|
|
756
|
+
bits = np.zeros((n, self.width), np.uint8)
|
|
757
|
+
bits[:, :] = np.stack(levels[:self.width], axis=1)
|
|
758
|
+
return np.packbits(bits.reshape(-1), bitorder="little").tobytes()
|
|
705
759
|
return pack_samples([sum(self.value(k, first + i) << k for k in range(self.width)) for i in range(n)], self.width)
|
|
706
760
|
|
|
761
|
+
def _levels(self, first: int, n: int):
|
|
762
|
+
"""Logic channels 0 .. max(width, channels) - 1 at samples first .. first + n - 1 as numpy arrays, as value() gives them; None
|
|
763
|
+
where only value() can (numpy missing, the glitch filter, the external clock, a wave without its array form, a
|
|
764
|
+
value() a test put on the track).
|
|
765
|
+
Python made a sample a microsecond or more: a bench behind 1 MS/s on a busy host."""
|
|
766
|
+
ns = max(self.glitch_ns.values(), default=0)
|
|
767
|
+
if self.analog or self.clock is not None or n <= 0 or (ns and -(-ns * self.rate // 1_000_000_000) > 1) or \
|
|
768
|
+
"value" in vars(self): # a test's own value(): only it says
|
|
769
|
+
return None
|
|
770
|
+
try:
|
|
771
|
+
import numpy as np
|
|
772
|
+
except ImportError:
|
|
773
|
+
return None
|
|
774
|
+
i = np.arange(first, first + n, dtype=np.int64)
|
|
775
|
+
out = []
|
|
776
|
+
for k in range(max(self.width, self.channels)): # format 1: the channels, its w apart (0 or less)
|
|
777
|
+
wave = self.waves.get(self.logic_roles[k]) if k < len(self.logic_roles) else None
|
|
778
|
+
if wave is None:
|
|
779
|
+
out.append(((i >> k) & 1).astype(np.uint8))
|
|
780
|
+
elif isinstance(wave, _wave):
|
|
781
|
+
out.append(wave.many(np, i, self.rate))
|
|
782
|
+
else:
|
|
783
|
+
return None
|
|
784
|
+
return out
|
|
785
|
+
|
|
707
786
|
def _blocks(self, first: int, n: int, contiguous: bool, segment_start: bool = True) -> bytes:
|
|
708
787
|
"""A format 1 segment (§1.3): blocks of L from its sample 0; start_level the sample before when it is
|
|
709
788
|
contiguous in the generation, else the block's first. Format 2: _analog_blocks; format 3: _timed."""
|
|
@@ -715,10 +794,18 @@ class VirtualCapture:
|
|
|
715
794
|
raw = [k for k in roles if self.carriages.get(k, (CARRIAGE["raw"], 1))[0] == CARRIAGE["raw"]]
|
|
716
795
|
ev = [k for k in roles if k not in raw]
|
|
717
796
|
ds = [self.carriages[k][1] for k in ev]
|
|
797
|
+
levels = self._levels(first, n) # numpy: the samples and the blocks at once
|
|
718
798
|
out = bytearray()
|
|
719
799
|
for b in range(0, n, self.block):
|
|
720
800
|
r = min(self.block, n - b)
|
|
721
801
|
at = first + b
|
|
802
|
+
if levels is not None:
|
|
803
|
+
before = [int(levels[k][b - 1]) if b else (self.value(k, at - 1) if contiguous else int(levels[k][0]))
|
|
804
|
+
for k in ev]
|
|
805
|
+
import numpy as np
|
|
806
|
+
out += logic_block_np(np, [levels[k][b:b + r] for k in raw], [levels[k][b:b + r] for k in ev], ds,
|
|
807
|
+
before, self.block)
|
|
808
|
+
continue
|
|
722
809
|
before = [self.value(k, at - 1) if (b or contiguous) else self.value(k, at) for k in ev]
|
|
723
810
|
out += logic_block([[self.value(k, at + i) for i in range(r)] for k in raw],
|
|
724
811
|
[[self.value(k, at + i) for i in range(r)] for k in ev], ds, before, self.block)
|
|
@@ -1018,22 +1105,43 @@ class VirtualCapture:
|
|
|
1018
1105
|
if len(self.segs) >= self.segments_max:
|
|
1019
1106
|
self.state = STATE["paused"]
|
|
1020
1107
|
break
|
|
1108
|
+
elif self.mode == MODE["streaming"] and due - self.produced > self.held_most():
|
|
1109
|
+
events += self.overflow() # behind by more than its stream holds (below)
|
|
1021
1110
|
elif self.mode == MODE["streaming"] and self.format in PIECES:
|
|
1022
1111
|
self._stream_blocks(due, whole=True)
|
|
1023
1112
|
elif self.mode == MODE["streaming"]:
|
|
1024
|
-
|
|
1025
|
-
n = min((due - self.produced) // per_byte * per_byte, BLOCKS_A_TICK)
|
|
1026
|
-
if n > 0:
|
|
1027
|
-
self.data += self._pack(self.produced, n)
|
|
1028
|
-
self.produced += n
|
|
1029
|
-
taken = self.produced - self.capture_begin
|
|
1030
|
-
first = self.first_segment_samples or self.samples
|
|
1031
|
-
complete = 0 if taken < first else 1 + (taken - first) // self.samples
|
|
1032
|
-
self.serial_done = complete & 0xFFFFFFFF
|
|
1033
|
-
done_samples = 0 if not complete else first + (complete - 1) * self.samples
|
|
1034
|
-
self.stream_committed_bytes = self.bytes_of(done_samples)
|
|
1113
|
+
self._stream_samples(due)
|
|
1035
1114
|
return events
|
|
1036
1115
|
|
|
1116
|
+
# Streaming follows the clock as a probe's does: sample i is the one taken at t0 + i / rate, and the samples the
|
|
1117
|
+
# clock has taken that the bench has not made yet are as a probe's samples held unsent in its stream buffer. A tick
|
|
1118
|
+
# makes a bounded number (the bench keeps answering), so it may be behind for a while and catch up; stop makes every
|
|
1119
|
+
# sample up to the stop (a probe sends all it holds); behind by more than the stream buffer holds, the track stops
|
|
1120
|
+
# in error as a probe whose buffer overflowed (state 6, error storage) - never a stream that silently ran late
|
|
1121
|
+
# (a section placed by the probe's clock past the stream's end, wireskein on a busy host).
|
|
1122
|
+
def held_most(self) -> int:
|
|
1123
|
+
"""The samples its stream buffer holds (stream_buffer, §3.3), at format 0's bytes a sample."""
|
|
1124
|
+
return STREAM_BUFFER_BYTES // max(1, self.width) if self.analog else STREAM_BUFFER_BYTES * 8 // max(1, self.width)
|
|
1125
|
+
|
|
1126
|
+
def a_tick(self) -> int:
|
|
1127
|
+
"""The most samples one tick makes: more when numpy makes them at once (a sample a microsecond or more in
|
|
1128
|
+
Python, about a hundredth of that at once)."""
|
|
1129
|
+
return FAST_A_TICK if self._levels(self.produced, 1) is not None else BLOCKS_A_TICK
|
|
1130
|
+
|
|
1131
|
+
def _stream_samples(self, due: int, most: int | None = None) -> None:
|
|
1132
|
+
"""Format 0 streaming: the samples up to `due`, at most `most` (a_tick() by default), whole bytes only."""
|
|
1133
|
+
per_byte = 1 if self.analog else 8 // math.gcd(self.width, 8) # whole bytes only (§2.2)
|
|
1134
|
+
n = min((due - self.produced) // per_byte * per_byte, self.a_tick() if most is None else most)
|
|
1135
|
+
if n > 0:
|
|
1136
|
+
self.data += self._pack(self.produced, n)
|
|
1137
|
+
self.produced += n
|
|
1138
|
+
taken = self.produced - self.capture_begin
|
|
1139
|
+
first = self.first_segment_samples or self.samples
|
|
1140
|
+
complete = 0 if taken < first else 1 + (taken - first) // self.samples
|
|
1141
|
+
self.serial_done = complete & 0xFFFFFFFF
|
|
1142
|
+
done_samples = 0 if not complete else first + (complete - 1) * self.samples
|
|
1143
|
+
self.stream_committed_bytes = self.bytes_of(done_samples)
|
|
1144
|
+
|
|
1037
1145
|
def _stream_geometry(self, rel: int) -> tuple[int, int, int]:
|
|
1038
1146
|
"""Streaming: the segment holding sample `rel` (from the retained start) -> (its number, first sample, size)."""
|
|
1039
1147
|
first = self.first_segment_samples or self.samples
|
|
@@ -1046,7 +1154,7 @@ class VirtualCapture:
|
|
|
1046
1154
|
"""Format 1 streaming: the blocks the clock has taken - each whole (a block counts its events first, §1.3), at
|
|
1047
1155
|
most BLOCKS_A_TICK samples a call; `whole` False at stop: the block being taken ends there, short."""
|
|
1048
1156
|
if whole:
|
|
1049
|
-
due = min(due, self.produced +
|
|
1157
|
+
due = min(due, self.produced + self.a_tick())
|
|
1050
1158
|
else: # stop: only the block begun, not all the time behind
|
|
1051
1159
|
rel = self.produced - self.capture_begin
|
|
1052
1160
|
_, at, size = self._stream_geometry(rel)
|
|
@@ -1104,6 +1212,18 @@ class VirtualCapture:
|
|
|
1104
1212
|
index = self.first_trigger_index if self.first_trigger_index < partial else NONE
|
|
1105
1213
|
segment = self._segment(partial, index, flags=FLAG["short"])
|
|
1106
1214
|
events.append(bytes([EVENT["segment"]]) + segment.pack())
|
|
1215
|
+
if self.state == STATE["capturing"] and self.mode == MODE["streaming"] and now_ms is not None:
|
|
1216
|
+
due = self.kept(int((now_ms - self.started_ms) * self.rate / 1000)) # every sample up to the stop: the
|
|
1217
|
+
if due - self.produced > self.held_most(): # stream holds them (tick's rules, above)
|
|
1218
|
+
return events + self.overflow()
|
|
1219
|
+
while self.state == STATE["capturing"]:
|
|
1220
|
+
before = self.produced
|
|
1221
|
+
if self.format in PIECES:
|
|
1222
|
+
self._stream_blocks(due, whole=True)
|
|
1223
|
+
else:
|
|
1224
|
+
self._stream_samples(due, most=due)
|
|
1225
|
+
if self.produced == before:
|
|
1226
|
+
break
|
|
1107
1227
|
if self.state == STATE["capturing"] and self.mode == MODE["streaming"] and self.format in PIECES:
|
|
1108
1228
|
if now_ms is not None: # the taken samples, a short last block
|
|
1109
1229
|
self._stream_blocks(self.kept(int((now_ms - self.started_ms) * self.rate / 1000)), whole=False)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: oep-client-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.49
|
|
4
4
|
Summary: Open Embedded Probe (OEP) v1 host: serial / USB / TCP transports, the session rules, the standard interfaces, and a virtual bench
|
|
5
5
|
Project-URL: Homepage, https://github.com/Open-Embedded-Probe/oep-client-python
|
|
6
6
|
Project-URL: Repository, https://github.com/Open-Embedded-Probe/oep-client-python
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
oep_client/__init__.py,sha256=
|
|
1
|
+
oep_client/__init__.py,sha256=HsHjSnQVjNKgEHyTGCVruPWP4HisGn-GuiP1r3bk70c,164
|
|
2
2
|
oep_client/__main__.py,sha256=kbXBtEmFdhRXbVqXEbWCO-_5aDa-KyqMcW2HLZb5fjc,31510
|
|
3
|
-
oep_client/acquire.py,sha256=
|
|
3
|
+
oep_client/acquire.py,sha256=9_rNRUB6jLPMu2Ga9QWSh9bLYR99taLpZL9-qBHdt8M,104034
|
|
4
4
|
oep_client/arm.py,sha256=SszSLae8zErD4T-a1uQ6s6o3Lz7pe2SR8d3Qy-wi5rY,15633
|
|
5
5
|
oep_client/capture.py,sha256=fvLqs4Ltot4pyOdQiCWIzf_v1j_iduCxU4rrX6oWfg8,76245
|
|
6
6
|
oep_client/capture_blocks.py,sha256=dPrrZ8K-ISF80w6UumKVst5XNt0IjUk9lxbVvFnUEqg,20836
|
|
@@ -38,7 +38,7 @@ oep_client/targets.py,sha256=ixUxbZUfYqOJjZzcaOudwV2wweVwdk0G85dfRiZzMeA,7183
|
|
|
38
38
|
oep_client/uiapduino.py,sha256=oafP1SyKPO3cox-2RYbWUZusy4vc6NsEVC7Z-Y1sjWI,6337
|
|
39
39
|
oep_client/usb_stream.py,sha256=zRGGHkvtOme6lIZ-gkrCe2xKn9hC62JGqmc7pKQDAJI,23540
|
|
40
40
|
oep_client/virtual_bench.py,sha256=gc2i8UZM5P_2sg68wcDx5B4pRkYNUZ2wjzIQBpKOOuI,50262
|
|
41
|
-
oep_client/virtual_bench_capture.py,sha256=
|
|
41
|
+
oep_client/virtual_bench_capture.py,sha256=84MsaS2wXq2N6wcFtsFHdBaGR9bjWPXathZpcJ341Mo,101920
|
|
42
42
|
oep_client/virtual_bench_mdns.py,sha256=cnJNBKg5zTduXUcH-wqN_ZBDGl7DyL-tL3CBn2jro0E,13305
|
|
43
43
|
oep_client/virtual_bench_serial.py,sha256=EvbdOYeGrM6CRti2b90I0PzpmmherfoJRaAg4v7Iq9Y,13205
|
|
44
44
|
oep_client/virtual_bench_serve.py,sha256=LPjvXcfVpixOyhGM1-oZpDqjJfD53eKOrhpAdoXV1ck,39015
|
|
@@ -255,8 +255,8 @@ oep_client/conformance/wire_options_sample.py,sha256=dog-yvUcu693M8b51tA5TnhAnKr
|
|
|
255
255
|
oep_client/conformance/writer_lease.py,sha256=5wDd4XIJWFPFlRY91wHlJs5U7ANp3xPpGgU2Eki7e8g,7331
|
|
256
256
|
oep_client/conformance/writer_lease_model.py,sha256=FxhDqqzdFOa_SSHSvjdQFh49Wn3YuZ98ISSlRRxrq9E,1721
|
|
257
257
|
oep_client/conformance/writer_lease_sample.py,sha256=oowRwYUNAE4f6rEE2HmYlSS9dDWE0TGegkcsqVH8Nak,455
|
|
258
|
-
oep_client_python-0.0.
|
|
259
|
-
oep_client_python-0.0.
|
|
260
|
-
oep_client_python-0.0.
|
|
261
|
-
oep_client_python-0.0.
|
|
262
|
-
oep_client_python-0.0.
|
|
258
|
+
oep_client_python-0.0.49.dist-info/METADATA,sha256=UYYYs1l9AeiJXE7eZqgk2XKm04VWVD1PLmjh5LlcYXQ,55269
|
|
259
|
+
oep_client_python-0.0.49.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
260
|
+
oep_client_python-0.0.49.dist-info/entry_points.txt,sha256=XEt39Jz7oQyU9Hfg_tV6eDGofNxWYrjSfslxKP-fh70,135
|
|
261
|
+
oep_client_python-0.0.49.dist-info/licenses/LICENSE,sha256=ntlalztb3L1OaNAxmQdHlubu5fVhjMc9oRZi3PeQhXg,1076
|
|
262
|
+
oep_client_python-0.0.49.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|