FileReader #5
@@ -23,10 +23,6 @@ class FileDatasource:
|
||||
|
||||
self._started = False
|
||||
|
||||
# one-row buffers (supports CSVs with or without header)
|
||||
self._acc_has_header: Optional[bool] = None
|
||||
self._gps_has_header: Optional[bool] = None
|
||||
|
||||
def startReading(self, *args, **kwargs):
|
||||
"""Must be called before read()"""
|
||||
if self._started:
|
||||
@@ -50,8 +46,8 @@ class FileDatasource:
|
||||
if not self._started:
|
||||
raise RuntimeError("Datasource is not started. Call startReading() before read().")
|
||||
|
||||
acc_row = self._get_next_row(self._acc_reader)
|
||||
gps_row = self._get_next_row(self._gps_reader)
|
||||
acc_row = self._get_next_row(self._acc_reader, source="acc")
|
||||
gps_row = self._get_next_row(self._gps_reader, source="gps")
|
||||
|
||||
acc = self._parse_acc(acc_row)
|
||||
gps = self._parse_gps(gps_row)
|
||||
@@ -78,10 +74,6 @@ class FileDatasource:
|
||||
self._acc_reader = csv.reader(self._acc_f, skipinitialspace=True)
|
||||
self._gps_reader = csv.reader(self._gps_f, skipinitialspace=True)
|
||||
|
|
||||
|
||||
self._acc_has_header = None
|
||||
self._gps_has_header = None
|
||||
|
||||
# detect header / buffer first data row (we only need the buffered row)
|
||||
self._rewind_acc()
|
||||
self._rewind_gps()
|
||||
|
if you open file, your read pointer is already 0, why to set it to 0 again? if you open file, your read pointer is already 0, why to set it to 0 again?
I removed the unnecessary rewind from _open_files(). I removed the unnecessary rewind from _open_files().
|
||||
|
||||
@@ -103,22 +95,16 @@ class FileDatasource:
|
||||
raise RuntimeError("Accelerometer file is not open.")
|
||||
self._acc_f.seek(0)
|
||||
self._acc_reader = csv.reader(self._acc_f, skipinitialspace=True)
|
||||
next(self._acc_reader) # Skip header row
|
||||
_ = self._detect_header_and_buffer(
|
||||
self._acc_reader, expected_cols=3, header_tokens=("x", "y", "z")
|
||||
)
|
||||
next(self._acc_reader, None) # skip header row
|
||||
|
||||
def _rewind_gps(self) -> None:
|
||||
if self._gps_f is None:
|
||||
raise RuntimeError("GPS file is not open.")
|
||||
self._gps_f.seek(0)
|
||||
self._gps_reader = csv.reader(self._gps_f, skipinitialspace=True)
|
||||
|
Why leave _ here if it's not used? Why leave _ here if it's not used?
Good catch. The _detect_header_and_buffer helper wasn’t used and didn’t modify class state, so I removed it. Good catch. The _detect_header_and_buffer helper wasn’t used and didn’t modify class state, so I removed it.
|
||||
next(self._gps_reader) # Skip header row
|
||||
_ = self._detect_header_and_buffer(
|
||||
self._gps_reader, expected_cols=2, header_tokens=("longitude", "latitude")
|
||||
)
|
||||
next(self._gps_reader, None) # skip header row
|
||||
|
||||
def _get_next_row(self, reader) -> List[str]:
|
||||
def _get_next_row(self, reader, source: str) -> List[str]:
|
||||
"""Get the next valid row from the reader."""
|
||||
if reader is None:
|
||||
raise RuntimeError("Reader is not initialized.")
|
||||
@@ -127,7 +113,12 @@ class FileDatasource:
|
||||
row = next(reader, None)
|
||||
if row is None:
|
||||
|
Why leave _ here if it's not used? Why leave _ here if it's not used?
Maybe dont return anything from this method?
As I see this method doesn't modify any class fiels, so maybe just remove this method? As I see this method doesn't modify any class fiels, so maybe just remove this method?
The _detect_header_and_buffer method was not modifying any class state and its return value was unused. The _detect_header_and_buffer method was not modifying any class state and its return value was unused.
I removed the method and simplified the logic.
|
||||
# EOF -> rewind & continue
|
||||
self._rewind_acc() if reader == self._acc_reader else self._rewind_gps()
|
||||
if source == "acc":
|
||||
self._rewind_acc()
|
||||
reader = self._acc_reader
|
||||
else:
|
||||
self._rewind_gps()
|
||||
reader = self._gps_reader
|
||||
continue
|
||||
|
||||
if not row or not any(cell.strip() for cell in row):
|
||||
@@ -135,32 +126,6 @@ class FileDatasource:
|
||||
|
||||
return row
|
||||
|
||||
@staticmethod
|
||||
def _detect_header_and_buffer(
|
||||
rdr: csv.reader, expected_cols: int, header_tokens: tuple[str, ...]
|
||||
) -> tuple[bool, Optional[List[str]]]:
|
||||
|
||||
first = None
|
||||
while True:
|
||||
first = next(rdr, None)
|
||||
if first is None:
|
||||
return False, None
|
||||
if first and any(first):
|
||||
break
|
||||
|
||||
norm = [c.strip().lower() for c in first]
|
||||
|
||||
# Header if it contains the expected tokens
|
||||
if all(tok in norm for tok in header_tokens):
|
||||
return True, None
|
||||
|
||||
# If first row is numeric-like and has enough columns => it's data (buffer it back)
|
||||
if len(norm) >= expected_cols and all(FileDatasource._is_number(x) for x in norm[:expected_cols]):
|
||||
return False, first
|
||||
|
||||
# Otherwise treat it as header-ish (skip it)
|
||||
return True, None
|
||||
|
||||
@staticmethod
|
||||
def _parse_acc(row: List[str]) -> Accelerometer:
|
||||
|
This looks a bit comlex This looks a bit comlex
Why itarate though loop to get 1 row?
"Simplified the line reading logic by replacing the while True loop with a clearer check "Simplified the line reading logic by replacing the while True loop with a clearer check
|
||||
if len(row) < 3:
|
||||
@@ -181,12 +146,4 @@ class FileDatasource:
|
||||
raise ValueError(f"GPS row must have 2 values (longitude,latitude). Got: {row}")
|
||||
lon = float(row[0])
|
||||
lat = float(row[1])
|
||||
return Gps(longitude=lon, latitude=lat)
|
||||
|
||||
@staticmethod
|
||||
def _is_number(s: str) -> bool:
|
||||
try:
|
||||
float(s)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
return Gps(longitude=lon, latitude=lat)
|
||||
Reference in New Issue
Block a user
You just can not return this variable from _detect_header_and_buffer() if it is not used
removed unnecessary variables from _detect_header_and_buffer() and fixed the _rewind_acc() and _rewind_gps() methods