Updated sqlitekvstore

This commit is contained in:
Rhet Turnbull
2022-09-01 06:17:15 -07:00
parent e605ed847d
commit cee2acad53
3 changed files with 29 additions and 28 deletions

View File

@@ -37,7 +37,7 @@ from osxphotos.exiftool import ExifToolCaching, get_exiftool_path
from osxphotos.photoinfo import PhotoInfoNone from osxphotos.photoinfo import PhotoInfoNone
from osxphotos.photosalbum import PhotosAlbumPhotoScript from osxphotos.photosalbum import PhotosAlbumPhotoScript
from osxphotos.phototemplate import PhotoTemplate, RenderOptions from osxphotos.phototemplate import PhotoTemplate, RenderOptions
from osxphotos.sqlitekvstore import SQLiteKeyValueStore from osxphotos.sqlitekvstore import SQLiteKVStore
from osxphotos.utils import pluralize from osxphotos.utils import pluralize
from .click_rich_echo import ( from .click_rich_echo import (
@@ -1293,7 +1293,7 @@ def import_cli(
# report data is set even if no report is generated # report data is set even if no report is generated
report_data: Dict[Path, ReportRecord] = {} report_data: Dict[Path, ReportRecord] = {}
import_db = SQLiteKeyValueStore( import_db = SQLiteKVStore(
get_data_dir() / IMPORT_DB, get_data_dir() / IMPORT_DB,
wal=True, wal=True,
serialize=ReportRecord.serialize, serialize=ReportRecord.serialize,

View File

@@ -6,11 +6,13 @@ import os.path
import sqlite3 import sqlite3
from typing import Callable, Dict, Generator, Iterable, Optional, Tuple, TypeVar, Union from typing import Callable, Dict, Generator, Iterable, Optional, Tuple, TypeVar, Union
# keep mypy happy # keep mypy happy, keys/values can be any type supported by SQLite
T = TypeVar("T") T = TypeVar("T")
__all__ = ["SQLiteKVStore"]
class SQLiteKeyValueStore:
class SQLiteKVStore:
"""Simple Key-Value Store that uses sqlite3 database as backend""" """Simple Key-Value Store that uses sqlite3 database as backend"""
def __init__( def __init__(
@@ -50,7 +52,7 @@ class SQLiteKeyValueStore:
self._conn.commit() self._conn.commit()
def _create_database(self, dbpath: str): def _create_database(self, dbpath: str):
"""Create the progress database""" """Create the key-value database"""
conn = sqlite3.Connection(dbpath) conn = sqlite3.Connection(dbpath)
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute( cursor.execute(
@@ -102,7 +104,10 @@ class SQLiteKeyValueStore:
Args: Args:
key: key to get from key-value store key: key to get from key-value store
default: optional default value to return if key not found default: optional default value to return if key not found
Returns: value for key or default (Note: does not insert key:default into database if key does not exist)
Returns: value for key or default
Note: does not insert key:default into database if key does not exist
""" """
try: try:
return self._get(key) return self._get(key)

View File

@@ -1,4 +1,4 @@
"""Test osxphotos.sqlitekvstore""" """Test sqlitekvstore"""
import gzip import gzip
import json import json
@@ -41,7 +41,7 @@ def unzip_and_unpickle(data: bytes) -> Any:
def test_basic_get_set(tmpdir): def test_basic_get_set(tmpdir):
"""Test basic functionality""" """Test basic functionality"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) kvstore = osxphotos.sqlitekvstore.SQLiteKVStore(dbpath)
kvstore.set("foo", "bar") kvstore.set("foo", "bar")
assert kvstore.get("foo") == "bar" assert kvstore.get("foo") == "bar"
assert kvstore.get("FOOBAR") is None assert kvstore.get("FOOBAR") is None
@@ -61,7 +61,7 @@ def test_basic_get_set(tmpdir):
def test_basic_get_set_wal(tmpdir): def test_basic_get_set_wal(tmpdir):
"""Test basic functionality with WAL mode""" """Test basic functionality with WAL mode"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath, wal=True) kvstore = osxphotos.sqlitekvstore.SQLiteKVStore(dbpath, wal=True)
kvstore.set("foo", "bar") kvstore.set("foo", "bar")
assert kvstore.get("foo") == "bar" assert kvstore.get("foo") == "bar"
assert kvstore.get("FOOBAR") is None assert kvstore.get("FOOBAR") is None
@@ -84,14 +84,14 @@ def test_set_many(tmpdir):
"""Test set_many()""" """Test set_many()"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) kvstore = osxphotos.sqlitekvstore.SQLiteKVStore(dbpath)
kvstore.set_many([("foo", "bar"), ("baz", "qux")]) kvstore.set_many([("foo", "bar"), ("baz", "qux")])
assert kvstore.get("foo") == "bar" assert kvstore.get("foo") == "bar"
assert kvstore.get("baz") == "qux" assert kvstore.get("baz") == "qux"
kvstore.close() kvstore.close()
# make sure values got committed # make sure values got committed
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) kvstore = osxphotos.sqlitekvstore.SQLiteKVStore(dbpath)
assert kvstore.get("foo") == "bar" assert kvstore.get("foo") == "bar"
assert kvstore.get("baz") == "qux" assert kvstore.get("baz") == "qux"
kvstore.close() kvstore.close()
@@ -101,14 +101,14 @@ def test_set_many_dict(tmpdir):
"""Test set_many() with dict of values""" """Test set_many() with dict of values"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) kvstore = osxphotos.sqlitekvstore.SQLiteKVStore(dbpath)
kvstore.set_many({"foo": "bar", "baz": "qux"}) kvstore.set_many({"foo": "bar", "baz": "qux"})
assert kvstore.get("foo") == "bar" assert kvstore.get("foo") == "bar"
assert kvstore.get("baz") == "qux" assert kvstore.get("baz") == "qux"
kvstore.close() kvstore.close()
# make sure values got committed # make sure values got committed
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) kvstore = osxphotos.sqlitekvstore.SQLiteKVStore(dbpath)
assert kvstore.get("foo") == "bar" assert kvstore.get("foo") == "bar"
assert kvstore.get("baz") == "qux" assert kvstore.get("baz") == "qux"
kvstore.close() kvstore.close()
@@ -118,7 +118,7 @@ def test_basic_context_handler(tmpdir):
"""Test basic functionality with context handler""" """Test basic functionality with context handler"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
with osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) as kvstore: with osxphotos.sqlitekvstore.SQLiteKVStore(dbpath) as kvstore:
kvstore.set("foo", "bar") kvstore.set("foo", "bar")
assert kvstore.get("foo") == "bar" assert kvstore.get("foo") == "bar"
assert kvstore.get("FOOBAR") is None assert kvstore.get("FOOBAR") is None
@@ -134,7 +134,7 @@ def test_basic_context_handler(tmpdir):
def test_about(tmpdir): def test_about(tmpdir):
"""Test about property""" """Test about property"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
with osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) as kvstore: with osxphotos.sqlitekvstore.SQLiteKVStore(dbpath) as kvstore:
kvstore.about = "My description" kvstore.about = "My description"
assert kvstore.about == "My description" assert kvstore.about == "My description"
kvstore.about = "My new description" kvstore.about = "My new description"
@@ -144,17 +144,17 @@ def test_about(tmpdir):
def test_existing_db(tmpdir): def test_existing_db(tmpdir):
"""Test that opening an existing database works as expected""" """Test that opening an existing database works as expected"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
with osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) as kvstore: with osxphotos.sqlitekvstore.SQLiteKVStore(dbpath) as kvstore:
kvstore.set("foo", "bar") kvstore.set("foo", "bar")
with osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) as kvstore: with osxphotos.sqlitekvstore.SQLiteKVStore(dbpath) as kvstore:
assert kvstore.get("foo") == "bar" assert kvstore.get("foo") == "bar"
def test_dict_interface(tmpdir): def test_dict_interface(tmpdir):
""" "Test dict interface""" """ "Test dict interface"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
with osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) as kvstore: with osxphotos.sqlitekvstore.SQLiteKVStore(dbpath) as kvstore:
kvstore["foo"] = "bar" kvstore["foo"] = "bar"
assert kvstore["foo"] == "bar" assert kvstore["foo"] == "bar"
assert len(kvstore) == 1 assert len(kvstore) == 1
@@ -186,7 +186,7 @@ def test_dict_interface(tmpdir):
def test_serialize_deserialize(tmpdir): def test_serialize_deserialize(tmpdir):
"""Test serialize/deserialize""" """Test serialize/deserialize"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore( kvstore = osxphotos.sqlitekvstore.SQLiteKVStore(
dbpath, serialize=json.dumps, deserialize=json.loads dbpath, serialize=json.dumps, deserialize=json.loads
) )
kvstore.set("foo", {"bar": "baz"}) kvstore.set("foo", {"bar": "baz"})
@@ -197,7 +197,7 @@ def test_serialize_deserialize(tmpdir):
def test_serialize_deserialize_binary_data(tmpdir): def test_serialize_deserialize_binary_data(tmpdir):
"""Test serialize/deserialize with binary data""" """Test serialize/deserialize with binary data"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore( kvstore = osxphotos.sqlitekvstore.SQLiteKVStore(
dbpath, serialize=pickle_and_zip, deserialize=unzip_and_unpickle dbpath, serialize=pickle_and_zip, deserialize=unzip_and_unpickle
) )
kvstore.set("foo", {"bar": "baz"}) kvstore.set("foo", {"bar": "baz"})
@@ -209,20 +209,16 @@ def test_serialize_deserialize_bad_callable(tmpdir):
"""Test serialize/deserialize with bad values""" """Test serialize/deserialize with bad values"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
with pytest.raises(TypeError): with pytest.raises(TypeError):
osxphotos.sqlitekvstore.SQLiteKeyValueStore( osxphotos.sqlitekvstore.SQLiteKVStore(dbpath, serialize=1, deserialize=None)
dbpath, serialize=1, deserialize=None
)
with pytest.raises(TypeError): with pytest.raises(TypeError):
osxphotos.sqlitekvstore.SQLiteKeyValueStore( osxphotos.sqlitekvstore.SQLiteKVStore(dbpath, serialize=None, deserialize=1)
dbpath, serialize=None, deserialize=1
)
def test_iter(tmpdir): def test_iter(tmpdir):
"""Test generator behavior""" """Test generator behavior"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) kvstore = osxphotos.sqlitekvstore.SQLiteKVStore(dbpath)
kvstore.set("foo", "bar") kvstore.set("foo", "bar")
kvstore.set("baz", "qux") kvstore.set("baz", "qux")
kvstore.set("quux", "corge") kvstore.set("quux", "corge")
@@ -234,7 +230,7 @@ def test_iter(tmpdir):
def test_keys_values_items(tmpdir): def test_keys_values_items(tmpdir):
"""Test keys, values, items""" """Test keys, values, items"""
dbpath = tmpdir / "kvtest.db" dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) kvstore = osxphotos.sqlitekvstore.SQLiteKVStore(dbpath)
kvstore.set("foo", "bar") kvstore.set("foo", "bar")
kvstore.set("baz", "qux") kvstore.set("baz", "qux")
kvstore.set("quux", "corge") kvstore.set("quux", "corge")