ib-related: cope with invalid txn timestamps
That is inside embedded `.accounting.calc.dyn_parse_to_dt()` closure add an optional `_invalid: list` param to where we can report bad-timestamped records which we instead override and return as `from_timestamp(0.)` (when the parser loop falls through) and report later (in summary ) from the `.accounting.calc.iter_by_dt()` caller . Add some logging and an optional debug block for future tracing.alt_tpts_for_perf
parent
9df1988aa6
commit
a45de0b710
|
@ -22,7 +22,9 @@ you know when you're losing money (if possible) XD
|
|||
from __future__ import annotations
|
||||
from collections.abc import ValuesView
|
||||
from contextlib import contextmanager as cm
|
||||
from functools import partial
|
||||
from math import copysign
|
||||
from pprint import pformat
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
|
@ -37,12 +39,16 @@ from pendulum import (
|
|||
parse,
|
||||
)
|
||||
|
||||
from ..log import get_logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ._ledger import (
|
||||
Transaction,
|
||||
TransactionLedger,
|
||||
)
|
||||
|
||||
log = get_logger(__name__)
|
||||
|
||||
|
||||
def ppu(
|
||||
clears: Iterator[Transaction],
|
||||
|
@ -238,6 +244,9 @@ def iter_by_dt(
|
|||
|
||||
def dyn_parse_to_dt(
|
||||
tx: tuple[str, dict[str, Any]] | Transaction,
|
||||
|
||||
debug: bool = False,
|
||||
_invalid: list|None = None,
|
||||
) -> DateTime:
|
||||
|
||||
# handle `.items()` inputs
|
||||
|
@ -250,11 +259,16 @@ def iter_by_dt(
|
|||
# get best parser for this record..
|
||||
for k in parsers:
|
||||
if (
|
||||
isdict and k in tx
|
||||
or getattr(tx, k, None)
|
||||
(v := getattr(tx, k, None))
|
||||
or
|
||||
(
|
||||
isdict
|
||||
and
|
||||
(v := tx.get(k))
|
||||
)
|
||||
):
|
||||
v = tx[k] if isdict else tx.dt
|
||||
assert v is not None, f'No valid value for `{k}`!?'
|
||||
# TODO? remove yah?
|
||||
# v = tx[k] if isdict else tx.dt
|
||||
|
||||
# only call parser on the value if not None from
|
||||
# the `parsers` table above (when NOT using
|
||||
|
@ -262,21 +276,54 @@ def iter_by_dt(
|
|||
# sort on it directly
|
||||
if (
|
||||
not isinstance(v, DateTime)
|
||||
and (parser := parsers.get(k))
|
||||
and
|
||||
(parser := parsers.get(k))
|
||||
):
|
||||
return parser(v)
|
||||
ret = parser(v)
|
||||
else:
|
||||
return v
|
||||
ret = v
|
||||
|
||||
return ret
|
||||
|
||||
else:
|
||||
continue
|
||||
|
||||
# XXX: should never get here..
|
||||
else:
|
||||
# XXX: should never get here..
|
||||
breakpoint()
|
||||
if debug:
|
||||
import tractor
|
||||
with tractor.devx.maybe_open_crash_handler():
|
||||
raise ValueError(
|
||||
f'Invalid txn time ??\n'
|
||||
f'txn-id: {k!r}\n'
|
||||
f'{k!r}: {v!r}\n'
|
||||
)
|
||||
# assert v is not None, f'No valid value for `{k}`!?'
|
||||
|
||||
entry: tuple[str, dict] | Transaction
|
||||
if _invalid is not None:
|
||||
_invalid.append(tx)
|
||||
return from_timestamp(0.)
|
||||
|
||||
# breakpoint()
|
||||
|
||||
entry: tuple[str, dict]|Transaction
|
||||
invalid: list = []
|
||||
for entry in sorted(
|
||||
records,
|
||||
key=key or dyn_parse_to_dt,
|
||||
key=key or partial(
|
||||
dyn_parse_to_dt,
|
||||
_invalid=invalid,
|
||||
),
|
||||
):
|
||||
if entry in invalid:
|
||||
log.warning(
|
||||
f'Ignoring txn w invalid timestamp ??\n'
|
||||
f'{pformat(entry)}\n'
|
||||
# f'txn-id: {k!r}\n'
|
||||
# f'{k!r}: {v!r}\n'
|
||||
)
|
||||
continue
|
||||
|
||||
# NOTE the type sig above; either pairs or txns B)
|
||||
yield entry
|
||||
|
||||
|
|
Loading…
Reference in New Issue