''' Weight data (manually logged) ''' from collections.abc import Iterator from dataclasses import dataclass from datetime import datetime from typing import Any from my import orgmode from my.core import make_logger from my.core.error import Res, extract_error_datetime, set_error_datetime config = Any def make_config() -> config: from my.config import weight as user_config # type: ignore[attr-defined] return user_config() log = make_logger(__name__) @dataclass class Entry: dt: datetime value: float # TODO comment?? Result = Res[Entry] def from_orgmode() -> Iterator[Result]: cfg = make_config() orgs = orgmode.query() for o in orgmode.query().all(): if 'weight' not in o.tags: continue try: # TODO can it throw? not sure created = o.created assert created is not None except Exception as e: log.exception(e) yield e continue try: w = float(o.heading) except Exception as e: set_error_datetime(e, dt=created) log.exception(e) yield e continue # FIXME use timezone provider created = cfg.default_timezone.localize(created) assert created is not None # ??? somehow mypy wasn't happy? yield Entry( dt=created, value=w, # TODO add org note content as comment? ) def make_dataframe(data: Iterator[Result]): import pandas as pd def it(): for e in data: if isinstance(e, Exception): dt = extract_error_datetime(e) yield { 'dt': dt, 'error': str(e), } else: yield { 'dt': e.dt, 'weight': e.value, } df = pd.DataFrame(it()) df = df.set_index('dt') # TODO not sure about UTC?? df.index = pd.to_datetime(df.index, utc=True) return df def dataframe(): entries = from_orgmode() return make_dataframe(entries) # TODO move to a submodule? e.g. my.body.weight.orgmode? # so there could be more sources # not sure about my.body thing though