diff roundup/backends/sessions_rdbms.py @ 2082:c091cacdc505

Finished implementation of session and one-time-key stores for RDBMS backends. Refactored the API of sessions and their interaction with the backend database a fair bit too. Added some session tests. Nothing testing ageing yet, 'cos that's a pain inna ass to test :) Note: metakit backend still uses the *dbm implementation. It might want to implement its own session store some day, as it'll be faster than the *dbm one.
author Richard Jones <richard@users.sourceforge.net>
date Thu, 18 Mar 2004 01:58:46 +0000
parents
children 12cd4fa91eb7
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/roundup/backends/sessions_rdbms.py	Thu Mar 18 01:58:46 2004 +0000
@@ -0,0 +1,90 @@
+#$Id: sessions_rdbms.py,v 1.1 2004-03-18 01:58:45 richard Exp $
+"""This module defines a very basic store that's used by the CGI interface
+to store session and one-time-key information.
+
+Yes, it's called "sessions" - because originally it only defined a session
+class. It's now also used for One Time Key handling too.
+"""
+__docformat__ = 'restructuredtext'
+
+import os, time
+
+class BasicDatabase:
+    ''' Provide a nice encapsulation of an RDBMS table.
+
+        Keys are id strings, values are automatically marshalled data.
+    '''
+    def __init__(self, db):
+        self.db = db
+        self.cursor = self.db.cursor
+
+    def clear(self):
+        self.cursor.execute('delete from %ss'%self.name)
+
+    _marker = []
+    def get(self, infoid, value, default=_marker):
+        n = self.name
+        self.cursor.execute('select %s_value from %ss where %s_key=%s'%(n,
+            n, n, self.db.arg), (infoid,))
+        res = self.cursor.fetchone()
+        if not res:
+            if default != self._marker:
+                return default
+            raise KeyError, 'No such %s "%s"'%(self.name, infoid)
+        values = eval(res[0])
+        return values.get(value, None)
+
+    def getall(self, infoid):
+        n = self.name
+        self.cursor.execute('select %s_value from %ss where %s_key=%s'%(n,
+            n, n, self.db.arg), (infoid,))
+        res = self.cursor.fetchone()
+        if not res:
+            raise KeyError, 'No such %s "%s"'%(self.name, infoid)
+        return eval(res[0])
+
+    def set(self, infoid, **newvalues):
+        c = self.cursor
+        n = self.name
+        a = self.db.arg
+        c.execute('select %s_value from %ss where %s_key=%s'%(n, n, n, a),
+            (infoid,))
+        res = c.fetchone()
+        if res:
+            values = eval(res[0])
+        else:
+            values = {}
+        values.update(newvalues)
+
+        if res:
+            sql = 'update %ss set %s_value=%s where %s_key=%s'%(n, n,
+                a, n, a)
+            args = (repr(values), infoid)
+        else:
+            sql = 'insert into %ss (%s_key, %s_time, %s_value) '\
+                'values (%s, %s, %s)'%(n, n, n, n, a, a, a)
+            args = (infoid, time.time(), repr(values))
+        c.execute(sql, args)
+
+    def destroy(self, infoid):
+        self.cursor.execute('delete from %ss where %s_key=%s'%(self.name,
+            self.name, self.db.arg), (infoid,))
+
+    def updateTimestamp(self, infoid):
+        self.cursor.execute('update %ss set %s_time=%s where %s_key=%s'%(
+            self.name, self.name, self.db.arg, self.name, self.db.arg),
+            (time.time(), infoid))
+
+    def clean(self, now):
+        """Age sessions, remove when they haven't been used for a week.
+        """
+        old = now - 60*60*24*7
+        self.cursor.execute('delete from %ss where %s_time < %s'%(self.name,
+            self.name, self.db.arg), (old, ))
+
+class Sessions(BasicDatabase):
+    name = 'session'
+
+class OneTimeKeys(BasicDatabase):
+    name = 'otk'
+

Roundup Issue Tracker: http://roundup-tracker.org/