From 7cae9d5bf367f0c5d2a1cc158cb5782a523666b1 Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Sun, 25 Aug 2024 22:36:54 +0100 Subject: [PATCH] my.google.takeout.paths: migrate to new style lazy config also clean up tests a little and move into my.tests.location.google --- my/google/takeout/paths.py | 45 ++++++++++++++++++------------ my/tests/common.py | 4 +++ my/tests/location/google.py | 55 +++++++++++++++++++++++++++++++++++++ tests/location.py | 28 ------------------- 4 files changed, 86 insertions(+), 46 deletions(-) create mode 100644 my/tests/location/google.py delete mode 100644 tests/location.py diff --git a/my/google/takeout/paths.py b/my/google/takeout/paths.py index 5b53149..948cf2e 100644 --- a/my/google/takeout/paths.py +++ b/my/google/takeout/paths.py @@ -2,44 +2,53 @@ Module for locating and accessing [[https://takeout.google.com][Google Takeout]] data ''' -from dataclasses import dataclass -from ...core.common import Paths, get_files -from ...core.util import __NOT_HPI_MODULE__ - -from my.config import google as user_config +from abc import abstractmethod +from pathlib import Path +from typing import Iterable, Optional, Protocol from more_itertools import last -@dataclass -class google(user_config): - takeout_path: Paths # path/paths/glob for the takeout zips -### +from my.core import __NOT_HPI_MODULE__, Paths, get_files + + +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 -from ...core.cfg import make_config -config = make_config(google) -from pathlib import Path -from typing import Optional, Iterable +def make_config() -> config: + 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 """ - # TODO FIXME zip is not great.. + # TODO zip is not great.. # 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(): 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) # TODO might be a good idea to merge across multiple takeouts... # perhaps even a special takeout module that deals with all of this automatically? # e.g. accumulate, filter and maybe report useless takeouts? - diff --git a/my/tests/common.py b/my/tests/common.py index f8b645d..962ee46 100644 --- a/my/tests/common.py +++ b/my/tests/common.py @@ -31,3 +31,7 @@ def testdata() -> Path: d = Path(__file__).absolute().parent.parent.parent / 'testdata' assert d.exists(), d return d + + +# prevent pytest from treating this as test +testdata.__test__ = False # type: ignore[attr-defined] diff --git a/my/tests/location/google.py b/my/tests/location/google.py new file mode 100644 index 0000000..612522b --- /dev/null +++ b/my/tests/location/google.py @@ -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 diff --git a/tests/location.py b/tests/location.py deleted file mode 100644 index 2597d5e..0000000 --- a/tests/location.py +++ /dev/null @@ -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 -