Skip to content

Commit fa9671b

Browse files
authored
Merge pull request #18 from harp-tech/gl-dev
Allow setting default params when creating device reader
2 parents e54ce51 + 7829bd1 commit fa9671b

2 files changed

Lines changed: 37 additions & 15 deletions

File tree

harp/reader.py

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pathlib import Path
66
from datetime import datetime
77
from functools import partial
8+
from dataclasses import dataclass
89
from numpy import dtype
910
from pandas import DataFrame, Series
1011
from typing import Any, BinaryIO, Callable, Iterable, Optional, Protocol, Union
@@ -16,6 +17,13 @@
1617
_camel_to_snake_regex = re.compile(r"(?<!^)(?=[A-Z])")
1718

1819

20+
@dataclass
21+
class _ReaderParams:
22+
path: Path
23+
epoch: Optional[datetime] = None
24+
keep_type: bool = False
25+
26+
1927
class _ReadRegister(Protocol):
2028
def __call__(
2129
self,
@@ -55,13 +63,15 @@ def __getattr__(self, __name: str) -> RegisterReader:
5563

5664

5765
def _compose_parser(
58-
f: Callable[[DataFrame], DataFrame], g: Callable[..., DataFrame]
66+
f: Callable[[DataFrame], DataFrame],
67+
g: Callable[..., DataFrame],
68+
params: _ReaderParams,
5969
) -> Callable[..., DataFrame]:
6070
def parser(
6171
file: Optional[Union[str, bytes, PathLike[Any], BinaryIO]] = None,
6272
columns: Optional[Axes] = None,
63-
epoch: Optional[datetime] = None,
64-
keep_type: bool = False,
73+
epoch: Optional[datetime] = params.epoch,
74+
keep_type: bool = params.keep_type,
6575
):
6676
df = g(file, columns, epoch, keep_type)
6777
result = f(df)
@@ -149,15 +159,15 @@ def parser(df: DataFrame):
149159
return parser
150160

151161

152-
def _create_register_reader(register: Register, base_path: Path):
162+
def _create_register_reader(register: Register, params: _ReaderParams):
153163
def reader(
154164
file: Optional[Union[str, bytes, PathLike[Any], BinaryIO]] = None,
155165
columns: Optional[Axes] = None,
156-
epoch: Optional[datetime] = None,
157-
keep_type: bool = False,
166+
epoch: Optional[datetime] = params.epoch,
167+
keep_type: bool = params.keep_type,
158168
):
159169
if file is None:
160-
file = f"{base_path}_{register.address}.bin"
170+
file = f"{params.path}_{register.address}.bin"
161171

162172
data = read(
163173
file,
@@ -173,22 +183,22 @@ def reader(
173183
return reader
174184

175185

176-
def _create_register_parser(device: Model, name: str, base_path: Path):
186+
def _create_register_parser(device: Model, name: str, params: _ReaderParams):
177187
register = device.registers[name]
178-
reader = _create_register_reader(register, base_path)
188+
reader = _create_register_reader(register, params)
179189

180190
if register.maskType is not None:
181191
key = register.maskType.root
182192
bitMask = None if device.bitMasks is None else device.bitMasks.get(key)
183193
if bitMask is not None:
184194
parser = _create_bitmask_parser(bitMask)
185-
reader = _compose_parser(parser, reader)
195+
reader = _compose_parser(parser, reader, params)
186196
return RegisterReader(register, reader)
187197

188198
groupMask = None if device.groupMasks is None else device.groupMasks.get(key)
189199
if groupMask is not None:
190200
parser = _create_groupmask_parser(name, groupMask)
191-
reader = _compose_parser(parser, reader)
201+
reader = _compose_parser(parser, reader, params)
192202
return RegisterReader(register, reader)
193203

194204
if register.payloadSpec is not None:
@@ -200,7 +210,7 @@ def _create_register_parser(device: Model, name: str, base_path: Path):
200210
def parser(df: DataFrame):
201211
return DataFrame({n: f(df) for n, f in payload_parsers}, index=df.index)
202212

203-
reader = _compose_parser(parser, reader)
213+
reader = _compose_parser(parser, reader, params)
204214
return RegisterReader(register, reader)
205215

206216
columns = [_id_camel_to_snake(name)]
@@ -209,7 +219,10 @@ def parser(df: DataFrame):
209219

210220

211221
def create_reader(
212-
device: Union[str, PathLike, Model], include_common_registers: bool = True
222+
device: Union[str, PathLike, Model],
223+
include_common_registers: bool = True,
224+
epoch: Optional[datetime] = None,
225+
keep_type: bool = False,
213226
):
214227
if isinstance(device, Model):
215228
base_path = Path(device.device)
@@ -223,7 +236,9 @@ def create_reader(
223236
base_path = path / device.device if is_dir else path.parent / device.device
224237

225238
reg_readers = {
226-
name: _create_register_parser(device, name, base_path)
239+
name: _create_register_parser(
240+
device, name, _ReaderParams(base_path, epoch, keep_type)
241+
)
227242
for name in device.registers.keys()
228243
}
229244
return DeviceReader(device, reg_readers)

tests/test_reader.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import numpy as np
12
from pytest import mark
3+
from harp.io import REFERENCE_EPOCH, MessageType
24
from harp.reader import create_reader
35
from tests.params import DeviceSchemaParam
46

@@ -18,8 +20,13 @@
1820

1921
@mark.parametrize("schemaFile", testdata)
2022
def test_create_reader(schemaFile: DeviceSchemaParam):
21-
reader = create_reader(schemaFile.path)
23+
reader = create_reader(schemaFile.path, epoch=REFERENCE_EPOCH)
2224
schemaFile.assert_schema(reader.device)
2325

2426
whoAmI = reader.WhoAmI.read()
2527
assert reader.device.whoAmI == whoAmI.iloc[0, 0]
28+
assert whoAmI.index.dtype.type == np.datetime64
29+
30+
whoAmI = reader.WhoAmI.read(epoch=None, keep_type=True)
31+
assert whoAmI.index.dtype.type == np.float64
32+
assert whoAmI.iloc[0, -1] == MessageType.READ.name

0 commit comments

Comments
 (0)