Skip to content
This repository was archived by the owner on Apr 18, 2018. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions sqlite3dbm/dbm.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@
from __future__ import with_statement

import os
import time
import functools
import sqlite3

__all__ = [
Expand Down Expand Up @@ -179,6 +181,28 @@ class SqliteMapException(Exception):
# DBM interface
error = SqliteMapException

ATTEMPTS_COUNT = float("inf")

def lockwait(f):
@functools.wraps(f)
def _lockwait(*args, **kwargs):
attempt = ATTEMPTS_COUNT
r = None
while attempt >= 0:
attempt -= 1
try:
r = f(*args, **kwargs)
except sqlite3.OperationalError, e:
if e.message != "database is locked" or \
attempt == -1: # -1 is last attempt
raise
else:
time.sleep(0.01)
else:
break

return r
return _lockwait

class SqliteMap(object):
"""Dictionary interface backed by a SQLite DB.
Expand Down Expand Up @@ -221,6 +245,7 @@ def __init__(self, path, flag='r', mode=0666):
if flag == 'n':
self.clear()

@lockwait
def __setitem__(self, k, v):
"""x.__setitem__(k, v) <==> x[k] = v"""
if self.readonly:
Expand All @@ -229,6 +254,7 @@ def __setitem__(self, k, v):
self.conn.execute(_SET_QUERY, (k, v))
self.conn.commit()

@lockwait
def __getitem__(self, k):
"""x.__getitem__(k) <==> x[k]

Expand All @@ -247,6 +273,7 @@ def __getitem__(self, k):
raise KeyError(k)
return row[0]

@lockwait
def __delitem__(self, k):
"""x.__delitem__(k) <==> del x[k]"""
if self.readonly:
Expand All @@ -262,6 +289,7 @@ def __delitem__(self, k):
self.conn.execute(_DEL_QUERY, (k,))
self.conn.commit()

@lockwait
def __contains__(self, k):
"""D.__contains__(k) -> True if D has a key k, else False"""
try:
Expand All @@ -271,6 +299,7 @@ def __contains__(self, k):
else:
return True

@lockwait
def clear(self):
"""D.clear() -> None. Remove all items from D."""
if self.readonly:
Expand Down Expand Up @@ -359,6 +388,7 @@ def k_gen():
else:
yield arg

@lockwait
def lookup(keys):
"""Reuse the slightly weird logic to lookup values"""
# Do all the selects in a single transaction
Expand Down Expand Up @@ -406,6 +436,7 @@ def select(self, *args):
raise KeyError('One of the requested keys is missing!')
return vals

@lockwait
def update(self, *args, **kwargs):
"""D.update(E, **F) -> None. Update D from E and F: for k in E: D[k] = E[k]
(if E has keys else: for (k, v) in E: D[k] = v) then: for k in F: D[k] = F[k]
Expand Down