Skip to content
Snippets Groups Projects
Commit 56c697da5c21 authored by jfp's avatar jfp
Browse files

Add ovms.rms.SequentialFile module

parent b8c0658b3bf3
Branches
No related tags found
No related merge requests found
# -*- coding: iso-8859-1 -*-
#
from typing import Callable
from . import (
file,
error,
RmsFile,
)
from ovms.fabdef import (
FAB_M_PUT,
FAB_M_GET,
FAB_M_DEL,
FAB_M_UPD,
FAB_M_SHRPUT,
FAB_M_SHRGET,
FAB_M_SHRDEL,
FAB_M_SHRUPD,
)
from ovms.rabdef import RAB_M_LIM, RAB_M_KGT, RAB_M_KGE, RAB_M_REV
from ovms.rmsdef import RMS__RNF, RMS__EOF, RMS__OK_LIM
from construct import Struct, Container
class FileNotOpened(ValueError):
def __init__(self, value=None):
self.value = value
def __str__(self):
ret = 'I/O operation on closed file'
if self.value:
ret = '%s\n %s' % (ret, self.value)
return ret
class SequentialFile(object):
_ACC = dict(p=FAB_M_PUT, g=FAB_M_GET, d=FAB_M_DEL, u=FAB_M_UPD)
_SHR = dict(p=FAB_M_SHRPUT, g=FAB_M_SHRGET, d=FAB_M_SHRDEL, u=FAB_M_SHRUPD)
_FOP = dict()
_file: RmsFile
def __init__(
self,
filename,
item_class,
acc: int | str = FAB_M_PUT + FAB_M_GET + FAB_M_DEL + FAB_M_UPD,
shr: int
| str = FAB_M_SHRPUT + FAB_M_SHRGET + FAB_M_SHRDEL + FAB_M_SHRUPD,
fop=0,
):
self.filename = filename
self._status = None
self._item_class = item_class
self._file = None # type: ignore
self._opened_in_with = False
self._acc = self._decode_acc(acc)
self._shr = self._decode_shr(shr)
self._fop = self._decode_fop(fop)
def __del__(self):
if self._file:
self.close()
@staticmethod
def _decode(dict_val, def_val):
def _decode_val(self, val):
if val is None:
return getattr(self, def_val)
if isinstance(val, int):
return val
val = val.lower()
return sum([v for k, v in dict_val.items() if k in val])
return _decode_val
_decode_acc = _decode(_ACC, '_acc')
_decode_shr = _decode(_SHR, '_shr')
_decode_fop = _decode(_FOP, '_fop')
def __iter__(self):
if not self._file:
raise FileNotOpened
return self
def __next__(self):
try:
rec = next(self._file)
except StopIteration:
raise
return self._item_class.parse(rec)
def next(self):
try:
rec = next(self._file)
except StopIteration:
return None
return self._item_class.parse(rec)
def rewind(self):
if not self._file:
raise FileNotOpened
self._file.rewind()
def open(
self,
acc=None,
shr=None,
fop=None,
):
acc = self._acc if acc is None else self._decode_acc(acc)
shr = self._shr if shr is None else self._decode_shr(shr)
fop = self._fop if fop is None else self._decode_fop(fop)
self._status = None
self._file = file(self.filename, fac=acc, shr=shr, fop=fop)
def close(self):
if not self._file:
raise FileNotOpened
self._file.close()
self._file = None # type: ignore
self._opened_in_with = False
def __enter__(self):
if not self._file:
self.open()
self._opened_in_with = True
return self
def __exit__(self, type, value, traceback):
if self._opened_in_with:
self.close()
def status(self):
return self._status
def put(self, rec):
if not self._file:
raise FileNotOpened
f = self._file
self._status = None
rec = self._item_class.build(rec)
try:
self._status = f.put(rec)
except error:
raise
def delete_current(self):
if not self._file:
raise FileNotOpened
self._status = None
try:
self._status = self._file.delete()
except error:
raise
def fetch(self, item_class=None) -> Container | None:
if not self._file:
raise FileNotOpened
if item_class is None:
item_class = self._item_class
f = self._file
self._status = None
try:
self._status, r = f.fetch()
except error:
raise
if self._status == RMS__RNF:
return None
return item_class.parse(r)
def fetch_next(self, item_class=None):
if not self._file:
raise FileNotOpened
if item_class is None:
item_class = self._item_class
f = self._file
self._status = None
self._status, r = f.fetch()
if self._status % 2 == 0:
return None
return item_class.parse(r)
def update_current(self, rec: Container) -> bool:
if not self._file:
raise FileNotOpened
self._status = None
try:
rec = self._item_class.build(rec)
self._status = self._file.update(rec)
if not self._status & 1:
return False
except error:
raise
return True
update = update_current
def fetchall(
self,
stop: Callable | None = None,
limit=None,
):
if not self._file:
raise FileNotOpened
f = self._file
self._status = None
f.rewind()
if limit is not None:
limit -= 1
for n, r in enumerate(f):
rec = self._item_class.parse(r)
if stop and stop(rec):
break
yield rec
if limit is not None and n >= limit:
break
return
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment