telemetry-cli 1.0.0__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.
- telemetry_cli/__init__.py +8 -0
- telemetry_cli/_cli.py +18 -0
- telemetry_cli/_getopt.py +114 -0
- telemetry_cli/_msg.py +39 -0
- telemetry_cli/_pack.py +183 -0
- telemetry_cli/_perl.py +183 -0
- telemetry_cli/pick/__init__.py +1 -0
- telemetry_cli/pick/__main__.py +7 -0
- telemetry_cli/pick/cli.py +157 -0
- telemetry_cli/pick/commandline.py +219 -0
- telemetry_cli/pick/fields.py +166 -0
- telemetry_cli/pick/formats.py +191 -0
- telemetry_cli/pick/help.py +536 -0
- telemetry_cli/pick/symbols/airmoc +24 -0
- telemetry_cli/pick/symbols/aux +28 -0
- telemetry_cli/pick/symbols/corr +31 -0
- telemetry_cli/pick/symbols/corrOld +29 -0
- telemetry_cli/pick/symbols/hw +16 -0
- telemetry_cli/pick/symbols/moc +42 -0
- telemetry_cli/pick/symbols/subcom +83 -0
- telemetry_cli/pick/symbols/subcom_2002 +111 -0
- telemetry_cli/recl/__init__.py +1 -0
- telemetry_cli/recl/__main__.py +7 -0
- telemetry_cli/recl/cli.py +214 -0
- telemetry_cli/recl/corr.py +83 -0
- telemetry_cli/recs/__init__.py +1 -0
- telemetry_cli/recs/__main__.py +7 -0
- telemetry_cli/recs/cli.py +182 -0
- telemetry_cli/recs/extract.py +399 -0
- telemetry_cli/tgen/__init__.py +1 -0
- telemetry_cli/tgen/__main__.py +7 -0
- telemetry_cli/tgen/cli.py +128 -0
- telemetry_cli/tgen/cmdfile.py +68 -0
- telemetry_cli/tgen/convert.py +278 -0
- telemetry_cli/tgen/examples/arb_data.tgen +15 -0
- telemetry_cli/tgen/examples/calsweep.tgen +32 -0
- telemetry_cli/tgen/examples/cond_fill.tgen +17 -0
- telemetry_cli/tgen/examples/counter.tgen +11 -0
- telemetry_cli/tgen/examples/null_data.tgen +11 -0
- telemetry_cli/tgen/examples/random_size.tgen +20 -0
- telemetry_cli/tgen/examples/subcom.tgen +14 -0
- telemetry_cli/tgen/examples/valueV_value.tgen +20 -0
- telemetry_cli/tgen/runtime.py +390 -0
- telemetry_cli-1.0.0.dist-info/METADATA +106 -0
- telemetry_cli-1.0.0.dist-info/RECORD +48 -0
- telemetry_cli-1.0.0.dist-info/WHEEL +4 -0
- telemetry_cli-1.0.0.dist-info/entry_points.txt +5 -0
- telemetry_cli-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"""Printing pick's fields: the print formats (``pick ?f``).
|
|
2
|
+
|
|
3
|
+
The output matches the Perl original's, including its spacing: most formats
|
|
4
|
+
are followed by a space, and x, o, d and u on byte types print another space
|
|
5
|
+
after each byte.
|
|
6
|
+
|
|
7
|
+
Byte order: each item is first put into big-endian order (each half separately
|
|
8
|
+
for complex types), and then printed the way the Perl printed on the
|
|
9
|
+
big-endian machines it was written for. So the output doesn't depend on the
|
|
10
|
+
machine pick runs on, only on the data's byte order.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import math
|
|
16
|
+
import struct
|
|
17
|
+
|
|
18
|
+
from .._perl import multiply, sprintf, substr
|
|
19
|
+
from .fields import STRUCT, Field
|
|
20
|
+
|
|
21
|
+
PI = 3.14159265359 # the Perl original's value, used for the D format
|
|
22
|
+
|
|
23
|
+
FORMAT = {"u": "%u", "d": "%d", "x": "%02x", "o": "%03o", "g": "%g", "G": "%25.18g"}
|
|
24
|
+
FORMAT |= {"M": "%g", "P": "%g", "R": "%g", "I": "%g", "D": "%g"}
|
|
25
|
+
|
|
26
|
+
# names of the ASCII control characters, 0..31
|
|
27
|
+
ASCII_NAMES = ( # noqa: SIM905 (a list literal would take 32 lines)
|
|
28
|
+
"nul soh stx etx eot enq ack bel bs ht nl vt np cr so si "
|
|
29
|
+
"dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us"
|
|
30
|
+
).split()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class FormatError(ValueError):
|
|
34
|
+
"""A print format that can't be used with a field's data type."""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def reversed_order(t: str, nb: int) -> list[int]:
|
|
38
|
+
"""Byte indices that reverse an item's byte order (each half, for complex)."""
|
|
39
|
+
if t in "zZ":
|
|
40
|
+
half = nb // 2
|
|
41
|
+
return [*range(half - 1, -1, -1), *range(nb - 1, half - 1, -1)]
|
|
42
|
+
return list(range(nb - 1, -1, -1))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def reorder(data: bytes, order: list[int]) -> bytes:
|
|
46
|
+
"""data rearranged by index; missing bytes become zero (as in the Perl)."""
|
|
47
|
+
return bytes(data[i] if i < len(data) else 0 for i in order)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _index(seq, i):
|
|
51
|
+
"""Perl's $array[i]: negative indices count from the end; out of range is undef."""
|
|
52
|
+
if -len(seq) <= i < len(seq):
|
|
53
|
+
return seq[i]
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _value(d: bytes, t: str):
|
|
58
|
+
"""The first item of type t in d (big-endian), as Perl's unpack gave it."""
|
|
59
|
+
if t in "cSA": # unpacked as a one-character string
|
|
60
|
+
return d[:1].decode("latin-1")
|
|
61
|
+
code = STRUCT[t]
|
|
62
|
+
size = struct.calcsize(code)
|
|
63
|
+
return struct.unpack(">" + code, d[:size])[0] if len(d) >= size else None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _bit_field(d0: bytes, f: Field) -> bytes:
|
|
67
|
+
"""Apply a field's bit offset and mask, as the Perl's "slow" path did."""
|
|
68
|
+
nb, out = f.nb, f.out_bytes
|
|
69
|
+
r = [d0[j] if j < len(d0) else 0 for j in range(nb)]
|
|
70
|
+
if nb > 4: # bit fields aren't available for these types
|
|
71
|
+
return bytes(r[j] if j < nb else 0 for j in range(out))
|
|
72
|
+
u = 0
|
|
73
|
+
for x in r:
|
|
74
|
+
u = (u << 8) | x
|
|
75
|
+
u = (u >> f.first_bit) & f.mask
|
|
76
|
+
d = []
|
|
77
|
+
for _ in range(out):
|
|
78
|
+
d.append(u & 0xFF)
|
|
79
|
+
u >>= 8
|
|
80
|
+
d += [0] * (nb - out)
|
|
81
|
+
return bytes(reversed(d))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def render(data: bytes, fields: list[Field], *, order: str, host: str, fast_binary: bool) -> bytes:
|
|
85
|
+
"""The output for one record."""
|
|
86
|
+
out = bytearray()
|
|
87
|
+
for f in fields:
|
|
88
|
+
if fast_binary: # -b: the bytes as they are
|
|
89
|
+
out += substr(data, f.pos, f.nb * f.m)
|
|
90
|
+
continue
|
|
91
|
+
rev = reversed_order(f.t, f.nb)
|
|
92
|
+
for i in range(f.m):
|
|
93
|
+
d0 = substr(data, f.pos + i * f.nb, f.nb * f.m)
|
|
94
|
+
item = d0[: f.nb]
|
|
95
|
+
full = len(item) == f.nb
|
|
96
|
+
# big-endian view of the item
|
|
97
|
+
canon = reorder(item, rev) if order == "little" and full else d0
|
|
98
|
+
nbytes = f.out_bytes
|
|
99
|
+
for p in f.formats:
|
|
100
|
+
d = _bit_field(canon, f) if f.bits else canon
|
|
101
|
+
if p == "U":
|
|
102
|
+
out += _unformatted(d, d0, f, order=order, host=host)
|
|
103
|
+
elif f.t in "zZ":
|
|
104
|
+
out += _complex(d, f, p).encode()
|
|
105
|
+
else:
|
|
106
|
+
out += _scalar(d, f, p, nbytes).encode("latin-1")
|
|
107
|
+
if p not in "SAUn":
|
|
108
|
+
out += b" "
|
|
109
|
+
return bytes(out)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _unformatted(d: bytes, d0: bytes, f: Field, *, order: str, host: str) -> bytes:
|
|
113
|
+
"""The 'U' format: the item's bytes, in the host's byte order."""
|
|
114
|
+
nbytes = f.out_bytes
|
|
115
|
+
if f.bits and f.nb <= 4:
|
|
116
|
+
# the masked value's low bytes (the Perl wrote the wrong end of them)
|
|
117
|
+
value = d[len(d) - nbytes :]
|
|
118
|
+
return value[::-1] if host == "little" else value
|
|
119
|
+
if f.bits:
|
|
120
|
+
return d[:nbytes][::-1] if host == "little" and nbytes == f.nb else d[:nbytes]
|
|
121
|
+
if order == host:
|
|
122
|
+
return d0[:nbytes]
|
|
123
|
+
return reorder(d0[: f.nb], reversed_order(f.t, f.nb))[:nbytes]
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _complex(d: bytes, f: Field, p: str) -> str:
|
|
127
|
+
code = STRUCT[f.t]
|
|
128
|
+
size = struct.calcsize(code)
|
|
129
|
+
parts = [struct.unpack_from(">" + code, d, k * size)[0] for k in range(min(2, len(d) // size))]
|
|
130
|
+
re_, im = (parts + [0.0, 0.0])[:2]
|
|
131
|
+
if p == "R":
|
|
132
|
+
return sprintf("%g", re_)
|
|
133
|
+
if p == "I":
|
|
134
|
+
return sprintf("%g", im)
|
|
135
|
+
if p == "g": # documented as RI; the Perl rejected it
|
|
136
|
+
return sprintf("%g", re_) + " " + sprintf("%g", im)
|
|
137
|
+
if p == "M":
|
|
138
|
+
return sprintf("%g", math.sqrt(re_ * re_ + im * im))
|
|
139
|
+
if p == "P":
|
|
140
|
+
return sprintf("%g", math.atan2(im, re_))
|
|
141
|
+
if p == "D":
|
|
142
|
+
return sprintf("%g", multiply(180.0, math.atan2(im, re_)) / PI)
|
|
143
|
+
raise FormatError(f"Unrecognized print format for complex type: {p}")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _scalar(d: bytes, f: Field, p: str, nbytes: int) -> str:
|
|
147
|
+
t, nb = f.t, f.nb
|
|
148
|
+
if p in "cSA":
|
|
149
|
+
text = []
|
|
150
|
+
for k in range(nb):
|
|
151
|
+
ch = d[k : k + 1]
|
|
152
|
+
o = ch[0] if ch else 0
|
|
153
|
+
if ch and 0x20 <= o <= 0x7E:
|
|
154
|
+
text.append(chr(o))
|
|
155
|
+
elif o < 128:
|
|
156
|
+
if p == "c":
|
|
157
|
+
text.append(ASCII_NAMES[o] if o < 32 else "del")
|
|
158
|
+
elif p == "S":
|
|
159
|
+
text.append(f"({ASCII_NAMES[o] if o < 32 else 'del'})")
|
|
160
|
+
elif p == "c":
|
|
161
|
+
text.append(f"{o:o}")
|
|
162
|
+
elif p == "S":
|
|
163
|
+
text.append(f"({o:o})")
|
|
164
|
+
return "".join(text)
|
|
165
|
+
if p in "udgG" and t not in "cb":
|
|
166
|
+
return sprintf(FORMAT[p], _value(d, t))
|
|
167
|
+
if p == "D":
|
|
168
|
+
return sprintf("%g", multiply(_value(d, t), 180.0) / PI)
|
|
169
|
+
if p == "n":
|
|
170
|
+
return "\n"
|
|
171
|
+
if p == "s":
|
|
172
|
+
return ""
|
|
173
|
+
if p in "xodu":
|
|
174
|
+
k = list(d[:nb])
|
|
175
|
+
return "".join(sprintf(FORMAT[p], _index(k, j)) + " " for j in range(nb - nbytes, nb))
|
|
176
|
+
if p == "b":
|
|
177
|
+
k = list(reversed(d[:nb]))
|
|
178
|
+
bout: list[int] = []
|
|
179
|
+
for j in range(nbytes):
|
|
180
|
+
x = _index(k, j) or 0
|
|
181
|
+
for _ in range(8):
|
|
182
|
+
bout.insert(0, x & 1)
|
|
183
|
+
x >>= 1
|
|
184
|
+
n = len(bout)
|
|
185
|
+
text = []
|
|
186
|
+
for bb in range(n - f.nbits, n):
|
|
187
|
+
text.append(str(_index(bout, bb) or 0))
|
|
188
|
+
if (n - (bb + 1)) % 4 == 0:
|
|
189
|
+
text.append(" ")
|
|
190
|
+
return "".join(text)
|
|
191
|
+
raise FormatError(f"unrecognized print format-->{p}<--")
|