diff --git a/lena/flow/cache.py b/lena/flow/cache.py index 94c10c7..3a79845 100644 --- a/lena/flow/cache.py +++ b/lena/flow/cache.py @@ -47,10 +47,16 @@ class Cache(object): Never unpickle data from an untrusted source. """ - def __init__(self, filename, method="cPickle", protocol=2): + def __init__(self, filename, recompute=False, + method="cPickle", protocol=2): """*filename* is the name of file where to store the cache. You can give it *.pkl* extension. + If *recompute* is ``True``, + an existing cache will always be overwritten. + This option is typically used if one wants to define + cache behaviour from the command line. + *method* can be *pickle* or *cPickle* (faster pickle). For Python 3 they are same. @@ -77,11 +83,18 @@ def __init__(self, filename, method="cPickle", protocol=2): self._filename = filename self.protocol = protocol + self._recompute = recompute # used by meta elements self.is_cache = True def cache_exists(self): - """Return ``True`` if file with cache exists and is readable.""" + """Return ``True`` if file with cache exists and is readable. + + If *recompute* was ``True`` during the initialization, + pretend that cache does not exist (return ``False``). + """ + if self._recompute: + return False return os.access(self._filename, os.R_OK) def drop_cache(self): @@ -138,7 +151,8 @@ def alter_sequence(seq): break if last_cache_filled_ind is not None: return lena.core.Source( - lena.core.SourceEl(seq[last_cache_filled_ind], call="_load_flow"), + lena.core.SourceEl(seq[last_cache_filled_ind], + call="_load_flow"), *seq[last_cache_filled_ind+1:] ) else: diff --git a/tests/flow/test_cache.py b/tests/flow/test_cache.py index 03a7a61..d793301 100644 --- a/tests/flow/test_cache.py +++ b/tests/flow/test_cache.py @@ -5,20 +5,29 @@ from lena.core import Sequence, Source, LenaTypeError, LenaValueError from tests.example_sequences import ( ASCIILowercase, ASCIIUppercase, ascii_lowercase, ascii_uppercase, - lowercase_cached_filename, lowercase_cached_seq, id_ + lowercase_cached_filename, lowercase_cached_seq, id_, ) from lena.flow.cache import Cache from lena.flow.iterators import Slice from tests.shortcuts import cnt1, cnt1c -def test_cache(): - s = Source(ascii_lowercase, lowercase_cached_seq) - assert "".join(s()) == "abcdefghijklmnopqrstuvwxyz" - # cache is actually used - s = Source(ascii_uppercase, lowercase_cached_seq) - assert "".join(s()) == "abcdefghijklmnopqrstuvwxyz" - lowercase_cached_seq[0].drop_cache() +def test_cache(tmpdir): + low_letters = "abcdefghijklmnopqrstuvwxyz" + os.chdir(tmpdir) + + # empty cache makes no problems + s1 = Source(ascii_lowercase, lowercase_cached_seq) + assert "".join(s1()) == low_letters + + # filled cache is actually used + s2 = Source(ascii_uppercase, lowercase_cached_seq) + assert "".join(s2()) == low_letters + + # recompute works + c3 = Cache(lowercase_cached_filename, recompute=True) + s3 = Source(ascii_uppercase, c3) + assert "".join(s3()) == "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # it's a shame, but I had two tests in different files @@ -64,13 +73,10 @@ def test_cache_2(tmp_path): assert res4 == [(1, {'1': 1}), (2, {'2': 2})] -def test_alter_sequence(): +def test_alter_sequence(tmpdir): + os.chdir(tmpdir) cached_to_source = Cache.alter_sequence - # remove cache - try: - os.remove(lowercase_cached_filename) - except Exception: - pass + lowercase_cache_el = Cache(lowercase_cached_filename) el = lowercase_cache_el s0 = Sequence(el) @@ -93,5 +99,3 @@ def test_alter_sequence(): # this fails for nested Sequences. To be done. assert cached_to_source(s) != s assert isinstance(cached_to_source(s), Source) - - lowercase_cache_el.drop_cache()