tkem/cachetools

[Feature] Ignore caching /using cached values when a certain argument is passed to the method

Closed this issue · 1 comments

Hi.

First of all, thank you for the package. I recently started using this and found it very helpful.

I went through the documentation and missed a feature that was required for one of my projects. Please let me know if you already have such feature in the package which I missed somehow (or a different) or would be interested in supporting something like this.

Currently,

class CachedPEPs(object):

    def __init__(self, cachesize):
        self.cache = LRUCache(maxsize=cachesize)

    @cachedmethod(operator.attrgetter('cache'))
    def get(self, num):
        """Retrieve text of a Python Enhancement Proposal"""
        url = "http://www.python.org/dev/peps/pep-%04d/" % num
        with urllib.request.urlopen(url) as s:
            return s.read()

peps = CachedPEPs(cachesize=10)
print(peps.get(1))
print(peps.get(1))

would cache response returned for 1

The feature I wanted is that, whenever I call the method with a certain argument, say ignore_cached the cachedmethod should ignore the cached value and make the method call instead. This can be extended to another argument, say ignore_caching which will not cache the value. (And another ignore_cache which does not cache the return value and does not use a cached value)

Essentially,

the decorator definition will look something like this

cachedmethod(cache, key=hashkey, lock=None, ignore_cached_kwarg: str = "ignore_cached", ignore_caching_kwarg: str = "ignore_caching", ignore_cache_kwarg: str = "ignore_cache"):

Note: These argument names are just for representational purpose, can be more meaningful.

With this,

print(peps.get(1))
print(peps.get(1, ignore_cached=True))       # This should ignore the cached value and make the method call anyways
print(peps.get(1, ignore_caching=True))      # This should not cache the values once its returned.

I ended up writing my own decorator for my project which is adding some more if-else statements to the existing decorator definition. Do let me know if this is possible if I missed something in the docs. If not, also let me know if you would like this feature in the package.

Thank you again!

tkem commented

@shashankrnr32: Thanks for your interest! At this time, I don't want to add more features to the decorators. I think that if you have special needs, it is often easier to work with the cache classes directly than adding "yet another decorator feature", e.g.

class CachedPEPs(object):

    def __init__(self, cachesize):
        self.cache = LRUCache(maxsize=cachesize)

    @cachedmethod(operator.attrgetter('cache'))
    def get(self, num, ignore_cached=False):
        """Retrieve text of a Python Enhancement Proposal"""
        url = "http://www.python.org/dev/peps/pep-%04d/" % num
        if not ignore_cached:
            try:
                return self.cache[url]
            except KeyError:
                pass
        with urllib.request.urlopen(url) as s:
            pep = s.read()
        self.cache[url] = pep
        return pep

I've found this to be especially true with the @cachedmethod decorator. If I wrote cachetools today, I probably wouldn't even include it.