harp-python 0.3.0__py3-none-any.whl → 0.4.1__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.
- harp/__init__.py +2 -2
- harp/io.py +166 -14
- harp/model.py +1 -8
- harp/reader.py +27 -21
- harp/schema.py +3 -0
- harp/typing.py +13 -0
- {harp_python-0.3.0.dist-info → harp_python-0.4.1.dist-info}/METADATA +4 -4
- harp_python-0.4.1.dist-info/RECORD +12 -0
- {harp_python-0.3.0.dist-info → harp_python-0.4.1.dist-info}/WHEEL +1 -1
- harp_python-0.3.0.dist-info/RECORD +0 -11
- {harp_python-0.3.0.dist-info → harp_python-0.4.1.dist-info/licenses}/LICENSE +0 -0
- {harp_python-0.3.0.dist-info → harp_python-0.4.1.dist-info}/top_level.txt +0 -0
harp/__init__.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from harp.io import REFERENCE_EPOCH, MessageType, read
|
|
1
|
+
from harp.io import REFERENCE_EPOCH, MessageType, read, to_buffer, to_file
|
|
2
2
|
from harp.reader import create_reader
|
|
3
3
|
from harp.schema import read_schema
|
|
4
4
|
|
|
5
|
-
__all__ = ["REFERENCE_EPOCH", "MessageType", "read", "create_reader", "read_schema"]
|
|
5
|
+
__all__ = ["REFERENCE_EPOCH", "MessageType", "read", "to_buffer", "to_file", "create_reader", "read_schema"]
|
harp/io.py
CHANGED
|
@@ -4,8 +4,11 @@ from os import PathLike
|
|
|
4
4
|
from typing import Any, BinaryIO, Optional, Union
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
|
+
import numpy.typing as npt
|
|
7
8
|
import pandas as pd
|
|
8
|
-
from pandas._typing import Axes
|
|
9
|
+
from pandas._typing import Axes # pyright: ignore[reportPrivateImportUsage]
|
|
10
|
+
|
|
11
|
+
from harp.typing import _BufferLike, _FileLike
|
|
9
12
|
|
|
10
13
|
REFERENCE_EPOCH = datetime(1904, 1, 1)
|
|
11
14
|
"""The reference epoch for UTC harp time."""
|
|
@@ -21,8 +24,9 @@ class MessageType(IntEnum):
|
|
|
21
24
|
|
|
22
25
|
|
|
23
26
|
_SECONDS_PER_TICK = 32e-6
|
|
27
|
+
_PAYLOAD_TIMESTAMP_MASK = 0x10
|
|
24
28
|
_messagetypes = [type.name for type in MessageType]
|
|
25
|
-
|
|
29
|
+
_dtypefrompayloadtype = {
|
|
26
30
|
1: np.dtype(np.uint8),
|
|
27
31
|
2: np.dtype(np.uint16),
|
|
28
32
|
4: np.dtype(np.uint32),
|
|
@@ -33,10 +37,11 @@ _payloadtypes = {
|
|
|
33
37
|
136: np.dtype(np.int64),
|
|
34
38
|
68: np.dtype(np.float32),
|
|
35
39
|
}
|
|
40
|
+
_payloadtypefromdtype = {v: k for k, v in _dtypefrompayloadtype.items()}
|
|
36
41
|
|
|
37
42
|
|
|
38
43
|
def read(
|
|
39
|
-
|
|
44
|
+
file_or_buf: Union[_FileLike, _BufferLike],
|
|
40
45
|
address: Optional[int] = None,
|
|
41
46
|
dtype: Optional[np.dtype] = None,
|
|
42
47
|
length: Optional[int] = None,
|
|
@@ -44,22 +49,22 @@ def read(
|
|
|
44
49
|
epoch: Optional[datetime] = None,
|
|
45
50
|
keep_type: bool = False,
|
|
46
51
|
):
|
|
47
|
-
"""Read single-register Harp data from the specified file.
|
|
52
|
+
"""Read single-register Harp data from the specified file or buffer.
|
|
48
53
|
|
|
49
54
|
Parameters
|
|
50
55
|
----------
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
file_or_buf
|
|
57
|
+
File path, open file object, or buffer containing binary data from
|
|
53
58
|
a single device register.
|
|
54
59
|
address
|
|
55
60
|
Expected register address. If specified, the address of
|
|
56
|
-
the first message
|
|
61
|
+
the first message is used for validation.
|
|
57
62
|
dtype
|
|
58
63
|
Expected data type of the register payload. If specified, the
|
|
59
|
-
payload type of the first message
|
|
64
|
+
payload type of the first message is used for validation.
|
|
60
65
|
length
|
|
61
66
|
Expected number of elements in register payload. If specified, the
|
|
62
|
-
payload length of the first message
|
|
67
|
+
payload length of the first message is used for validation.
|
|
63
68
|
columns
|
|
64
69
|
The optional column labels to use for the data values.
|
|
65
70
|
epoch
|
|
@@ -72,9 +77,20 @@ def read(
|
|
|
72
77
|
-------
|
|
73
78
|
A pandas data frame containing message data, sorted by time.
|
|
74
79
|
"""
|
|
75
|
-
|
|
80
|
+
if isinstance(file_or_buf, (str, PathLike, BinaryIO)) or hasattr(file_or_buf, "readinto"):
|
|
81
|
+
# TODO: in the below we ignore the type as otherwise
|
|
82
|
+
# we have no way to runtime check _IOProtocol
|
|
83
|
+
data = np.fromfile(file_or_buf, dtype=np.uint8) # type: ignore
|
|
84
|
+
else:
|
|
85
|
+
data = np.frombuffer(file_or_buf, dtype=np.uint8)
|
|
86
|
+
|
|
76
87
|
if len(data) == 0:
|
|
77
|
-
return pd.DataFrame(
|
|
88
|
+
return pd.DataFrame(
|
|
89
|
+
columns=columns,
|
|
90
|
+
index=pd.DatetimeIndex([], name="Time")
|
|
91
|
+
if epoch
|
|
92
|
+
else pd.Index([], dtype=np.float64, name="Time"),
|
|
93
|
+
)
|
|
78
94
|
|
|
79
95
|
if address is not None and address != data[2]:
|
|
80
96
|
raise ValueError(f"expected address {address} but got {data[2]}")
|
|
@@ -84,20 +100,20 @@ def read(
|
|
|
84
100
|
nrows = len(data) // stride
|
|
85
101
|
payloadtype = data[4]
|
|
86
102
|
payloadoffset = 5
|
|
87
|
-
if payloadtype &
|
|
103
|
+
if payloadtype & _PAYLOAD_TIMESTAMP_MASK != 0:
|
|
88
104
|
seconds = np.ndarray(nrows, dtype=np.uint32, buffer=data, offset=payloadoffset, strides=stride)
|
|
89
105
|
payloadoffset += 4
|
|
90
106
|
micros = np.ndarray(nrows, dtype=np.uint16, buffer=data, offset=payloadoffset, strides=stride)
|
|
91
107
|
payloadoffset += 2
|
|
92
108
|
time = micros * _SECONDS_PER_TICK + seconds
|
|
93
|
-
payloadtype = payloadtype & ~np.uint8(
|
|
109
|
+
payloadtype = payloadtype & ~np.uint8(_PAYLOAD_TIMESTAMP_MASK)
|
|
94
110
|
if epoch is not None:
|
|
95
111
|
time = epoch + pd.to_timedelta(time, "s") # type: ignore
|
|
96
112
|
index = pd.Series(time)
|
|
97
113
|
index.name = "Time"
|
|
98
114
|
|
|
99
115
|
payloadsize = stride - payloadoffset - 1
|
|
100
|
-
payloadtype =
|
|
116
|
+
payloadtype = _dtypefrompayloadtype[payloadtype]
|
|
101
117
|
if dtype is not None and dtype != payloadtype:
|
|
102
118
|
raise ValueError(f"expected payload type {dtype} but got {payloadtype}")
|
|
103
119
|
|
|
@@ -120,3 +136,139 @@ def read(
|
|
|
120
136
|
msgtype = pd.Categorical.from_codes(msgtype, categories=_messagetypes) # type: ignore
|
|
121
137
|
result[MessageType.__name__] = msgtype
|
|
122
138
|
return result
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def to_file(
|
|
142
|
+
data: pd.DataFrame,
|
|
143
|
+
file: _FileLike,
|
|
144
|
+
address: int,
|
|
145
|
+
dtype: Optional[np.dtype] = None,
|
|
146
|
+
length: Optional[int] = None,
|
|
147
|
+
port: Optional[int] = None,
|
|
148
|
+
epoch: Optional[datetime] = None,
|
|
149
|
+
message_type: Optional[MessageType] = None,
|
|
150
|
+
):
|
|
151
|
+
"""Write single-register Harp data to the specified file.
|
|
152
|
+
|
|
153
|
+
Parameters
|
|
154
|
+
----------
|
|
155
|
+
data
|
|
156
|
+
Pandas data frame containing message payload.
|
|
157
|
+
file
|
|
158
|
+
File path, or open file object in which to store binary data from
|
|
159
|
+
a single device register.
|
|
160
|
+
address
|
|
161
|
+
Register address used to identify all formatted Harp messages.
|
|
162
|
+
dtype
|
|
163
|
+
Data type of the register payload. If specified, all data will
|
|
164
|
+
be converted before formatting the binary payload.
|
|
165
|
+
length
|
|
166
|
+
Expected number of elements in register payload. If specified, the
|
|
167
|
+
number of columns in the input data frame is validated.
|
|
168
|
+
port
|
|
169
|
+
Optional port value used for all formatted Harp messages.
|
|
170
|
+
epoch
|
|
171
|
+
Reference datetime at which time zero begins. If specified,
|
|
172
|
+
the input data frame must have a datetime index.
|
|
173
|
+
message_type
|
|
174
|
+
Optional message type used for all formatted Harp messages.
|
|
175
|
+
If not specified, data must contain a MessageType column.
|
|
176
|
+
"""
|
|
177
|
+
buffer = to_buffer(data, address, dtype, port, length, epoch, message_type)
|
|
178
|
+
buffer.tofile(file)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def to_buffer(
|
|
182
|
+
data: pd.DataFrame,
|
|
183
|
+
address: int,
|
|
184
|
+
dtype: Optional[np.dtype] = None,
|
|
185
|
+
length: Optional[int] = None,
|
|
186
|
+
port: Optional[int] = None,
|
|
187
|
+
epoch: Optional[datetime] = None,
|
|
188
|
+
message_type: Optional[MessageType] = None,
|
|
189
|
+
) -> npt.NDArray[np.uint8]:
|
|
190
|
+
"""Convert single-register Harp data to a flat binary buffer.
|
|
191
|
+
|
|
192
|
+
Parameters
|
|
193
|
+
----------
|
|
194
|
+
data
|
|
195
|
+
Pandas data frame containing message payload.
|
|
196
|
+
address
|
|
197
|
+
Register address used to identify all formatted Harp messages.
|
|
198
|
+
dtype
|
|
199
|
+
Data type of the register payload. If specified, all data will
|
|
200
|
+
be converted before formatting the binary payload.
|
|
201
|
+
length
|
|
202
|
+
Expected number of elements in register payload. If specified, the
|
|
203
|
+
number of columns in the input data frame is validated.
|
|
204
|
+
port
|
|
205
|
+
Optional port value used for all formatted Harp messages.
|
|
206
|
+
epoch
|
|
207
|
+
Reference datetime at which time zero begins. If specified,
|
|
208
|
+
the input data frame must have a datetime index.
|
|
209
|
+
message_type
|
|
210
|
+
Optional message type used for all formatted Harp messages.
|
|
211
|
+
If not specified, data must contain a MessageType column.
|
|
212
|
+
|
|
213
|
+
Returns
|
|
214
|
+
-------
|
|
215
|
+
An array object containing message data formatted according
|
|
216
|
+
to the Harp binary protocol.
|
|
217
|
+
"""
|
|
218
|
+
nrows = len(data)
|
|
219
|
+
if nrows == 0:
|
|
220
|
+
return np.empty(0, dtype=np.uint8)
|
|
221
|
+
|
|
222
|
+
if MessageType.__name__ in data.columns:
|
|
223
|
+
msgtype = data[MessageType.__name__].cat.codes
|
|
224
|
+
payload = data[data.columns.drop(MessageType.__name__)].values
|
|
225
|
+
elif message_type is not None:
|
|
226
|
+
msgtype = message_type
|
|
227
|
+
payload = data.values
|
|
228
|
+
else:
|
|
229
|
+
raise ValueError(f"message type must be specified either in the data or as argument")
|
|
230
|
+
|
|
231
|
+
time = data.index
|
|
232
|
+
is_timestamped = True
|
|
233
|
+
if epoch is not None:
|
|
234
|
+
if not isinstance(time, pd.DatetimeIndex):
|
|
235
|
+
raise ValueError(f"expected datetime index to encode with epoch but got {time.inferred_type}")
|
|
236
|
+
time = (time - epoch).total_seconds()
|
|
237
|
+
elif isinstance(time, pd.RangeIndex):
|
|
238
|
+
is_timestamped = False
|
|
239
|
+
|
|
240
|
+
if dtype is not None:
|
|
241
|
+
payload = payload.astype(dtype, copy=False)
|
|
242
|
+
|
|
243
|
+
ncols = payload.shape[1]
|
|
244
|
+
if length is not None and ncols != length:
|
|
245
|
+
raise ValueError(f"expected payload length {length} but got {ncols}")
|
|
246
|
+
|
|
247
|
+
if port is None:
|
|
248
|
+
port = 255
|
|
249
|
+
|
|
250
|
+
payloadtype = _payloadtypefromdtype[payload.dtype]
|
|
251
|
+
payloadlength = ncols * payload.dtype.itemsize
|
|
252
|
+
stride = payloadlength + 6
|
|
253
|
+
if is_timestamped:
|
|
254
|
+
payloadtype |= _PAYLOAD_TIMESTAMP_MASK
|
|
255
|
+
stride += 6
|
|
256
|
+
|
|
257
|
+
buffer = np.empty((nrows, stride), dtype=np.uint8)
|
|
258
|
+
buffer[:, 0] = msgtype
|
|
259
|
+
buffer[:, 1:5] = [stride - 2, address, port, payloadtype]
|
|
260
|
+
|
|
261
|
+
payloadoffset = 5
|
|
262
|
+
if is_timestamped:
|
|
263
|
+
seconds = time.astype(np.uint32)
|
|
264
|
+
micros = np.around(((time - seconds) / _SECONDS_PER_TICK).values).astype(np.uint16)
|
|
265
|
+
buffer[:, 5:9] = np.ndarray((nrows, 4), dtype=np.uint8, buffer=seconds.values)
|
|
266
|
+
buffer[:, 9:11] = np.ndarray((nrows, 2), dtype=np.uint8, buffer=micros)
|
|
267
|
+
payloadoffset += 6
|
|
268
|
+
|
|
269
|
+
payloadstop = payloadoffset + payloadlength
|
|
270
|
+
buffer[:, payloadoffset:payloadstop] = np.ndarray(
|
|
271
|
+
(nrows, payloadlength), dtype=np.uint8, buffer=np.ascontiguousarray(payload)
|
|
272
|
+
)
|
|
273
|
+
buffer[:, -1] = np.sum(buffer[:, 0:-1], axis=1, dtype=np.uint8)
|
|
274
|
+
return buffer.reshape(-1)
|
harp/model.py
CHANGED
|
@@ -7,14 +7,7 @@ from __future__ import annotations
|
|
|
7
7
|
from enum import Enum
|
|
8
8
|
from typing import Annotated, Dict, List, Optional, Union
|
|
9
9
|
|
|
10
|
-
from pydantic import
|
|
11
|
-
BaseModel,
|
|
12
|
-
BeforeValidator,
|
|
13
|
-
ConfigDict,
|
|
14
|
-
Field,
|
|
15
|
-
RootModel,
|
|
16
|
-
field_serializer,
|
|
17
|
-
)
|
|
10
|
+
from pydantic import BaseModel, BeforeValidator, ConfigDict, Field, RootModel, field_serializer
|
|
18
11
|
|
|
19
12
|
|
|
20
13
|
class PayloadType(str, Enum):
|
harp/reader.py
CHANGED
|
@@ -6,20 +6,21 @@ from functools import partial
|
|
|
6
6
|
from math import log2
|
|
7
7
|
from os import PathLike
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import
|
|
9
|
+
from typing import Callable, Iterable, Mapping, Optional, Protocol, Union
|
|
10
10
|
|
|
11
11
|
from numpy import dtype
|
|
12
12
|
from pandas import DataFrame, Series
|
|
13
|
-
from pandas._typing import Axes
|
|
13
|
+
from pandas._typing import Axes # pyright: ignore[reportPrivateImportUsage]
|
|
14
14
|
|
|
15
15
|
from harp.io import MessageType, read
|
|
16
16
|
from harp.model import BitMask, GroupMask, Model, PayloadMember, Register
|
|
17
17
|
from harp.schema import read_schema
|
|
18
|
+
from harp.typing import _BufferLike, _FileLike
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
@dataclass
|
|
21
22
|
class _ReaderParams:
|
|
22
|
-
|
|
23
|
+
base_path: Path
|
|
23
24
|
epoch: Optional[datetime] = None
|
|
24
25
|
keep_type: bool = False
|
|
25
26
|
|
|
@@ -27,7 +28,7 @@ class _ReaderParams:
|
|
|
27
28
|
class _ReadRegister(Protocol):
|
|
28
29
|
def __call__(
|
|
29
30
|
self,
|
|
30
|
-
|
|
31
|
+
file_or_buf: Optional[Union[_FileLike, _BufferLike]] = None,
|
|
31
32
|
epoch: Optional[datetime] = None,
|
|
32
33
|
keep_type: bool = False,
|
|
33
34
|
) -> DataFrame: ...
|
|
@@ -81,12 +82,12 @@ def _compose_parser(
|
|
|
81
82
|
params: _ReaderParams,
|
|
82
83
|
) -> Callable[..., DataFrame]:
|
|
83
84
|
def parser(
|
|
84
|
-
|
|
85
|
+
data: Optional[Union[_FileLike, _BufferLike]] = None,
|
|
85
86
|
columns: Optional[Axes] = None,
|
|
86
87
|
epoch: Optional[datetime] = params.epoch,
|
|
87
88
|
keep_type: bool = params.keep_type,
|
|
88
89
|
):
|
|
89
|
-
df = g(
|
|
90
|
+
df = g(data, columns, epoch, keep_type)
|
|
90
91
|
result = f(df)
|
|
91
92
|
type_col = df.get(MessageType.__name__)
|
|
92
93
|
if type_col is not None:
|
|
@@ -167,16 +168,16 @@ def _create_payloadmember_parser(device: Model, member: PayloadMember):
|
|
|
167
168
|
|
|
168
169
|
def _create_register_reader(register: Register, params: _ReaderParams):
|
|
169
170
|
def reader(
|
|
170
|
-
|
|
171
|
+
file_or_buf: Optional[Union[_FileLike, _BufferLike]] = None,
|
|
171
172
|
columns: Optional[Axes] = None,
|
|
172
173
|
epoch: Optional[datetime] = params.epoch,
|
|
173
174
|
keep_type: bool = params.keep_type,
|
|
174
175
|
):
|
|
175
|
-
if
|
|
176
|
-
|
|
176
|
+
if file_or_buf is None:
|
|
177
|
+
file_or_buf = f"{params.base_path}_{register.address}.bin"
|
|
177
178
|
|
|
178
179
|
data = read(
|
|
179
|
-
|
|
180
|
+
file_or_buf,
|
|
180
181
|
address=register.address,
|
|
181
182
|
dtype=dtype(register.type),
|
|
182
183
|
length=register.length,
|
|
@@ -189,7 +190,7 @@ def _create_register_reader(register: Register, params: _ReaderParams):
|
|
|
189
190
|
return reader
|
|
190
191
|
|
|
191
192
|
|
|
192
|
-
def
|
|
193
|
+
def _create_register_handler(device: Model, name: str, params: _ReaderParams):
|
|
193
194
|
register = device.registers[name]
|
|
194
195
|
reader = _create_register_reader(register, params)
|
|
195
196
|
|
|
@@ -197,29 +198,34 @@ def _create_register_parser(device: Model, name: str, params: _ReaderParams):
|
|
|
197
198
|
key = register.maskType.root
|
|
198
199
|
bitMask = None if device.bitMasks is None else device.bitMasks.get(key)
|
|
199
200
|
if bitMask is not None:
|
|
200
|
-
|
|
201
|
-
reader = _compose_parser(
|
|
201
|
+
bitmask_parser = _create_bitmask_parser(bitMask)
|
|
202
|
+
reader = _compose_parser(bitmask_parser, reader, params)
|
|
202
203
|
return RegisterReader(register, reader)
|
|
203
204
|
|
|
204
205
|
groupMask = None if device.groupMasks is None else device.groupMasks.get(key)
|
|
205
206
|
if groupMask is not None:
|
|
206
|
-
|
|
207
|
-
reader = _compose_parser(
|
|
207
|
+
groupmask_parser = _create_groupmask_parser(name, groupMask)
|
|
208
|
+
reader = _compose_parser(groupmask_parser, reader, params)
|
|
208
209
|
return RegisterReader(register, reader)
|
|
209
210
|
|
|
210
211
|
if register.payloadSpec is not None:
|
|
211
|
-
|
|
212
|
+
member_parsers = [
|
|
212
213
|
(key, _create_payloadmember_parser(device, member))
|
|
213
214
|
for key, member in register.payloadSpec.items()
|
|
214
215
|
]
|
|
215
216
|
|
|
216
|
-
def
|
|
217
|
-
return DataFrame({n: f(df) for n, f in
|
|
217
|
+
def payload_parser(df: DataFrame):
|
|
218
|
+
return DataFrame({n: f(df) for n, f in member_parsers}, index=df.index)
|
|
218
219
|
|
|
219
|
-
reader = _compose_parser(
|
|
220
|
+
reader = _compose_parser(payload_parser, reader, params)
|
|
220
221
|
return RegisterReader(register, reader)
|
|
221
222
|
|
|
222
|
-
|
|
223
|
+
columns = (
|
|
224
|
+
[name]
|
|
225
|
+
if register.length is None or register.length == 1
|
|
226
|
+
else [f"{name}_{i}" for i in range(register.length)]
|
|
227
|
+
)
|
|
228
|
+
reader = partial(reader, columns=columns)
|
|
223
229
|
return RegisterReader(register, reader)
|
|
224
230
|
|
|
225
231
|
|
|
@@ -265,7 +271,7 @@ def create_reader(
|
|
|
265
271
|
base_path = path / device.device if is_dir else path.parent / device.device
|
|
266
272
|
|
|
267
273
|
reg_readers = {
|
|
268
|
-
name:
|
|
274
|
+
name: _create_register_handler(device, name, _ReaderParams(base_path, epoch, keep_type))
|
|
269
275
|
for name in device.registers.keys()
|
|
270
276
|
}
|
|
271
277
|
return DeviceReader(device, reg_readers)
|
harp/schema.py
CHANGED
|
@@ -8,6 +8,9 @@ from harp.model import Model, Registers
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def _read_common_registers() -> Registers:
|
|
11
|
+
if __package__ is None:
|
|
12
|
+
raise ValueError("__package__ is None: unable to read common registers")
|
|
13
|
+
|
|
11
14
|
file = resources.files(__package__) / "common.yml"
|
|
12
15
|
with file.open("r") as fileIO:
|
|
13
16
|
return parse_yaml_raw_as(Registers, fileIO.read())
|
harp/typing.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import mmap
|
|
2
|
+
import sys
|
|
3
|
+
from os import PathLike
|
|
4
|
+
from typing import Any, BinaryIO, Union
|
|
5
|
+
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
|
|
8
|
+
if sys.version_info >= (3, 12):
|
|
9
|
+
from collections.abc import Buffer as _BufferLike
|
|
10
|
+
else:
|
|
11
|
+
_BufferLike = Union[bytes, bytearray, memoryview, mmap.mmap, NDArray[Any]]
|
|
12
|
+
|
|
13
|
+
_FileLike = Union[str, PathLike[str], BinaryIO]
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: harp-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: A low-level interface for loading binary Harp protocol data
|
|
5
5
|
Author-email: Goncalo Lopes <g.lopes@neurogears.org>
|
|
6
|
-
License: MIT
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Bug Tracker, https://github.com/harp-tech/harp-python/issues
|
|
8
8
|
Project-URL: Source Code, https://github.com/harp-tech/harp-python
|
|
9
9
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -12,7 +12,6 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.9
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
16
15
|
Requires-Python: >=3.9.0
|
|
17
16
|
Description-Content-Type: text/markdown
|
|
18
17
|
License-File: LICENSE
|
|
@@ -29,6 +28,7 @@ Requires-Dist: codespell; extra == "dev"
|
|
|
29
28
|
Provides-Extra: jupyter
|
|
30
29
|
Requires-Dist: ipykernel; extra == "jupyter"
|
|
31
30
|
Requires-Dist: matplotlib; extra == "jupyter"
|
|
31
|
+
Dynamic: license-file
|
|
32
32
|
|
|
33
33
|
# harp-python
|
|
34
34
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
harp/__init__.py,sha256=N6fclA4pCSdBwcJELnN15p5QioU_6F01gH-8F3wr_pI,264
|
|
2
|
+
harp/common.yml,sha256=qcejMFu00JjI5rkubuEDdrUu_uFkN17f_Ljb6yBd-RM,4452
|
|
3
|
+
harp/io.py,sha256=js_DDHOBxNIacnHQxua0i42ljOEYZFew28zPSTXSyOs,9828
|
|
4
|
+
harp/model.py,sha256=djJ7Ah6GliwDh1rXhTYoqXSDMUJ3UI9PAKFL-F6ooAg,5769
|
|
5
|
+
harp/reader.py,sha256=kdrNAG53yuWMgYvlv2uAfO-8CYLREI-1PLgsE-SnE_4,8887
|
|
6
|
+
harp/schema.py,sha256=9tNwjnec8WtRkV8P_oblauW7btOi_y1vWFC6Tw4EWt0,1929
|
|
7
|
+
harp/typing.py,sha256=MCjnRwj-K3vybLfp_dFFqf7MwmJ7PmYe0yD91bt8uEk,355
|
|
8
|
+
harp_python-0.4.1.dist-info/licenses/LICENSE,sha256=KxnuV3gNCp4WmLUC8DYWJvCKPdxMpwmWIzAYBYdqPrM,1104
|
|
9
|
+
harp_python-0.4.1.dist-info/METADATA,sha256=XjRu_m2eIB9ZVN649GnNRkinWiDmszh8W8fA3p6C96U,3164
|
|
10
|
+
harp_python-0.4.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
11
|
+
harp_python-0.4.1.dist-info/top_level.txt,sha256=ztK1iHjgwmfXqxHCpu-e2uHIwdmodywYEUaWSODMvyM,5
|
|
12
|
+
harp_python-0.4.1.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
harp/__init__.py,sha256=P2PHGnd9Oz3LwrscBHKXqdYZimF7k57HcAaIaksRKc0,220
|
|
2
|
-
harp/common.yml,sha256=qcejMFu00JjI5rkubuEDdrUu_uFkN17f_Ljb6yBd-RM,4452
|
|
3
|
-
harp/io.py,sha256=an802KRCU-eSBXKWB7nXsomUBWcfAwEOZs9U188_MUM,4179
|
|
4
|
-
harp/model.py,sha256=oJim5Gc42H4MJwpLwd2Y7KHsoeI_Yw3CO0o6qn7pJbQ,5805
|
|
5
|
-
harp/reader.py,sha256=u-Taf6gmkQ5_PcsDRNskPBhZ7UsCcYL0WPlH0sEmjk0,8588
|
|
6
|
-
harp/schema.py,sha256=bUr4WS-en03mzisIc9eAYiG7kReMmHdEvVwrhEpTboo,1816
|
|
7
|
-
harp_python-0.3.0.dist-info/LICENSE,sha256=KxnuV3gNCp4WmLUC8DYWJvCKPdxMpwmWIzAYBYdqPrM,1104
|
|
8
|
-
harp_python-0.3.0.dist-info/METADATA,sha256=lWiDbZSxbm8NmtXXopNpmmUN_h0wN0nIYc_LOrXr0s4,3190
|
|
9
|
-
harp_python-0.3.0.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
|
10
|
-
harp_python-0.3.0.dist-info/top_level.txt,sha256=ztK1iHjgwmfXqxHCpu-e2uHIwdmodywYEUaWSODMvyM,5
|
|
11
|
-
harp_python-0.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|