1+ import os
12import re
23from math import log2
34from os import PathLike
5+ from pathlib import Path
46from functools import partial
57from numpy import dtype
68from pandas import DataFrame , Series
7- from typing import Any , BinaryIO , Iterable , Callable , Optional , Union
9+ from typing import Any , BinaryIO , Iterable , Optional , Protocol , Union
810from pandas ._typing import Axes
911from harp .model import BitMask , GroupMask , Model , PayloadMember , Register
1012from harp .io import read
1315_camel_to_snake_regex = re .compile (r"(?<!^)(?=[A-Z])" )
1416
1517
18+ class _ReadRegister (Protocol ):
19+ def __call__ (
20+ self , file : Optional [Union [str , bytes , PathLike [Any ], BinaryIO ]] = None
21+ ) -> DataFrame :
22+ ...
23+
24+
1625class RegisterReader :
1726 register : Register
18- read : Callable [[ Union [ str , bytes , PathLike [ Any ], BinaryIO ]], DataFrame ]
27+ read : _ReadRegister
1928
2029 def __init__ (
2130 self ,
2231 register : Register ,
23- read : Callable [[ Union [ str , bytes , PathLike [ Any ], BinaryIO ]], DataFrame ] ,
32+ read : _ReadRegister ,
2433 ) -> None :
2534 self .register = register
2635 self .read = read
@@ -111,7 +120,7 @@ def parser(df: DataFrame):
111120 if member .mask is not None :
112121 series = series & member .mask
113122 if shift > 0 :
114- series = Series (series .values >> shift , series .index ) # type: ignore
123+ series = Series (series .values >> shift , series .index ) # type: ignore
115124 if is_boolean :
116125 series = series != 0
117126 elif lookup is not None :
@@ -121,10 +130,14 @@ def parser(df: DataFrame):
121130 return parser
122131
123132
124- def _create_register_reader (register : Register ):
133+ def _create_register_reader (register : Register , base_path : Path ):
125134 def reader (
126- file : Union [str , bytes , PathLike [Any ], BinaryIO ], columns : Optional [Axes ] = None
135+ file : Optional [Union [str , bytes , PathLike [Any ], BinaryIO ]] = None ,
136+ columns : Optional [Axes ] = None ,
127137 ):
138+ if file is None :
139+ file = f"{ base_path } _{ register .address } .bin"
140+
128141 data = read (
129142 file ,
130143 address = register .address ,
@@ -137,9 +150,9 @@ def reader(
137150 return reader
138151
139152
140- def _create_register_parser (device : Model , name : str ):
153+ def _create_register_parser (device : Model , name : str , base_path : Path ):
141154 register = device .registers [name ]
142- reader = _create_register_reader (register )
155+ reader = _create_register_reader (register , base_path )
143156
144157 if register .maskType is not None :
145158 key = register .maskType .root
@@ -172,9 +185,22 @@ def parser(df: DataFrame):
172185 return RegisterReader (register , reader )
173186
174187
175- def create_reader (file : Union [str , PathLike ], include_common_registers : bool = True ):
176- device = read_schema (file , include_common_registers )
188+ def create_reader (
189+ device : Union [str , PathLike , Model ], include_common_registers : bool = True
190+ ):
191+ if isinstance (device , Model ):
192+ base_path = Path (device .device )
193+ else :
194+ path = Path (device ).absolute ().resolve ()
195+ is_dir = os .path .isdir (path )
196+ if is_dir :
197+ device = path / "device.yml"
198+
199+ device = read_schema (device , include_common_registers )
200+ base_path = path / device .device if is_dir else path .parent / device .device
201+
177202 reg_readers = {
178- name : _create_register_parser (device , name ) for name in device .registers .keys ()
203+ name : _create_register_parser (device , name , base_path )
204+ for name in device .registers .keys ()
179205 }
180206 return DeviceReader (device , reg_readers )
0 commit comments