tkem/cachetools

For 5.0 - add in cachedproperty?

Closed this issue · 6 comments

I might be able to help contribute here. Didn't know if this was already planned: Similar: https://github.com/python/cpython/blob/3.10/Lib/functools.py#L934

tkem commented

AFAIK, @cached_property is just a method executed once and its result then "cached" indefinitely. I don't see how a cachetools implementation could improve on that?

The decorator for a property is different.

Take for instance:

import time

from cachetools import TTLCache, cached, cachedmethod


cache = TTLCache(maxsize=3, ttl=5)


class Upstream(dict):
    #@cache(cache=cache) # Nope
    #@cachedmethod(cache=cache) # Nope
    @property
    #@cachedmethod(cache=cache) # Nope
    #@cache(cache=cache) # Nope
    def frequently_accessed_thing(self) -> int:
        return time.time_ns()


upstream = Upstream()

print(upstream.frequently_accessed_thing)
print(upstream.frequently_accessed_thing)

The decorators don't properly account for what's needed to properly represent a property as this does:

import time
from functools import cached_property


class Upstream(dict):
    @cached_property
    def frequently_accessed_thing(self) -> int:
        return time.time_ns()


upstream = Upstream()

print(upstream.frequently_accessed_thing)
print(upstream.frequently_accessed_thing)

The only way to properly integrate an LRU or TTL cache via a property is to use an inner function (or get really explicit)

import time
from cachetools import cached, TTLCache

cache = TTLCache(maxsize=100, ttl=60)


class Upstream(dict):
    @property
    def frequently_accessed_thing(self) -> int:
        @cached(cache=cache)
        def _frequently_accessed_thing():
            return time.time_ns()

        return _frequently_accessed_thing()


upstream = Upstream()

print(upstream.frequently_accessed_thing)
print(upstream.frequently_accessed_thing)

So cachetools could provide a cachedproperty decorator akin to functools.cached_property in order to help this work.

tkem commented

So what would be the actual benefit of this, compared too the standard library @cached_property decorator?
The only difference I can see is when using a TTLCache, you could specify a timeout after which the cached property value would be updated. However, that could also (and maybe easier) be achieved by adding a ttl option to the standard library @cached_property decorator.

Being able to work directly with an externally managed cache store is the goal. We are using cachetools to help deal with things that aren't provided by the standard lib.

OK. I read the docs and I'm sorry for spinning this up. Thanks @tkem - I have a decorator in place wrapping cached(...) in that is using a hashed key attribute for the function name.. works like a champ and easy to implement without patching this lib.

tkem commented

@whardier: Great to hear you got this solved! Would you mind posting your solution here (or providing a link if it's available elsewhere) for future reference?