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

Don't use hash_funcs to compute an @st.cache function's cache_key #2331

Merged
merged 3 commits into from
Nov 10, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/streamlit/caching.py
Expand Up @@ -487,7 +487,7 @@ def cache(
update_hash(
(func.__module__, func.__qualname__, func),
hasher=func_hasher,
hash_funcs=hash_funcs,
hash_funcs=None, # hash_funcs are only used for value_key, below
hash_reason=HashReason.CACHING_FUNC_BODY,
hash_source=func,
)
Expand Down
38 changes: 35 additions & 3 deletions lib/tests/streamlit/caching_test.py
Expand Up @@ -13,15 +13,13 @@
# limitations under the License.

"""st.caching unit tests."""
from unittest.mock import patch
from unittest.mock import patch, Mock
import threading
import unittest
import pytest
import types

from streamlit import caching
from streamlit import hashing
from streamlit.hashing import UserHashError
from streamlit.elements import exception_proto
from streamlit.proto.Exception_pb2 import Exception as ExceptionProto
from tests import testutil
Expand Down Expand Up @@ -347,6 +345,40 @@ def bar(x):
self.assertEqual([0, 1, 2, 0, 1, 2], foo_vals)
self.assertEqual([0, 1, 2, 0, 1, 2], bar_vals)

def test_unique_function_caches(self):
"""Each function should have its own cache, even if it has an
identical body and arguments to another cached function.
"""

@st.cache
def foo():
return []

@st.cache
def bar():
return []

id_foo = id(foo())
id_bar = id(bar())
self.assertNotEqual(id_foo, id_bar)

def test_function_cache_does_not_use_hashfuncs(self):
"""Hash funcs should only be used on arguments to a function,
and not when computing the key for a function's unique MemCache.
"""

mock_hash_func = Mock(return_value=None)

@st.cache(hash_funcs={str: mock_hash_func})
def foo(string_arg):
return []

# If our hash_func is called multiple times, it's probably because
# it's being used to compute the function's cache_key (as opposed to
# the value_key). It should only be used to compute the value_key!
foo("ahoy")
mock_hash_func.assert_called_once_with("ahoy")


# Temporarily turn off these tests since there's no Cache object in __init__
# right now.
Expand Down