def test_double_caching(): '''Test that `cache` detects and prevents double-caching of functions.''' f = cache()(counting_func) g = cache()(f) assert f is g
def test_signature_preservation(): '''Test that a function's signature is preserved after decorating.''' f = cache()(counting_func) assert f() == f() == f(1, 2) == f(a=1, b=2) cute_testing.assert_same_signature(f, counting_func) def my_func(qq, zz=1, yy=2, *args): pass my_func_cached = cache(max_size=7)(my_func) cute_testing.assert_same_signature(my_func, my_func_cached) def my_other_func(**kwargs): pass my_func_cached = cache()(my_func) cute_testing.assert_same_signature(my_func, my_func_cached)
def test_unhashable_arguments(): """Test `cache` works with unhashable arguments.""" f = cache()(counting_func) assert f(set((1, 2))) == f(set((1, 2))) assert f(7, set((1, 2))) != f(8, set((1, 2))) assert f("boo") != f(meow="frrr") assert f(meow={1: [1, 2], 2: frozenset([3, "b"])}) == f(1, meow={1: [1, 2], 2: frozenset([3, "b"])})
def test_basic(): '''Test basic workings of `cache`.''' f = cache()(counting_func) assert f() == f() == f(1, 2) == f(a=1, b=2) assert f() != f('boo') assert f('boo') == f('boo') == f(a='boo') assert f('boo') != f(meow='frrr') assert f(meow='frrr') == f(1, meow='frrr') == f(a=1, meow='frrr')
def test_api(): '''Test the API of cached functions.''' f = cache()(counting_func) g = cache(max_size=3)(counting_func) for cached_function in (f, g): assert not hasattr(cached_function, 'cache') cute_testing.assert_polite_wrapper(cached_function, counting_func) result_1 = cached_function(1) assert cached_function(1) == result_1 == cached_function(1) cached_function.cache_clear() result_2 = cached_function(1) assert cached_function(1) == result_2 == cached_function(1) assert result_1 != result_2 == cached_function(1) != result_1 # Asserting we're not using `dict.clear` or something: assert cached_function.cache_clear.__name__ == 'cache_clear'
def test_unhashable_arguments(): '''Test `cache` works with unhashable arguments.''' f = cache()(counting_func) assert f(set((1, 2))) == f(set((1, 2))) assert f(7, set((1, 2))) != f(8, set((1, 2))) assert f('boo') != f(meow='frrr') assert f(meow={1: [1, 2], 2: frozenset([3, 'b'])}) == \ f(1, meow={1: [1, 2], 2: frozenset([3, 'b'])})
def test_api(): """Test the API of cached functions.""" f = cache()(counting_func) g = cache(max_size=3)(counting_func) for cached_function in (f, g): assert not hasattr(cached_function, "cache") cute_testing.assert_polite_wrapper(cached_function, counting_func) result_1 = cached_function(1) assert cached_function(1) == result_1 == cached_function(1) cached_function.cache_clear() result_2 = cached_function(1) assert cached_function(1) == result_2 == cached_function(1) assert result_1 != result_2 == cached_function(1) != result_1 # Asserting we're not using `dict.clear` or something: assert cached_function.cache_clear.__name__ == "cache_clear"
def test_basic(): """Test basic workings of `cache`.""" f = cache()(counting_func) assert f() == f() == f(1, 2) == f(a=1, b=2) assert f() != f("boo") assert f("boo") == f("boo") == f(a="boo") assert f("boo") != f(meow="frrr") assert f(meow="frrr") == f(1, meow="frrr") == f(a=1, meow="frrr")
def test_unhashable_arguments(): '''Test `cache` works with unhashable arguments.''' f = cache()(counting_func) x1 = set((1, 2)) x2 = set((1, 2)) assert f(x1) == f(x2) assert f(7, x1) != f(8, x2) assert f('boo') != f(meow='frrr') assert f(meow={1: [1, 2], 2: frozenset([3, 'b'])}) == \ f(1, meow={1: [1, 2], 2: frozenset([3, 'b'])})
def test_lru(): """Test the least-recently-used algorithm for forgetting cached results.""" f = cache(max_size=3)(counting_func) r0, r1, r2 = f(0), f(1), f(2) assert f(0) == f(0) == r0 == f(0) assert f(1) == f(1) == r1 == f(1) assert f(2) == f(2) == r2 == f(2) r3 = f(3) assert f(0) != r0 # Now we recalculated `f(0)` so we forgot `f(1)` assert f(2) == f(2) == r2 == f(2) assert f(3) == f(3) == r3 == f(3) new_r1 = f(1) # Requesting these: f(3) f(1) # So `f(2)` will be the least-recently-used. r4 = f(4) # Now `f(2)` has been thrown out. new_r2 = f(2) # And now `f(3)` is thrown out assert f(2) != r2 assert f(1) == new_r1 == f(1) assert f(4) == r4 == f(4) assert f(2) == new_r2 == f(2) # Now `f(1)` is the least-recently-used. r5 = f(5) # Now `f(1)` has been thrown out. assert f(4) == r4 == f(4) assert f(5) == r5 == f(5) assert f(1) != new_r1
def test_lru(): '''Test the least-recently-used algorithm for forgetting cached results.''' f = cache(max_size=3)(counting_func) r0, r1, r2 = f(0), f(1), f(2) assert f(0) == f(0) == r0 == f(0) assert f(1) == f(1) == r1 == f(1) assert f(2) == f(2) == r2 == f(2) r3 = f(3) assert f(0) != r0 # Now we recalculated `f(0)` so we forgot `f(1)` assert f(2) == f(2) == r2 == f(2) assert f(3) == f(3) == r3 == f(3) new_r1 = f(1) # Requesting these: f(3) f(1) # So `f(2)` will be the least-recently-used. r4 = f(4) # Now `f(2)` has been thrown out. new_r2 = f(2) # And now `f(3)` is thrown out assert f(2) != r2 assert f(1) == new_r1 == f(1) assert f(4) == r4 == f(4) assert f(2) == new_r2 == f(2) # Now `f(1)` is the least-recently-used. r5 = f(5) # Now `f(1)` has been thrown out. assert f(4) == r4 == f(4) assert f(5) == r5 == f(5) assert f(1) != new_r1
def test_weakref(): '''Test that `cache` weakrefs weakreffable arguments.''' f = cache()(counting_func) class A(object): pass a = A() result = f(a) assert result == f(a) == f(a) == f(a) a_ref = weakref.ref(a) del a gc.collect() assert a_ref() is None a = A() result = f(meow=a) assert result == f(meow=a) == f(meow=a) == f(meow=a) a_ref = weakref.ref(a) del a gc.collect() assert a_ref() is None
from garlicsim.general_misc import caching from garlicsim_wx.general_misc import wx_tools from garlicsim_wx.general_misc.flag_raiser import FlagRaiser import garlicsim import garlicsim_wx.misc.colors from garlicsim_wx.widgets import WorkspaceWidget from . import images as __images_package images_package = __images_package.__name__ connector_length = 10 # length of connecting line between elements my_color_replaced_bitmap = \ caching.cache(max_size=80)(wx_tools.color_replaced_bitmap) class TreeBrowser(ScrolledPanel, WorkspaceWidget): '''Widget for browsing a `garlicsim.data_structures.Tree`.''' def __init__(self, frame): # todo: on mouse drag should pause like seek bar does ScrolledPanel.__init__(self, frame, size=(100, 100), style=wx.SUNKEN_BORDER) WorkspaceWidget.__init__(self, frame) self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self.SetBackgroundColour(wx_tools.get_background_color())
from garlicsim_wx.general_misc import wx_tools from garlicsim_wx.general_misc.flag_raiser import FlagRaiser import garlicsim import garlicsim_wx.misc.colors from garlicsim_wx.widgets import WorkspaceWidget from . import images as __images_package images_package = __images_package.__name__ connector_length = 10 # length of connecting line between elements my_color_replaced_bitmap = \ caching.cache(max_size=80)(wx_tools.color_replaced_bitmap) class TreeBrowser(ScrolledPanel, WorkspaceWidget): '''Widget for browsing a `garlicsim.data_structures.Tree`.''' def __init__(self, frame): # todo: on mouse drag should pause like seek bar does ScrolledPanel.__init__(self, frame, size=(100, 100), style=wx.SUNKEN_BORDER) WorkspaceWidget.__init__(self, frame) self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self.SetBackgroundColour(wx_tools.get_background_color()) self.SetupScrolling() #self.SetScrollRate(20,20)