Property Attributes in Memcache

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
"""
    Property attributes in memcached

    :copyright: (c) by Ori Livneh
    :license: Public Domain
"""
from django.core.cache import cache


def memcached_property(key_function, timeout=cache.default_timeout, doc=None):
    """
    Creates a property attribute that is stored in memcached. `key_function`
    should be a callable that accepts an object instance and returns a string
    representing a memcached key. Example::

        class Book(models.Model):
            isbn = models.CharField(max_length=13, primary_key=True)
            last_read = memcached_property(
                lambda self: "book:%d:last_read" % self.isbn)

    :param key_function: a callable that accepts an object instance and returns
                         a string representing a memcached key.
    :param timeout: used by setter to specify expiry; defaults to Django
                    default.
    :param doc: If given, doc will be the docstring of the property attribute.
    """
    if doc is None:
        doc = memcached_property.__doc__

    def fget(self):
        """ Getter function """
        key = key_function(self)
        return cache.get(key)

    def fset(self, value):
        """ Setter function """
        key = key_function(self)
        cache.set(key, value, timeout)

    def fdel(self):
        """ Deleter function """
        key = key_function(self)
        cache.delete(key)

    return property(fget, fset, fdel, doc)


if __name__ == '__main__':
    # when invoked as a script, run unit test
    import unittest
    from datetime import datetime, timedelta

    class Book(object):
        """ Dummy class for testing memcached_property """
        def __init__(self, isbn):
            self.isbn = isbn
        last_read = memcached_property(lambda b: "book:%d:last_read" % b.isbn)

    class MemcachedPropertyTestCase(unittest.TestCase):
        """ Test case for memcached_property descriptor """
        def setUp(self):
            """ Delete leftover keys in memcache """
            cache.delete("book:12:last_read")
        tearDown = setUp

        def test_descriptor_access(self):
            """
            Tests getter, setter and deleter functions for memcached properties
            """
            book = Book(isbn=12)

            # test init
            self.assertIsNone(book.last_read)

            # test setter
            date = datetime.now()
            book.last_read = date
            self.assertEqual(book.last_read, date)
            self.assertEqual(cache.get("book:12:last_read"), date)

            # test that the getter function really does go to memcached by
            # changing the value in memcached directly.
            different_date = date - timedelta(hours=1)
            self.assertNotEqual(date, different_date)
            cache.set("book:12:last_read", different_date)
            self.assertEqual(book.last_read, different_date)

            # test the deleter function
            del book.last_read
            self.assertIsNone(book.last_read)
            # cache.add should return true if the key did not exist, thereby
            # conforming deletion.
            self.assertTrue(cache.add("book:12:last_read", 123))

    unittest.main()

More like this

  1. Cached model property decorator (like @property) by homunq 2 years, 4 months ago
  2. Tastypie MongoDB Resource by fatiherikli 1 year, 6 months ago
  3. A simple client to get some info (NOT values...) from memcached by pterk 4 years, 10 months ago
  4. i18n base model for translatable content by foxbunny 5 years, 9 months ago
  5. JSON instead of pickle for memcached by diverman 2 years, 3 months ago

Comments

(Forgotten your password?)