Mercurial > p > roundup > code
changeset 8593:bd97eaffe900
refactor(ruff): cleanup ruff issues and optimize some code.
In each method that uses self.X more than once, assign:
a = self.db.arg # value is the database specific placeholder for the
# parameterized query.
n = self.name # value is 'session' or 'otk'
and use throughout the method. This may also be a minor performance win.
Ruff reports:
error[S608]: Possible SQL injection vector through string-based
query construction
however every use of string based query injection substitutes ``n`` or
``a`` (or one reference to their safe.X forms) which are safe
parameters.
I have documented the safety of these values at the top of the class
outside of the docstring. I could '# nosec: S608' the lines, but it
would be better if I could declare 'n' and 'a' safe so future changes
that are unsafe get flagged. But....
Ruff also recommended some spacing changes and replacing if statement
with if expression.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Sat, 25 Apr 2026 18:03:04 -0400 |
| parents | 363a6bb5a6ae |
| children | be128eb0a4e1 |
| files | roundup/backends/sessions_rdbms.py |
| diffstat | 1 files changed, 31 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/roundup/backends/sessions_rdbms.py Tue Apr 21 12:55:19 2026 -0400 +++ b/roundup/backends/sessions_rdbms.py Sat Apr 25 18:03:04 2026 -0400 @@ -11,16 +11,31 @@ from roundup.anypy.html import html_escape as escape from roundup.backends.sessions_common import SessionCommon + def safe_eval(s): """Restricted eval to eval a repr of a dict of constants. """ return ast.literal_eval(s) + class BasicDatabase(SessionCommon): ''' Provide a nice encapsulation of an RDBMS table. Keys are id strings, values are automatically marshalled data. ''' + """ In methods the variables ``n`` and ``a`` should be used + only for the values of self.name and self.db.arg + respectively. Only these values should be interpolated + into a sql string as they are safe. + + self.name is ``otk`` or ``session`` for the otk or + session databases. + + self.db.arg is ``%s`` or ``?`` and is the placeholder for + parameterized queries in mysql/postgresql or sqlite + respectively. + """ + name = None def __init__(self, db): @@ -46,7 +61,7 @@ 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"' % (n, escape(infoid))) values = safe_eval(res[0]) return values.get(value, None) @@ -56,7 +71,7 @@ (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"' % (n, escape(infoid))) return safe_eval(res[0]) def set(self, infoid, **newvalues): @@ -73,11 +88,9 @@ (n, n, n, a), (infoid,)) res = c.fetchone() + values = safe_eval(res[0]) if res else {} + timestamp = time.time() - if res: - values = safe_eval(res[0]) - else: - values = {} if '__timestamp' in newvalues: try: @@ -86,7 +99,7 @@ except ValueError: if res: # keep the original timestamp - del(newvalues['__timestamp']) + del newvalues['__timestamp'] else: # here timestamp is the new timestamp newvalues['__timestamp'] = timestamp @@ -108,25 +121,29 @@ return [res[0] for res in c.fetchall()] def destroy(self, infoid): + n = self.name self.cursor.execute('delete from %ss where %s_key=%s' % - (self.name, self.name, self.db.arg), (infoid,)) + (n, n, self.db.arg), (infoid,)) def updateTimestamp(self, infoid): """ don't update every hit - once a minute should be OK """ + n = self.name + a = self.db.arg 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)) + (n, n, a, n, a, n, a), + (now, infoid, now - 60)) def clean(self): ''' Remove session records that haven't been used for a week. ''' + n = self.name + a = self.db.arg now = time.time() - week = 60*60*24*7 + 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, )) + (n, n, a), (old, )) def commit(self): self.log_info('commit %s' % self.name) @@ -138,7 +155,7 @@ in seconds. Default lifetime is 0. """ now = time.time() - week = 60*60*24*7 + week = 60 * 60 * 24 * 7 return now - week + item_lifetime def close(self):
