Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add exclude_kwargs to memoization decorators #38

Merged
merged 2 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ non-`path-like object
<https://docs.python.org/3/glossary.html#term-path-like-object>`_ as the value
of ``path``, the cache is ignored.

``memoize_path()`` optionally takes an ``exclude_kwargs`` argument, which must
be a sequence of names of arguments of the decorated function that will be
ignored for caching purposes.

Caches are stored on-disk and thus persist between Python runs. To clear a
given ``PersistentCache`` and erase its data store, call the ``clear()``
method.
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ package_dir =
python_requires = >=3.7
install_requires =
appdirs == 1.*
joblib >= 0.17
joblib ~= 1.1

[options.extras_require]
benchmarks =
Expand Down
18 changes: 13 additions & 5 deletions src/fscacher/cache.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections import deque, namedtuple
from functools import wraps
from functools import partial, wraps
from hashlib import md5
from inspect import Parameter, signature
import logging
Expand Down Expand Up @@ -78,12 +78,16 @@ def clear(self):
except Exception as exc:
lgr.warning(f"Failed to clear out the cache directory: {exc}")

def memoize(self, f, ignore=None):
def memoize(self, f=None, *, exclude_kwargs=None):
if f is None:
return partial(self.memoize, exclude_kwargs=exclude_kwargs)
if self._ignore_cache:
return f
return self._memory.cache(f, ignore=ignore)
return self._memory.cache(f, ignore=exclude_kwargs)

def memoize_path(self, f):
def memoize_path(self, f=None, *, exclude_kwargs=None):
if f is None:
return partial(self.memoize_path, exclude_kwargs=exclude_kwargs)
if self._ignore_cache:
return f

Expand Down Expand Up @@ -112,7 +116,11 @@ def fingerprinted(path, *args, **kwargs):
# we need to ignore 'path' since we would like to dereference if symlink
# but then expect joblib's caching work on both original and dereferenced
# So we will add dereferenced path into fingerprint_kwarg
fingerprinted = self.memoize(fingerprinted, ignore=[path_arg])
fingerprinted = self.memoize(
fingerprinted,
exclude_kwargs=[path_arg]
+ (list(exclude_kwargs) if exclude_kwargs is not None else []),
)

@wraps(f)
def fingerprinter(*args, **kwargs):
Expand Down
42 changes: 42 additions & 0 deletions src/fscacher/tests/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,3 +504,45 @@ def strify(x):

assert strify(bar) == str(tmp_path / "bar")
assert calls == [path, bar]


def test_memoize_path_exclude_kwargs(cache, tmp_path):
calls = []

@cache.memoize_path(exclude_kwargs=["extra"])
def memoread_extra(path, arg, kwarg=None, extra=None):
calls.append((path, arg, kwarg, extra))
with open(path) as f:
return f.read()

path = tmp_path / "file.dat"
path.write_text("content")

time.sleep(cache._min_dtime * 1.1)

assert memoread_extra(path, 1, extra="foo") == "content"
assert calls == [(path, 1, None, "foo")]

assert memoread_extra(path, 1, extra="bar") == "content"
assert calls == [(path, 1, None, "foo")]

assert memoread_extra(path, 1, kwarg="quux", extra="bar") == "content"
assert calls == [(path, 1, None, "foo"), (path, 1, "quux", "bar")]

path.write_text("different")

time.sleep(cache._min_dtime * 1.1)

assert memoread_extra(path, 1, extra="foo") == "different"
assert calls == [
(path, 1, None, "foo"),
(path, 1, "quux", "bar"),
(path, 1, None, "foo"),
]

assert memoread_extra(path, 1, extra="bar") == "different"
assert calls == [
(path, 1, None, "foo"),
(path, 1, "quux", "bar"),
(path, 1, None, "foo"),
]
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ addopts = --cov=fscacher --no-cov-on-fail
filterwarnings =
error
ignore:The distutils package is deprecated:DeprecationWarning:joblib
ignore:`formatargspec` is deprecated:DeprecationWarning:joblib
norecursedirs = test/data

[coverage:run]
Expand Down