From ced93e69423c5f9db4a526990eb73cf1a00c2c92 Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Sun, 4 Oct 2020 21:35:24 +0100 Subject: [PATCH] reflect cachew changes of exception handling and temporary suppression --- my/core/cachew.py | 23 ++++++----------------- my/core/common.py | 4 +--- my/core/error.py | 16 +++++++++------- my/location/takeout.py | 2 +- my/photos/__init__.py | 6 ++---- my/reddit.py | 2 +- my/rescuetime.py | 2 -- setup.py | 2 +- tests/bluemaestro.py | 3 --- tests/conftest.py | 8 ++++++++ tests/lastfm.py | 4 ---- tests/takeout.py | 3 --- 12 files changed, 29 insertions(+), 46 deletions(-) create mode 100644 tests/conftest.py diff --git a/my/core/cachew.py b/my/core/cachew.py index 61d0953..1579738 100644 --- a/my/core/cachew.py +++ b/my/core/cachew.py @@ -1,40 +1,29 @@ -# TODO this probably belongs to cachew? or cachew.experimental from contextlib import contextmanager from pathlib import Path def disable_cachew(): - ''' - NOTE: you need to use it before importing any function using @cachew.cachew - ''' - # TODO not sure... maybe it should instead use some hook.. it's a ibt ugly do try: import cachew except ImportError: # nothing to disable return - @cachew.doublewrap - def cachew_off(func=None, *args, **kwargs): - return func - old = cachew.cachew - cachew.cachew = cachew_off - return old + from cachew import settings + settings.ENABLE = False @contextmanager def disabled_cachew(): try: import cachew - except ModuleNotFoundError: - # no need to disable anything + except ImportError: + # nothing to disable yield return - old = disable_cachew() - try: + from cachew.extra import disabled_cachew + with disabled_cachew(): yield - finally: - cachew.cachew = old def cache_dir() -> Path: diff --git a/my/core/common.py b/my/core/common.py index b5b8d75..06743c1 100644 --- a/my/core/common.py +++ b/my/core/common.py @@ -202,7 +202,7 @@ if TYPE_CHECKING: mcachew: McachewType -# TODO ugh. I think it needs doublewrap, otherwise @mcachew without args doesn't work +# todo ugh. I think it needs doublewrap, otherwise @mcachew without args doesn't work def mcachew(*args, **kwargs): # type: ignore[no-redef] """ Stands for 'Maybe cachew'. @@ -214,8 +214,6 @@ def mcachew(*args, **kwargs): # type: ignore[no-redef] warnings.warn('cachew library not found. You might want to install it to speed things up. See https://github.com/karlicoss/cachew') return lambda orig_func: orig_func else: - import cachew.experimental - cachew.experimental.enable_exceptions() # TODO do it only once? return cachew.cachew(*args, **kwargs) diff --git a/my/core/error.py b/my/core/error.py index 70630f4..19f479c 100644 --- a/my/core/error.py +++ b/my/core/error.py @@ -105,18 +105,20 @@ def test_sort_res_by() -> None: # todo proper typevar? from datetime import datetime def set_error_datetime(e: Exception, dt: datetime) -> None: - # at the moment, we're using isoformat() instead of datetime directly to make it cachew-friendly - # once cachew preserves exception argument types, we can remove these hacks - e.args = e.args + (dt.isoformat(), ) + e.args = e.args + (dt,) # todo not sure if should return new exception? +# todo it might be problematic because might mess with timezones (when it's converted to string, it's converted to a shift) def extract_error_datetime(e: Exception) -> Optional[datetime]: from .common import fromisoformat import re - # TODO FIXME meh. definitely need to preserve exception args types in cachew if possible.. for x in reversed(e.args): - m = re.search(r'\d{4}-\d\d-\d\d(T..:..:..)?(\.\d{6})?(\+.....)?', x) + if isinstance(x, datetime): + return x + if not isinstance(x, str): + continue + m = re.search(r'\d{4}-\d\d-\d\d(...:..:..)?(\.\d{6})?(\+.....)?', x) if m is None: continue ss = m.group(0) @@ -134,8 +136,8 @@ def test_datetime_errors() -> None: assert extract_error_datetime(e1) is None set_error_datetime(e1, dt=dt) assert extract_error_datetime(e1) == dt - # test that cachew can handle it... - e2 = RuntimeError(str(e1.args)) + + e2 = RuntimeError(f'something something {dt} something else') assert extract_error_datetime(e2) == dt diff --git a/my/location/takeout.py b/my/location/takeout.py index 28be64f..a32242a 100644 --- a/my/location/takeout.py +++ b/my/location/takeout.py @@ -219,7 +219,7 @@ class Window: -# TODO cachew as well? +# todo cachew as well? # TODO maybe if tag is none, we just don't care? def get_groups(*args, **kwargs) -> List[LocInterval]: all_locations = iter(iter_locations(*args, **kwargs)) diff --git a/my/photos/__init__.py b/my/photos/__init__.py index abb6bb9..d444658 100644 --- a/my/photos/__init__.py +++ b/my/photos/__init__.py @@ -140,8 +140,6 @@ def _candidates() -> Iterable[str]: def photos() -> Iterator[Result]: candidates = tuple(sorted(_candidates())) return _photos(candidates) - # TODO figure out how to use cachew without helper function? - # I guess need lazy variables or something? # if geo information is missing from photo, you can specify it manually in geo.json file @@ -188,5 +186,5 @@ def print_all(): else: print(f"{p.dt} {p.path} {p.tags}") -# TODO cachew -- improve AttributeError: type object 'tuple' has no attribute '__annotations__' -- improve errors? -# TODO cachew -- invalidate if function code changed? +# todo cachew -- improve AttributeError: type object 'tuple' has no attribute '__annotations__' -- improve errors? +# todo cachew -- invalidate if function code changed? diff --git a/my/reddit.py b/my/reddit.py index 981a990..fd882ac 100755 --- a/my/reddit.py +++ b/my/reddit.py @@ -155,7 +155,7 @@ def _get_state(bfile: Path) -> Dict[Sid, SaveWithDt]: # it's called early so it ends up as a global variable that we can't monkey patch easily @mcachew def _get_events(backups: Sequence[Path], parallel: bool=True) -> Iterator[Event]: - # TODO cachew: let it transform return type? so you don't have to write a wrapper for lists? + # todo cachew: let it transform return type? so you don't have to write a wrapper for lists? prev_saves: Mapping[Sid, SaveWithDt] = {} # TODO suppress first batch?? diff --git a/my/rescuetime.py b/my/rescuetime.py index 1a0f664..45f8f58 100644 --- a/my/rescuetime.py +++ b/my/rescuetime.py @@ -73,8 +73,6 @@ from contextlib import contextmanager @contextmanager def fake_data(rows: int=1000) -> Iterator[None]: # todo also disable cachew automatically for such things? - # TODO right, disabled_cachew won't work here because at that point, entries() is already wrapped? - # I guess need to fix this in cachew? from .core.cachew import disabled_cachew from .core.cfg import override_config from tempfile import TemporaryDirectory diff --git a/setup.py b/setup.py index 657ed1d..377bc1c 100644 --- a/setup.py +++ b/setup.py @@ -61,7 +61,7 @@ def main(): 'optional': [ # TODO document these? 'logzero', - 'cachew', + 'cachew>=0.8.0', 'mypy', # used for config checks ], ':python_version<"3.7"': [ diff --git a/tests/bluemaestro.py b/tests/bluemaestro.py index e397f08..9d81447 100644 --- a/tests/bluemaestro.py +++ b/tests/bluemaestro.py @@ -1,9 +1,6 @@ #!/usr/bin/env python3 from pathlib import Path -from my.core.cachew import disable_cachew -disable_cachew() # meh - def test() -> None: from my.bluemaestro import measurements diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..334cd19 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,8 @@ +import pytest # type: ignore + +# I guess makes sense by default +@pytest.fixture(autouse=True) +def without_cachew(): + from my.core.cachew import disabled_cachew + with disabled_cachew(): + yield diff --git a/tests/lastfm.py b/tests/lastfm.py index 4b37e24..a93fc4b 100644 --- a/tests/lastfm.py +++ b/tests/lastfm.py @@ -1,7 +1,3 @@ -from my.core.cachew import disable_cachew -# TODO need something nicer and integrated inside cachew.. -disable_cachew() # meh - from more_itertools import ilen from my.lastfm import scrobbles diff --git a/tests/takeout.py b/tests/takeout.py index 101a037..69e16de 100644 --- a/tests/takeout.py +++ b/tests/takeout.py @@ -3,9 +3,6 @@ from datetime import datetime from itertools import islice import pytz -from my.core.cachew import disable_cachew -disable_cachew() - import my.location.takeout as LT from my.google.takeout.html import read_html from my.google.takeout.paths import get_last_takeout