my.google.takeout.paths: migrate to new style lazy config

also clean up tests a little and move into my.tests.location.google
This commit is contained in:
Dima Gerasimov 2024-08-25 22:36:54 +01:00 committed by karlicoss
parent 2ff2dcfc00
commit 7cae9d5bf3
4 changed files with 86 additions and 46 deletions

View file

@ -2,44 +2,53 @@
Module for locating and accessing [[https://takeout.google.com][Google Takeout]] data Module for locating and accessing [[https://takeout.google.com][Google Takeout]] data
''' '''
from dataclasses import dataclass from abc import abstractmethod
from ...core.common import Paths, get_files from pathlib import Path
from ...core.util import __NOT_HPI_MODULE__ from typing import Iterable, Optional, Protocol
from my.config import google as user_config
from more_itertools import last from more_itertools import last
@dataclass from my.core import __NOT_HPI_MODULE__, Paths, get_files
class google(user_config):
takeout_path: Paths # path/paths/glob for the takeout zips
### class config:
"""
path/paths/glob for the takeout zips
"""
@property
@abstractmethod
def takeout_path(self) -> Paths:
raise NotImplementedError
# TODO rename 'google' to 'takeout'? not sure # TODO rename 'google' to 'takeout'? not sure
from ...core.cfg import make_config
config = make_config(google)
from pathlib import Path def make_config() -> config:
from typing import Optional, Iterable from my.config import google as user_config
class combined_config(user_config, config): ...
return combined_config()
def get_takeouts(*, path: Optional[str]=None) -> Iterable[Path]: def get_takeouts(*, path: Optional[str] = None) -> Iterable[Path]:
""" """
Sometimes google splits takeout into multiple archives, so we need to detect the ones that contain the path we need Sometimes google splits takeout into multiple archives, so we need to detect the ones that contain the path we need
""" """
# TODO FIXME zip is not great.. # TODO zip is not great..
# allow a lambda expression? that way the user could restrict it # allow a lambda expression? that way the user could restrict it
for takeout in get_files(config.takeout_path, glob='*.zip'): cfg = make_config()
for takeout in get_files(cfg.takeout_path, glob='*.zip'):
if path is None or (takeout / path).exists(): if path is None or (takeout / path).exists():
yield takeout yield takeout
def get_last_takeout(*, path: Optional[str]=None) -> Optional[Path]: def get_last_takeout(*, path: Optional[str] = None) -> Optional[Path]:
return last(get_takeouts(path=path), default=None) return last(get_takeouts(path=path), default=None)
# TODO might be a good idea to merge across multiple takeouts... # TODO might be a good idea to merge across multiple takeouts...
# perhaps even a special takeout module that deals with all of this automatically? # perhaps even a special takeout module that deals with all of this automatically?
# e.g. accumulate, filter and maybe report useless takeouts? # e.g. accumulate, filter and maybe report useless takeouts?

View file

@ -31,3 +31,7 @@ def testdata() -> Path:
d = Path(__file__).absolute().parent.parent.parent / 'testdata' d = Path(__file__).absolute().parent.parent.parent / 'testdata'
assert d.exists(), d assert d.exists(), d
return d return d
# prevent pytest from treating this as test
testdata.__test__ = False # type: ignore[attr-defined]

View file

@ -0,0 +1,55 @@
"""
Tests for LEGACY location provider
Keeping for now for backwards compatibility
"""
from pathlib import Path
import pytest
from more_itertools import one
from my.core.cfg import tmp_config
from my.location.google import locations
def test_google_locations() -> None:
locs = list(locations())
assert len(locs) == 3810, len(locs)
last = locs[-1]
assert last.dt.strftime('%Y%m%d %H:%M:%S') == '20170802 13:01:56' # should be utc
# todo approx
assert last.lat == 46.5515350
assert last.lon == 16.4742742
# todo check altitude
@pytest.fixture(autouse=True)
def prepare(tmp_path: Path):
# TODO could just pick a part of shared config? not sure
_takeout_path = _prepare_takeouts_dir(tmp_path)
class google:
takeout_path = _takeout_path
with tmp_config() as config:
config.google = google
yield
def _prepare_takeouts_dir(tmp_path: Path) -> Path:
from ..common import testdata
try:
track = one(testdata().rglob('italy-slovenia-2017-07-29.json'))
except ValueError:
raise RuntimeError('testdata not found, setup git submodules?')
# todo ugh. unnecessary zipping, but at the moment takeout provider doesn't support plain dirs
import zipfile
with zipfile.ZipFile(tmp_path / 'takeout.zip', 'w') as zf:
zf.writestr('Takeout/Location History/Location History.json', track.read_bytes())
return tmp_path

View file

@ -1,28 +0,0 @@
from pathlib import Path
import pytest
def test() -> None:
from my.location.google import locations
locs = list(locations())
assert len(locs) == 3810
last = locs[-1]
assert last.dt.strftime('%Y%m%d %H:%M:%S') == '20170802 13:01:56' # should be utc
# todo approx
assert last.lat == 46.5515350
assert last.lon == 16.4742742
# todo check altitude
@pytest.fixture(autouse=True)
def prepare(tmp_path: Path):
from .shared_config import temp_config
user_config = temp_config(tmp_path)
import my.core.cfg as C
with C.tmp_config() as config:
config.google = user_config.google
yield