# Path: pymonet/utils.py
# def memoize(fn: Callable, key=eq) -> Callable:
#     """
#     Create a new function that, when invoked,
#     caches the result of calling fn for a given argument set and returns the result.
#     Subsequent calls to the memoized fn with the same argument set will not result in an additional call to fn;
#     instead, the cached result for that set of arguments will be returned.
# 
#     :param fn: function to invoke
#     :type fn: Function(A) -> B
#     :param key: function to decide if result should be taken from cache
#     :type key: Function(A, A) -> Boolean
#     :returns: new function invoking old one
#     :rtype: Function(A) -> B
#     """
#     cache: List[Any] = []
# 
#     def memoized_fn(argument):
#         cached_result = find(cache, lambda cacheItem: key(cacheItem[0], argument))
#         if cached_result is not None:
#             return cached_result[1]
#         fn_result = fn(argument)
#         cache.append((argument, fn_result))
# 
#         return fn_result
# 
#     return memoized_fn


from pymonet.utils import memoize


result = {'key': 'value'}


class MemoizeSpy:

    def fn(*args):
        return args

    def key(_, value, new_value):
        return value['compare_key'] == new_value['compare_key']


def test_utils_memoize_should_call_fn_once_when_args_are_equal(mocker):
    memoize_spy = MemoizeSpy()
    mocker.spy(memoize_spy, 'fn')


# Path: pymonet/utils.py
# def memoize(fn: Callable, key=eq) -> Callable:
#     """
#     Create a new function that, when invoked,
#     caches the result of calling fn for a given argument set and returns the result.
#     Subsequent calls to the memoized fn with the same argument set will not result in an additional call to fn;
#     instead, the cached result for that set of arguments will be returned.
# 
#     :param fn: function to invoke
#     :type fn: Function(A) -> B
#     :param key: function to decide if result should be taken from cache
#     :type key: Function(A, A) -> Boolean
#     :returns: new function invoking old one
#     :rtype: Function(A) -> B
#     """
#     cache: List[Any] = []
# 
#     def memoized_fn(argument):
#         cached_result = find(cache, lambda cacheItem: key(cacheItem[0], argument))
#         if cached_result is not None:
#             return cached_result[1]
#         fn_result = fn(argument)
#         cache.append((argument, fn_result))
# 
#         return fn_result
# 
#     return memoized_fn


# Path: tests/test_utlis_memoize.py
from pymonet.utils import memoize



result = {'key': 'value'}


class MemoizeSpy:

    def fn(*args):
        return args

    def key(_, value, new_value):
        return value['compare_key'] == new_value['compare_key']


def test_utils_memoize_should_call_fn_once_when_args_are_equal(mocker):
    memoize_spy = MemoizeSpy()
    mocker.spy(memoize_spy, 'fn')


    momoized_function = memoize(memoize_spy.fn)