Skip to content
Open
Show file tree
Hide file tree
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
15 changes: 15 additions & 0 deletions tests/test_middlewares.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import os

import pytest

from tinydb import TinyDB
from tinydb.middlewares import CachingMiddleware
from tinydb.storages import MemoryStorage, JSONStorage
Expand Down Expand Up @@ -98,6 +100,19 @@ def test_caching_json_write(tmpdir):
# Assert JSON file has been closed
assert db._storage._handle.closed


def test_caching_rejects_use_after_close(tmpdir):
path = str(tmpdir.join('closed.db'))
db = TinyDB(path, storage=CachingMiddleware(JSONStorage))
db.insert({'key': 'value'})
db.close()

with pytest.raises(ValueError, match='closed'):
db.insert({'key': 'again'})

with pytest.raises(ValueError, match='closed'):
db.all()

del db

# Reopen database
Expand Down
15 changes: 15 additions & 0 deletions tinydb/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,12 @@ def __init__(self, storage_cls):
# Prepare the cache
self.cache = None
self._cache_modified_count = 0
self._closed = False

def read(self):
if self._closed:
raise ValueError('I/O operation on closed storage')

if self.cache is None:
# Empty cache: read from the storage
self.cache = self.storage.read()
Expand All @@ -102,6 +106,9 @@ def read(self):
return self.cache

def write(self, data):
if self._closed:
raise ValueError('I/O operation on closed storage')

# Store data in cache
self.cache = data
self._cache_modified_count += 1
Expand All @@ -114,14 +121,22 @@ def flush(self):
"""
Flush all unwritten data to disk.
"""
if self._closed:
raise ValueError('I/O operation on closed storage')

if self._cache_modified_count > 0:
# Force-flush the cache by writing the data to the storage
self.storage.write(self.cache)
self._cache_modified_count = 0

def close(self):
if self._closed:
return

# Flush potentially unwritten data
self.flush()

# Let the storage clean up too
self.storage.close()
self._closed = True
self.cache = None