tkem/cachetools

documentation example doesn't work

Closed this issue · 1 comments

The cachetools documentation has an example of creating a custom function to allow dictionary arguments: https://cachetools.readthedocs.io/en/stable/#module-cachetools.keys. However, that example doesn't work for me:

====

# cat dict_test.py
from cachetools import *
from cachetools.keys import hashkey

def envkey(*args, env={}, **kwargs):
    key = hashkey(*args, **kwargs)
    key += tuple(sorted(env.items()))
    return key

@cached(LRUCache(maxsize=128), key=envkey)
def foo(x, y, z, env={}):
    pass

x = {}
x['abc'] = 1
x['def'] = 'def'
foo(1, 2, 3, x)
# python3 ./dict_test.py
Traceback (most recent call last):
  File "./dict_test.py", line 20, in <module>
    foo(1, 2, 3, x)
  File "/usr/lib/python3.8/site-packages/cachetools/decorators.py", line 19, in wrapper
    return cache[k]
  File "/usr/lib/python3.8/site-packages/cachetools/lru.py", line 14, in __getitem__
    value = cache_getitem(self, key)
  File "/usr/lib/python3.8/site-packages/cachetools/cache.py", line 39, in __getitem__
    return self.__data[key]
  File "/usr/lib/python3.8/site-packages/cachetools/keys.py", line 19, in __hash__
    self.__hashvalue = hashvalue = hash(self)
TypeError: unhashable type: 'dict'

====

I'm on Fedora 32 with python 3.8.2 and cachetools 4.1.0

tkem commented

The way envkey is implemented requires env to be a named argument:

foo(1, 2, 3, env=x)

I think extending the example with an actual call of foo() might help somewhat, e.g.

@cached(LRUCache(maxsize=128), key=envkey)
def foo(x, y, z, env={}):
    pass

foo(1, 2, 3, env=dict(a=4, b=5))