Skip to content
This repository has been archived by the owner on Mar 22, 2018. It is now read-only.

Commit

Permalink
implementing some basic caching.
Browse files Browse the repository at this point in the history
relates to #247.
  • Loading branch information
mfrasca committed Jan 4, 2016
1 parent cdd0a46 commit 612baed
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 5 deletions.
64 changes: 60 additions & 4 deletions bauble/test/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2005,2006,2007,2008,2009 Brett Adams <brett@belizebotanic.org>
# Copyright (c) 2012-2015 Mario Frasca <mario@anche.no>
# Copyright (c) 2012-2016 Mario Frasca <mario@anche.no>
#
# This file is part of bauble.classic.
#
Expand All @@ -19,10 +19,11 @@
# along with bauble.classic. If not, see <http://www.gnu.org/licenses/>.

import bauble.utils as utils
from bauble.test import BaubleTestCase
from unittest import TestCase


class Utils(TestCase):

class Utils(BaubleTestCase):

def test_topological_sort_total(self):
self.assertEqual(utils.topological_sort([1,2,3], [(2,1), (3,2)]), [3, 2, 1])

Expand All @@ -31,3 +32,58 @@ def test_topological_sort_partial(self):

def test_topological_sort_loop(self):
self.assertEqual(utils.topological_sort([1,2], [(2,1), (1,2)]), None)


class CacheTest(TestCase):
def test_create_store_retrieve(self):
from bauble.utils import Cache
from functools import partial
invoked = []

def getter(x):
invoked.append(x)
return x

cache = Cache(2)
v = cache.get(1, partial(getter, 1))
self.assertEquals(v, 1)
self.assertEquals(invoked, [1])
v = cache.get(1, partial(getter, 1))
self.assertEquals(v, 1)
self.assertEquals(invoked, [1])

def test_respect_size(self):
from bauble.utils import Cache
from functools import partial
invoked = []

def getter(x):
invoked.append(x)
return x

cache = Cache(2)
cache.get(1, partial(getter, 1))
cache.get(2, partial(getter, 2))
cache.get(3, partial(getter, 3))
cache.get(4, partial(getter, 4))
self.assertEquals(invoked, [1, 2, 3, 4])
self.assertEquals(sorted(cache.storage.keys()), [3, 4])

def test_respect_timing(self):
from bauble.utils import Cache
from functools import partial
invoked = []

def getter(x):
invoked.append(x)
return x

cache = Cache(2)
cache.get(1, partial(getter, 1))
cache.get(2, partial(getter, 2))
cache.get(1, partial(getter, 1))
cache.get(3, partial(getter, 3))
cache.get(1, partial(getter, 1))
cache.get(4, partial(getter, 4))
self.assertEquals(invoked, [1, 2, 3, 4])
self.assertEquals(sorted(cache.storage.keys()), [1, 4])
35 changes: 34 additions & 1 deletion bauble/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2005,2006,2007,2008,2009 Brett Adams <brett@belizebotanic.org>
# Copyright (c) 2015 Mario Frasca <mario@anche.no>
# Copyright (c) 2015-2016 Mario Frasca <mario@anche.no>
#
# This file is part of bauble.classic.
#
Expand Down Expand Up @@ -125,6 +125,39 @@ def read_local_url(self):
self.loader.write(piece)


class Cache:
'''a simple class for caching images
you instantiate a size 10 cache like this:
>>> cache = ImageCache(10)
if `getter` is a function that returns a picture, you don't immediately
invoke it, you use the cache like this:
>>> image = cache.get(name, getter)
internally, the cache is stored in a dictionary, the key is the name of
the image, the value is a pair with first the timestamp of the last usage
of that key and second the value.
'''

def __init__(self, size):
self.size = size
self.storage = {}

def get(self, key, getter):
if key in self.storage:
value = self.storage[key][1]
else:
if len(self.storage) == self.size:
# remove the oldest entry
k = min(zip(self.storage.values(), self.storage.keys()))[1]
del self.storage[k]
value = getter()
import time
self.storage[key] = time.time(), value
return value


def find_dependent_tables(table, metadata=None):
'''
Return an iterator with all tables that depend on table. The
Expand Down

0 comments on commit 612baed

Please sign in to comment.