diff roundup/backends/sessions_rdbms.py @ 6823:fe0091279f50

Refactor session db logging and key generation for sessions/otks While I was working on the redis sessiondb stuff, I noticed that log_wanrning, get_logger ... was duplicated. Also there was code to generate a unique key for otks that was duplicated. Changes: creating new sessions_common.py and SessionsCommon class to provide methods: log_warning, log_info, log_debug, get_logger, getUniqueKey getUniqueKey method is closer to the method used to make session keys in client.py. sessions_common.py now report when random_.py chooses a weak random number generator. Removed same from rest.py. get_logger reconciles all logging under roundup.hyperdb.backends.<name of BasicDatabase class> some backends used to log to root logger. have BasicDatabase in other sessions_*.py modules inherit from SessionCommon. change logging to use log_* methods. In addition: remove unused imports reported by flake8 and other formatting changes modify actions.py, rest.py, templating.py to use getUniqueKey method. add tests for new methods test_redis_session.py swap out ModuleNotFoundError for ImportError to prevent crash in python2 when redis is not present. allow injection of username:password or just password into redis connection URL. set pytest_redis_pw envirnment variable to password or user:password when running test.
author John Rouillard <rouilj@ieee.org>
date Sun, 07 Aug 2022 01:51:11 -0400
parents 375d40a9e730
children ee17f62c8341
line wrap: on
line diff
--- a/roundup/backends/sessions_rdbms.py	Sun Aug 07 01:26:30 2022 -0400
+++ b/roundup/backends/sessions_rdbms.py	Sun Aug 07 01:51:11 2022 -0400
@@ -5,67 +5,70 @@
 class. It's now also used for One Time Key handling too.
 """
 __docformat__ = 'restructuredtext'
-import os, time, logging
+import time
 
 from roundup.anypy.html import html_escape as escape
+from roundup.backends.sessions_common import SessionCommon
 
-class BasicDatabase:
+
+class BasicDatabase(SessionCommon):
     ''' Provide a nice encapsulation of an RDBMS table.
 
         Keys are id strings, values are automatically marshalled data.
     '''
     name = None
+
     def __init__(self, db):
         self.db = db
         self.conn, self.cursor = self.db.sql_open_connection()
 
     def clear(self):
-        self.cursor.execute('delete from %ss'%self.name)
+        self.cursor.execute('delete from %ss' % self.name)
 
     def exists(self, infoid):
         n = self.name
-        self.cursor.execute('select count(*) from %ss where %s_key=%s'%(n,
-            n, self.db.arg), (infoid,))
+        self.cursor.execute('select count(*) from %ss where %s_key=%s' %
+                            (n, n, self.db.arg), (infoid,))
         return int(self.cursor.fetchone()[0])
 
     _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,))
+        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, escape(infoid)))
+            raise KeyError('No such %s "%s"' % (self.name, escape(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,))
+        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, escape (infoid)))
+            raise KeyError('No such %s "%s"' % (self.name, escape(infoid)))
         return eval(res[0])
 
     def set(self, infoid, **newvalues):
         """ Store all newvalues under key infoid with a timestamp in database.
 
-            If newvalues['__timestamp'] exists and is representable as a floating point number
-            (i.e. could be generated by time.time()), that value is used for the <name>_time
-            column in the database.
+            If newvalues['__timestamp'] exists and is representable as
+            a floating point number (i.e. could be generated by time.time()),
+            that value is used for the <name>_time column in the database.
         """
         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,))
+        c.execute('select %s_value from %ss where %s_key=%s' %
+                  (n, n, n, a), (infoid,))
         res = c.fetchone()
 
-        timestamp=time.time()
+        timestamp = time.time()
         if res:
             values = eval(res[0])
         else:
@@ -85,43 +88,43 @@
         values.update(newvalues)
         if res:
             sql = ('update %ss set %s_value=%s, %s_time=%s '
-                       'where %s_key=%s'%(n, n, a, n, a, n, a))
+                   'where %s_key=%s' % (n, n, a, n, a, n, a))
             args = (repr(values), timestamp, infoid)
         else:
             sql = 'insert into %ss (%s_key, %s_time, %s_value) '\
-                'values (%s, %s, %s)'%(n, n, n, n, a, a, a)
+                'values (%s, %s, %s)' % (n, n, n, n, a, a, a)
             args = (infoid, timestamp, repr(values))
         c.execute(sql, args)
 
     def list(self):
         c = self.cursor
         n = self.name
-        c.execute('select %s_key from %ss'%(n, n))
+        c.execute('select %s_key from %ss' % (n, n))
         return [res[0] for res in c.fetchall()]
 
     def destroy(self, infoid):
-        self.cursor.execute('delete from %ss where %s_key=%s'%(self.name,
-            self.name, self.db.arg), (infoid,))
+        self.cursor.execute('delete from %ss where %s_key=%s' %
+                            (self.name, self.name, self.db.arg), (infoid,))
 
     def updateTimestamp(self, infoid):
         """ don't update every hit - once a minute should be OK """
         now = time.time()
-        self.cursor.execute('''update %ss set %s_time=%s where %s_key=%s
-            and %s_time < %s'''%(self.name, self.name, self.db.arg,
-            self.name, self.db.arg, self.name, self.db.arg),
-            (now, infoid, now-60))
+        self.cursor.execute('''update %ss set %s_time=%s where %s_key=%s '''
+            '''and %s_time < %s''' %
+                            (self.name, self.name, self.db.arg, self.name,
+                             self.db.arg, self.name, self.db.arg),
+                            (now, infoid, now-60))
 
     def clean(self):
         ''' Remove session records that haven't been used for a week. '''
         now = time.time()
         week = 60*60*24*7
         old = now - week
-        self.cursor.execute('delete from %ss where %s_time < %s'%(self.name,
-            self.name, self.db.arg), (old, ))
+        self.cursor.execute('delete from %ss where %s_time < %s' %
+                            (self.name, self.name, self.db.arg), (old, ))
 
     def commit(self):
-        logger = logging.getLogger('roundup.hyperdb.backend')
-        logger.info('commit %s' % self.name)
+        self.log_info('commit %s' % self.name)
         self.conn.commit()
         self.cursor = self.conn.cursor()
 
@@ -136,9 +139,11 @@
     def close(self):
         self.conn.close()
 
+
 class Sessions(BasicDatabase):
     name = 'session'
 
+
 class OneTimeKeys(BasicDatabase):
     name = 'otk'
 

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