Skip to content

Commit

Permalink
Merge PR #37 Read-only mode
Browse files Browse the repository at this point in the history
  • Loading branch information
tmylk committed Oct 5, 2015
2 parents 043c6b9 + 03c6055 commit 41d337e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
13 changes: 12 additions & 1 deletion sqlitedict.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ def decode(obj):


class SqliteDict(DictClass):
VALID_FLAGS = ['c', 'r', 'w', 'n']

def __init__(self, filename=None, tablename='unnamed', flag='c',
autocommit=False, journal_mode="DELETE"):
"""
Expand All @@ -123,16 +125,22 @@ def __init__(self, filename=None, tablename='unnamed', flag='c',
Set `journal_mode` to 'OFF' if you're experiencing sqlite I/O problems
or if you need performance and don't care about crash-consistency.
The `flag` parameter:
The `flag` parameter. Exactly one of:
'c': default mode, open for read/write, creating the db/table if necessary.
'w': open for r/w, but drop `tablename` contents first (start with empty table)
'r': open as read-only
'n': create a new database (erasing any existing tables, not just `tablename`!).
"""
self.in_temp = filename is None
if self.in_temp:
randpart = hex(random.randint(0, 0xffffff))[2:]
filename = os.path.join(tempfile.gettempdir(), 'sqldict' + randpart)

if flag not in SqliteDict.VALID_FLAGS:
raise RuntimeError("Unrecognized flag: %s" % flag)
self.flag = flag

if flag == 'n':
if os.path.exists(filename):
os.remove(filename)
Expand Down Expand Up @@ -218,6 +226,9 @@ def __getitem__(self, key):
return decode(item[0])

def __setitem__(self, key, value):
if self.flag == 'r':
raise RuntimeError('Refusing to write to read-only SqliteDict')

ADD_ITEM = 'REPLACE INTO %s (key, value) VALUES (?,?)' % self.tablename
self.conn.execute(ADD_ITEM, (key, encode(value)))

Expand Down
24 changes: 24 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,30 @@ def test_overwrite_using_flag_n(self):
next_db = sqlitedict.SqliteDict(filename=fname, tablename='sometable', flag='n')
self.assertNotIn('key', next_db.keys())

def test_unrecognized_flag(self):

def build_with_bad_flag():
fname = norm_file('tests/db/sqlitedict-override-test.sqlite')
orig_db = sqlitedict.SqliteDict(filename=fname, flag = 'FOO')

with self.assertRaises(RuntimeError):
build_with_bad_flag()

def test_readonly(self):
fname = norm_file('tests/db/sqlitedict-override-test.sqlite')
orig_db = sqlitedict.SqliteDict(filename=fname)
orig_db['key'] = 'value'
orig_db.commit()
orig_db.close()

readonly_db = sqlitedict.SqliteDict(filename=fname, flag = 'r')
self.assertTrue(readonly_db['key'] == 'value')

def attempt_write():
readonly_db['key'] = ['new_value']

with self.assertRaises(RuntimeError):
attempt_write()

def test_overwrite_using_flag_w(self):
"""Re-opening of a database with flag='w' destroys only the target table."""
Expand Down

0 comments on commit 41d337e

Please sign in to comment.