''' Rescuetime (phone activity tracking) data. ''' REQUIRES = [ 'git+https://github.com/karlicoss/rescuexport', ] from pathlib import Path from datetime import timedelta from typing import Sequence, Iterable from my.core import get_files, make_logger from my.core.common import mcachew from my.core.error import Res, split_errors from my.config import rescuetime as config logger = make_logger(__name__) def inputs() -> Sequence[Path]: return get_files(config.export_path) import rescuexport.dal as dal DAL = dal.DAL Entry = dal.Entry @mcachew(depends_on=inputs) def entries() -> Iterable[Res[Entry]]: dal = DAL(inputs()) yield from dal.entries() def groups(gap: timedelta=timedelta(hours=3)) -> Iterable[Res[Sequence[Entry]]]: vit, eit = split_errors(entries(), ET=Exception) yield from eit from more_itertools import split_when yield from split_when(vit, lambda a, b: (b.dt - a.dt) > gap) # todo automatic dataframe interface? from .core.pandas import DataFrameT, as_dataframe def dataframe() -> DataFrameT: return as_dataframe(entries()) from .core import stat, Stats def stats() -> Stats: return { **stat(groups), **stat(entries), } # basically, hack config and populate it with fake data? fake data generated by DAL, but the rest is handled by this? from contextlib import contextmanager from typing import Iterator # todo take seed, or what? @contextmanager def fake_data(rows: int=1000) -> Iterator: # todo also disable cachew automatically for such things? from my.core.cfg import tmp_config from my.core.cachew import disabled_cachew from tempfile import TemporaryDirectory import json with disabled_cachew(), TemporaryDirectory() as td: tdir = Path(td) f = tdir / 'rescuetime.json' f.write_text(json.dumps(dal.fake_data_generator(rows=rows))) class override: class rescuetime: export_path = tdir with tmp_config(modules=__name__, config=override) as cfg: yield cfg # TODO ok, now it's something that actually could run on CI! # todo would be kinda nice if doctor could run against the fake data, to have a basic health check of the module? def fill_influxdb() -> None: from .core import influxdb it = (dict( dt=e.dt, duration_d=e.duration_s, tags=dict(activity=e.activity), ) for e in entries() if isinstance(e, Entry)) # TODO handle errors in core.influxdb influxdb.fill(it, measurement=__name__) # TODO lots of garbage in dir()? maybe need to del the imports...