oep-client-python 0.0.46__py3-none-any.whl → 0.0.48__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 +127 -44
- {oep_client_python-0.0.46.dist-info → oep_client_python-0.0.48.dist-info}/METADATA +1 -1
- {oep_client_python-0.0.46.dist-info → oep_client_python-0.0.48.dist-info}/RECORD +7 -7
- {oep_client_python-0.0.46.dist-info → oep_client_python-0.0.48.dist-info}/WHEEL +0 -0
- {oep_client_python-0.0.46.dist-info → oep_client_python-0.0.48.dist-info}/entry_points.txt +0 -0
- {oep_client_python-0.0.46.dist-info → oep_client_python-0.0.48.dist-info}/licenses/LICENSE +0 -0
oep_client/__init__.py
CHANGED
oep_client/acquire.py
CHANGED
|
@@ -11,14 +11,25 @@ probe's facts out.
|
|
|
11
11
|
|
|
12
12
|
Logic channels go to oep.fixture.logic, analog ones to oep.fixture.analog; with both, oep.fixture.capture-group
|
|
13
13
|
starts them together, a trigger on either track as the group's trigger source (capture §4.4). A line is named as a
|
|
14
|
-
script keeps it - the probe's channel name (fn 0's channel_name, core §7.5) or a port's line label (
|
|
15
|
-
|
|
14
|
+
script keeps it - the probe's channel name (fn 0's channel_name, core §7.5) or a port's line label (host guide §5.3:
|
|
15
|
+
S.N by its role, S@P by the target pin) - and looked up on the session (a channel number holds for one boot only); a track's channels are its plan roles
|
|
16
16
|
0..C-1 in the order given. The plans are released afterwards.
|
|
17
17
|
|
|
18
18
|
Modes: "oneshot" (the probe's memory), "repeat" (`segments` acquisitions read and released as they come: with a
|
|
19
19
|
trigger one part each, layout "segments"; without, a timeline), "stream" (for `seconds`, sent as taken,
|
|
20
20
|
put together on disk while it runs: a timeline, cut where data was lost).
|
|
21
21
|
|
|
22
|
+
A stream can run while the script does its steps on the same session (marking sections, sending console commands):
|
|
23
|
+
`during=steps` in place of `seconds` streams until steps(wait) returns, `wait(seconds)` collecting while it waits.
|
|
24
|
+
Steps should call wait often (the probe holds only its stream buffer meanwhile); a loss with on_loss "stop" raises
|
|
25
|
+
StreamStopped out of wait, and the stream ends there.
|
|
26
|
+
|
|
27
|
+
def steps(wait):
|
|
28
|
+
for duty in (64, 128):
|
|
29
|
+
with rec.section(2, f"duty={duty}"):
|
|
30
|
+
console.write(f"PWM {duty}\n".encode()); wait(0.5)
|
|
31
|
+
res = acquire.capture(hst, acquire.Request(chans, 1_000_000, 0, mode="stream", during=steps))
|
|
32
|
+
|
|
22
33
|
Times: tick 0 of a part is its first logic sample, `start_ns` on the probe's clock; an analog channel starts at
|
|
23
34
|
t0_ticks = (its segment's start_ns - that) plus its skew_ns, in ticks. These are the probe's estimates; each track's
|
|
24
35
|
uncertainty is kept. ADC values are kept raw with the probe's linear conversion; the input range, reference, Vrefint
|
|
@@ -37,13 +48,14 @@ import array
|
|
|
37
48
|
import math
|
|
38
49
|
import struct
|
|
39
50
|
import sys
|
|
51
|
+
from collections.abc import Callable
|
|
40
52
|
from dataclasses import dataclass, field
|
|
41
53
|
from fractions import Fraction
|
|
42
54
|
from pathlib import Path
|
|
43
55
|
|
|
44
56
|
from . import registry as _reg
|
|
45
57
|
|
|
46
|
-
__all__ = ["Analog", "Bits", "Changes", "OnDisk", "Part", "Request", "Result", "capture", "capture_at"]
|
|
58
|
+
__all__ = ["Analog", "Bits", "Changes", "OnDisk", "Part", "Request", "Result", "StreamStopped", "capture", "capture_at"]
|
|
47
59
|
|
|
48
60
|
TRIGGERS = ("high", "low", "rise", "fall", "both")
|
|
49
61
|
ANALOG_TRIGGERS = ("high", "low", "rise", "fall")
|
|
@@ -52,7 +64,8 @@ ANALOG_TRIGGERS = ("high", "low", "rise", "fall")
|
|
|
52
64
|
@dataclass
|
|
53
65
|
class Request:
|
|
54
66
|
channels: list[tuple[str, str]] # logic: (name to record, the line): the probe's channel name (fn 0's
|
|
55
|
-
# channel_name, GPIO47) or a port's line label (S.N, x035.swdio
|
|
67
|
+
# channel_name, GPIO47) or a port's line label (S.N, x035.swdio; S@P,
|
|
68
|
+
# x035@pb9), in order
|
|
56
69
|
rate: int # logic samples per second asked for (the probe may answer another)
|
|
57
70
|
samples: int
|
|
58
71
|
trigger: tuple | None = None # (logic channel, one of TRIGGERS) or (analog channel, rise / fall / high /
|
|
@@ -69,6 +82,8 @@ class Request:
|
|
|
69
82
|
segments: int | None = None # repeat: how many acquisitions
|
|
70
83
|
on_loss: str = "stop" # stream: "stop" at the first loss, or "continue" to the end
|
|
71
84
|
spool_dir: str | None = None # stream: where its channels are put together on disk while it runs
|
|
85
|
+
during: Callable[[Callable[[float], None]], None] | None = None # stream: instead of `seconds`, runs until this
|
|
86
|
+
# returns - called with wait(seconds), which collects while it waits
|
|
72
87
|
|
|
73
88
|
def __post_init__(self):
|
|
74
89
|
names = [n for n, _ in self.channels] + [n for n, *_ in self.analog]
|
|
@@ -92,8 +107,10 @@ class Request:
|
|
|
92
107
|
raise ValueError("repeat: logic channels only")
|
|
93
108
|
elif self.segments is not None:
|
|
94
109
|
raise ValueError("segments is for repeat only")
|
|
95
|
-
if self.
|
|
96
|
-
raise ValueError("a stream
|
|
110
|
+
if self.during is not None and (self.mode != "stream" or self.seconds is not None):
|
|
111
|
+
raise ValueError("during is for a stream, in place of seconds")
|
|
112
|
+
if self.mode == "stream" and self.during is None and not (self.seconds and self.seconds > 0):
|
|
113
|
+
raise ValueError("a stream needs seconds (how long) or during")
|
|
97
114
|
if self.arm not in ("pretrigger", "now"):
|
|
98
115
|
raise ValueError(f"arm {self.arm!r}: pretrigger or now")
|
|
99
116
|
logic = {n for n, _ in self.channels}
|
|
@@ -567,7 +584,8 @@ def _describe(core, hst, fn: int) -> list[tuple[int, bytes]]:
|
|
|
567
584
|
|
|
568
585
|
def _channels(core, hst, lines: list[str]) -> list[int]:
|
|
569
586
|
"""The probe's channel numbers (valid for this boot) of lines named as kept in scripts: a channel name (fn 0's
|
|
570
|
-
channel_name, core §7.5; GPIO47) or a port's line label (
|
|
587
|
+
channel_name, core §7.5; GPIO47) or a port's line label (host guide §5.3: S.N by its role, x035.swdio; S@P by the target pin, x035@pb9). ASCII
|
|
588
|
+
case aside."""
|
|
571
589
|
if not lines:
|
|
572
590
|
return []
|
|
573
591
|
from . import registry, settings
|
|
@@ -581,11 +599,13 @@ def _channels(core, hst, lines: list[str]) -> list[int]:
|
|
|
581
599
|
labels = None
|
|
582
600
|
out = []
|
|
583
601
|
for line in lines:
|
|
584
|
-
|
|
585
|
-
if
|
|
602
|
+
label = settings.parse_label(line)
|
|
603
|
+
if label is not None:
|
|
586
604
|
if labels is None:
|
|
587
605
|
labels = settings.labels(hst)
|
|
588
|
-
|
|
606
|
+
port, role, pin = label
|
|
607
|
+
ch = (settings.line_from_labels(labels, role, port) if role
|
|
608
|
+
else settings.pin_from_labels(labels, pin, port))
|
|
589
609
|
if ch is None:
|
|
590
610
|
raise ValueError(f"{line}: no channel carries that label (host guide §5.3)")
|
|
591
611
|
else:
|
|
@@ -1133,6 +1153,35 @@ STREAM_MAX_DELAY_MS = 20 # ... or after this long. With (0, 0) the P4X sent eac
|
|
|
1133
1153
|
# quiet lines) as a transfer of its own, 2000 a second, and dropped 35 % it could not send
|
|
1134
1154
|
|
|
1135
1155
|
|
|
1156
|
+
class StreamStopped(Exception):
|
|
1157
|
+
"""Raised by a stream's `wait` (Request.during) when data was lost and on_loss is "stop": the stream stops there."""
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
def _drive(req: Request, poll, lost) -> None:
|
|
1161
|
+
"""Collect a started stream: for req.seconds, or while req.during(wait) runs - its `wait(seconds)` collecting
|
|
1162
|
+
meanwhile. poll(seconds) takes what comes, lost() says whether anything was lost; with on_loss "stop" a loss ends
|
|
1163
|
+
it (a StreamStopped out of wait, caught here)."""
|
|
1164
|
+
import time
|
|
1165
|
+
|
|
1166
|
+
def wait(seconds: float) -> None:
|
|
1167
|
+
deadline = time.monotonic() + seconds
|
|
1168
|
+
while True:
|
|
1169
|
+
now = time.monotonic()
|
|
1170
|
+
if now >= deadline:
|
|
1171
|
+
return
|
|
1172
|
+
poll(min(STREAM_POLL_S, deadline - now))
|
|
1173
|
+
if req.on_loss == "stop" and lost():
|
|
1174
|
+
raise StreamStopped("data was lost while streaming")
|
|
1175
|
+
|
|
1176
|
+
try:
|
|
1177
|
+
if req.during is None:
|
|
1178
|
+
wait(req.seconds)
|
|
1179
|
+
else:
|
|
1180
|
+
req.during(wait)
|
|
1181
|
+
except StreamStopped:
|
|
1182
|
+
pass
|
|
1183
|
+
|
|
1184
|
+
|
|
1136
1185
|
def _collect_group(group, tracks, link, req: Request, oc, spool=None):
|
|
1137
1186
|
"""_collect for a group's streaming tracks (capture §4.1: each subscribed, started at once): -> ({fn: Received},
|
|
1138
1187
|
seconds). The first track's Received goes to the spool as it comes; a loss in any track stops it with "stop"."""
|
|
@@ -1141,20 +1190,22 @@ def _collect_group(group, tracks, link, req: Request, oc, spool=None):
|
|
|
1141
1190
|
t.subscribe(STREAM_MIN_BYTES, STREAM_MAX_DELAY_MS)
|
|
1142
1191
|
group.start(tracks)
|
|
1143
1192
|
t_read = time.monotonic()
|
|
1144
|
-
|
|
1193
|
+
got = {t.fn: oc.Received() for t in tracks}
|
|
1145
1194
|
lead = tracks[0].fn
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
break
|
|
1150
|
-
got = group.stream(link, tracks, seconds=min(STREAM_POLL_S, deadline - now), into=got)
|
|
1195
|
+
|
|
1196
|
+
def poll(seconds):
|
|
1197
|
+
group.stream(link, tracks, seconds=seconds, into=got)
|
|
1151
1198
|
if spool is not None:
|
|
1152
1199
|
spool.take(got[lead])
|
|
1153
|
-
|
|
1200
|
+
|
|
1201
|
+
def lost():
|
|
1202
|
+
return (spool is not None and spool.lost) or any(
|
|
1154
1203
|
g.gaps or (g.start or 0) > 0 for fn, g in got.items() if spool is None or fn != lead)
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1204
|
+
|
|
1205
|
+
try:
|
|
1206
|
+
_drive(req, poll, lost)
|
|
1207
|
+
finally:
|
|
1208
|
+
group.stop() # also when the caller's `during` raised: the probe is left stopped
|
|
1158
1209
|
got = group.finish(link, tracks, got)
|
|
1159
1210
|
return got, time.monotonic() - t_read
|
|
1160
1211
|
|
|
@@ -1182,25 +1233,26 @@ def _analog_runs(an, acfg, got) -> tuple[list, list]:
|
|
|
1182
1233
|
|
|
1183
1234
|
|
|
1184
1235
|
def _collect(track, link, req: Request, oc, spool=None):
|
|
1185
|
-
"""Subscribe, start, collect for req.seconds, stop and collect the rest -> (Received,
|
|
1186
|
-
at once with on_loss "stop"."""
|
|
1236
|
+
"""Subscribe, start, collect for req.seconds (or while req.during runs), stop and collect the rest -> (Received,
|
|
1237
|
+
seconds). A loss stops it at once with on_loss "stop"."""
|
|
1187
1238
|
import time
|
|
1188
1239
|
track.subscribe(STREAM_MIN_BYTES, STREAM_MAX_DELAY_MS) # batched: a capture wants bandwidth, not a frame per block
|
|
1189
1240
|
track.start()
|
|
1190
1241
|
t_read = time.monotonic()
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
break
|
|
1196
|
-
got = track.stream(link, seconds=min(STREAM_POLL_S, deadline - now), into=got)
|
|
1242
|
+
got = oc.Received()
|
|
1243
|
+
|
|
1244
|
+
def poll(seconds): # stream() renews the lease across calls on the same Received
|
|
1245
|
+
track.stream(link, seconds=seconds, into=got)
|
|
1197
1246
|
if spool is not None: # put together as it comes: memory holds a poll's worth, not the stream
|
|
1198
1247
|
spool.take(got)
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1248
|
+
|
|
1249
|
+
def lost():
|
|
1250
|
+
return spool.lost if spool is not None else bool(got.gaps or (got.start or 0) > 0)
|
|
1251
|
+
|
|
1252
|
+
try:
|
|
1253
|
+
_drive(req, poll, lost)
|
|
1254
|
+
finally:
|
|
1255
|
+
track.stop()
|
|
1204
1256
|
got = track.finish(link, got)
|
|
1205
1257
|
return got, time.monotonic() - t_read
|
|
1206
1258
|
|
|
@@ -1603,14 +1655,14 @@ class _Spool:
|
|
|
1603
1655
|
p, nxt = ready[k][0], ready[j][1]
|
|
1604
1656
|
x = self.segs[p]
|
|
1605
1657
|
samples = sum(self.segs.pop(q).samples for q, _ in ready[k:j + 1])
|
|
1606
|
-
if self.cur is not None and
|
|
1658
|
+
if self.cur is not None and any(self.cur["samples"] % d for d in self.ds):
|
|
1607
1659
|
self._close(follows=True) # a grid restart (format 1) is not a loss: the next part follows on
|
|
1608
1660
|
self._open(p, x)
|
|
1609
1661
|
data = bytes(self.pending[p - self.at:nxt - self.at])
|
|
1610
1662
|
cols = _segment_columns(self.cap, data, samples, len(self.names), self.cfg)
|
|
1611
|
-
for col, f, ev in zip(cols, self.cur["files"], self.cur["events"]):
|
|
1612
|
-
if isinstance(col, bytes):
|
|
1613
|
-
|
|
1663
|
+
for j, (col, f, ev) in enumerate(zip(cols, self.cur["files"], self.cur["events"])):
|
|
1664
|
+
if isinstance(col, bytes): # joined bit by bit: a segment need not end on a whole byte
|
|
1665
|
+
self.cur["carry"][j] = _write_bits(f, self.cur["carry"][j], col, samples)
|
|
1614
1666
|
else:
|
|
1615
1667
|
ev[0].append(col[0] + self.cur["samples"] // col[4])
|
|
1616
1668
|
ev[1].append(col[1])
|
|
@@ -1641,7 +1693,7 @@ class _Spool:
|
|
|
1641
1693
|
k = len(self.parts)
|
|
1642
1694
|
files = [open(os.path.join(self.dir, f"p{k}-{j}.bits"), "wb") for j in range(len(self.names))]
|
|
1643
1695
|
self.cur = {"tick0": tick0, "meta": _seg_meta(seg) if seg is not None else {}, "samples": 0, "files": files,
|
|
1644
|
-
"events": [[[], [], [], None] for _ in self.names]}
|
|
1696
|
+
"events": [[[], [], [], None] for _ in self.names], "carry": [None] * len(self.names)}
|
|
1645
1697
|
self._follows = False
|
|
1646
1698
|
|
|
1647
1699
|
_last_samples, _last_end, _follows = 0, None, False
|
|
@@ -1653,6 +1705,7 @@ class _Spool:
|
|
|
1653
1705
|
cur, n = self.cur, self.cur["samples"]
|
|
1654
1706
|
chans = []
|
|
1655
1707
|
for role, (name, ch, f, ev) in enumerate(zip(self.names, self.ids, cur["files"], cur["events"])):
|
|
1708
|
+
_flush_bits(f, cur["carry"][role])
|
|
1656
1709
|
f.close()
|
|
1657
1710
|
d = self.cfg.event_d.get(role) if self.blocks else None
|
|
1658
1711
|
if d is not None:
|
|
@@ -1739,7 +1792,7 @@ def _stream_parts(cap, cfg, got, names, ids, req: Request) -> tuple[list, list]:
|
|
|
1739
1792
|
chans = from_interleaved(data, names, cfg.width, cfg.positions, samples)
|
|
1740
1793
|
else:
|
|
1741
1794
|
chans = _from_blocks(cap, data, names, samples, cfg)
|
|
1742
|
-
restart = acc is not None and
|
|
1795
|
+
restart = acc is not None and any(acc_samples % d for d in ds)
|
|
1743
1796
|
if acc is None or restart: # a grid restart (format 1) is not a loss: the next part follows on
|
|
1744
1797
|
if acc is not None:
|
|
1745
1798
|
parts.append(_part(_built(acc, acc_samples, ids), acc_meta, tick0))
|
|
@@ -1813,10 +1866,41 @@ def _samples_at_once(run, names, ids, cfg, samples: int) -> list:
|
|
|
1813
1866
|
for name, ch, bits in zip(names, ids, packed)]
|
|
1814
1867
|
|
|
1815
1868
|
|
|
1869
|
+
def _write_bits(f, carry, col: bytes, samples: int):
|
|
1870
|
+
"""Append `samples` bits of `col` (sample i at bit i % 8 of byte i // 8) to file `f` after the `carry` bits not
|
|
1871
|
+
yet written (None: none): whole bytes go to the file, the bits left over (fewer than 8) come back as the carry."""
|
|
1872
|
+
if carry is None and samples % 8 == 0:
|
|
1873
|
+
f.write(col[:samples // 8])
|
|
1874
|
+
return None
|
|
1875
|
+
import numpy as np
|
|
1876
|
+
bits = np.unpackbits(np.frombuffer(col, np.uint8, (samples + 7) // 8), bitorder="little")[:samples]
|
|
1877
|
+
if carry is not None:
|
|
1878
|
+
bits = np.concatenate([carry, bits])
|
|
1879
|
+
whole = len(bits) // 8 * 8
|
|
1880
|
+
f.write(np.packbits(bits[:whole], bitorder="little").tobytes())
|
|
1881
|
+
return bits[whole:] if whole < len(bits) else None
|
|
1882
|
+
|
|
1883
|
+
|
|
1884
|
+
def _flush_bits(f, carry) -> None:
|
|
1885
|
+
"""The last carry of _write_bits: its bits in one byte, the rest 0."""
|
|
1886
|
+
if carry is not None and len(carry):
|
|
1887
|
+
import numpy as np
|
|
1888
|
+
f.write(np.packbits(carry, bitorder="little").tobytes())
|
|
1889
|
+
|
|
1890
|
+
|
|
1891
|
+
def _join_bits(pieces) -> bytes:
|
|
1892
|
+
"""Pieces (bits, n) joined bit by bit: n need not be a multiple of 8."""
|
|
1893
|
+
if all(n % 8 == 0 for _, n in pieces[:-1]):
|
|
1894
|
+
return b"".join(b[:(n + 7) // 8] for b, n in pieces)
|
|
1895
|
+
import numpy as np
|
|
1896
|
+
return np.packbits(np.concatenate([np.unpackbits(np.frombuffer(b, np.uint8, (n + 7) // 8), bitorder="little")[:n]
|
|
1897
|
+
for b, n in pieces]), bitorder="little").tobytes()
|
|
1898
|
+
|
|
1899
|
+
|
|
1816
1900
|
class _Acc:
|
|
1817
|
-
"""One channel of a part being joined from its segments (bits:
|
|
1818
|
-
|
|
1819
|
-
|
|
1901
|
+
"""One channel of a part being joined from its segments (bits: joined bit by bit; events: quanta offset by the
|
|
1902
|
+
samples so far, a multiple of D). A segment that follows on carries the level before it as its start (§1.3), so
|
|
1903
|
+
its changes join the part's as they are."""
|
|
1820
1904
|
def __init__(self, c):
|
|
1821
1905
|
self.first, self.pieces = c, []
|
|
1822
1906
|
self.start = getattr(c, "start_level", None)
|
|
@@ -1842,8 +1926,7 @@ def _built(acc: list, samples: int, ids) -> list:
|
|
|
1842
1926
|
ct += c_
|
|
1843
1927
|
out.append(changes(c.name, ks, lv, ct, -(-samples // c.step), c.step, 0, a.start, pin=ch))
|
|
1844
1928
|
else:
|
|
1845
|
-
out.append(Bits(c.name,
|
|
1846
|
-
{"pin": ch}))
|
|
1929
|
+
out.append(Bits(c.name, _join_bits(a.pieces)[:(samples + 7) // 8], samples, 1, 0, {"pin": ch}))
|
|
1847
1930
|
return out
|
|
1848
1931
|
|
|
1849
1932
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: oep-client-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.48
|
|
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=6oSvhMIWGGzIF7vHRn0zjXVkFRa6spDeH9YGkw-8pZU,164
|
|
2
2
|
oep_client/__main__.py,sha256=kbXBtEmFdhRXbVqXEbWCO-_5aDa-KyqMcW2HLZb5fjc,31510
|
|
3
|
-
oep_client/acquire.py,sha256=
|
|
3
|
+
oep_client/acquire.py,sha256=_-cH4JxePvym2REq7ElaBcNSuREt8DbsDwAkYM0xSw0,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
|
|
@@ -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.48.dist-info/METADATA,sha256=dmN1zicxaqz2IlW815qXtU6KXYYqPebwgAs00ikR0v0,55269
|
|
259
|
+
oep_client_python-0.0.48.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
260
|
+
oep_client_python-0.0.48.dist-info/entry_points.txt,sha256=XEt39Jz7oQyU9Hfg_tV6eDGofNxWYrjSfslxKP-fh70,135
|
|
261
|
+
oep_client_python-0.0.48.dist-info/licenses/LICENSE,sha256=ntlalztb3L1OaNAxmQdHlubu5fVhjMc9oRZi3PeQhXg,1076
|
|
262
|
+
oep_client_python-0.0.48.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|