Added --resume to import, #768 (#784)

This commit is contained in:
Rhet Turnbull
2022-08-31 22:14:49 -07:00
committed by GitHub
parent 026b86abe9
commit b8ad8016aa
4 changed files with 581 additions and 5 deletions

View File

@@ -15,7 +15,7 @@ from typing import Dict
import pytest
from click.testing import CliRunner
from photoscript import Photo
from pytest import approx
from pytest import MonkeyPatch, approx
from osxphotos.cli.import_cli import import_cli
from osxphotos.exiftool import get_exiftool_path
@@ -908,3 +908,41 @@ def test_import_report_invalid_name():
],
)
assert result.exit_code != 0
@pytest.mark.test_import
def test_import_resume(monkeypatch: MonkeyPatch, tmpdir):
"""Test import with --resume"""
monkeypatch.delenv("XDG_DATA_HOME", raising=False)
monkeypatch.setenv("XDG_DATA_HOME", os.fspath(str(tmpdir)))
cwd = os.getcwd()
test_image_1 = os.path.join(cwd, TEST_IMAGE_1)
runner = CliRunner()
result = runner.invoke(
import_cli,
["--verbose", test_image_1],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
import_data = parse_import_output(result.output)
file_1 = pathlib.Path(test_image_1).name
uuid_1 = import_data[file_1]
photo_1 = Photo(uuid_1)
assert photo_1.filename == file_1
# test resume
test_image_2 = os.path.join(cwd, TEST_IMAGE_2)
result = runner.invoke(
import_cli,
["--verbose", "--resume", test_image_1, test_image_2],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
assert "Skipping" in result.output
assert "1 skipped" in result.output
assert "imported 1" in result.output

249
tests/test_sqlitekvstore.py Normal file
View File

@@ -0,0 +1,249 @@
"""Test osxphotos.sqlitekvstore"""
import gzip
import json
import pickle
import sqlite3
from typing import Any
import pytest
import osxphotos.sqlitekvstore
def pickle_and_zip(data: Any) -> bytes:
"""
Pickle and gzip data.
Args:
data: data to pickle and gzip (must be pickle-able)
Returns:
bytes of gzipped pickled data
"""
pickled = pickle.dumps(data)
return gzip.compress(pickled)
def unzip_and_unpickle(data: bytes) -> Any:
"""
Unzip and unpickle data.
Args:
data: data to unzip and unpickle
Returns:
unpickled data
"""
return pickle.loads(gzip.decompress(data))
def test_basic_get_set(tmpdir):
"""Test basic functionality"""
dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath)
kvstore.set("foo", "bar")
assert kvstore.get("foo") == "bar"
assert kvstore.get("FOOBAR") is None
kvstore.delete("foo")
assert kvstore.get("foo") is None
kvstore.set("baz", None)
assert kvstore.get("baz") is None
kvstore.close()
# verify that the connection is closed
conn = kvstore.connection()
with pytest.raises(sqlite3.ProgrammingError):
conn.execute("PRAGMA user_version;")
def test_basic_get_set_wal(tmpdir):
"""Test basic functionality with WAL mode"""
dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath, wal=True)
kvstore.set("foo", "bar")
assert kvstore.get("foo") == "bar"
assert kvstore.get("FOOBAR") is None
kvstore.delete("foo")
assert kvstore.get("foo") is None
kvstore.set("baz", None)
assert kvstore.get("baz") is None
kvstore.vacuum()
kvstore.close()
# verify that the connection is closed
conn = kvstore.connection()
with pytest.raises(sqlite3.ProgrammingError):
conn.execute("PRAGMA user_version;")
def test_set_many(tmpdir):
"""Test set_many()"""
dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath)
kvstore.set_many([("foo", "bar"), ("baz", "qux")])
assert kvstore.get("foo") == "bar"
assert kvstore.get("baz") == "qux"
kvstore.close()
# make sure values got committed
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath)
assert kvstore.get("foo") == "bar"
assert kvstore.get("baz") == "qux"
kvstore.close()
def test_set_many_dict(tmpdir):
"""Test set_many() with dict of values"""
dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath)
kvstore.set_many({"foo": "bar", "baz": "qux"})
assert kvstore.get("foo") == "bar"
assert kvstore.get("baz") == "qux"
kvstore.close()
# make sure values got committed
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath)
assert kvstore.get("foo") == "bar"
assert kvstore.get("baz") == "qux"
kvstore.close()
def test_basic_context_handler(tmpdir):
"""Test basic functionality with context handler"""
dbpath = tmpdir / "kvtest.db"
with osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) as kvstore:
kvstore.set("foo", "bar")
assert kvstore.get("foo") == "bar"
assert kvstore.get("FOOBAR") is None
kvstore.delete("foo")
assert kvstore.get("foo") is None
# verify that the connection is closed
conn = kvstore.connection()
with pytest.raises(sqlite3.ProgrammingError):
conn.execute("PRAGMA user_version;")
def test_about(tmpdir):
"""Test about property"""
dbpath = tmpdir / "kvtest.db"
with osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) as kvstore:
kvstore.about = "My description"
assert kvstore.about == "My description"
kvstore.about = "My new description"
assert kvstore.about == "My new description"
def test_existing_db(tmpdir):
"""Test that opening an existing database works as expected"""
dbpath = tmpdir / "kvtest.db"
with osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) as kvstore:
kvstore.set("foo", "bar")
with osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) as kvstore:
assert kvstore.get("foo") == "bar"
def test_dict_interface(tmpdir):
""" "Test dict interface"""
dbpath = tmpdir / "kvtest.db"
with osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath) as kvstore:
kvstore["foo"] = "bar"
assert kvstore["foo"] == "bar"
assert len(kvstore) == 1
assert kvstore.get("foo") == "bar"
assert "foo" in kvstore
assert "FOOBAR" not in kvstore
assert kvstore.pop("foo") == "bar"
assert kvstore.get("foo") is None
kvstore["❤️"] = "💖"
assert kvstore["❤️"] == "💖"
assert kvstore.get("❤️") == "💖"
del kvstore["❤️"]
assert kvstore.get("❤️") is None
with pytest.raises(KeyError):
kvstore["baz"]
with pytest.raises(KeyError):
del kvstore["notakey"]
with pytest.raises(KeyError):
kvstore.pop("foo")
def test_serialize_deserialize(tmpdir):
"""Test serialize/deserialize"""
dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(
dbpath, serialize=json.dumps, deserialize=json.loads
)
kvstore.set("foo", {"bar": "baz"})
assert kvstore.get("foo") == {"bar": "baz"}
assert kvstore.get("FOOBAR") is None
def test_serialize_deserialize_binary_data(tmpdir):
"""Test serialize/deserialize with binary data"""
dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(
dbpath, serialize=pickle_and_zip, deserialize=unzip_and_unpickle
)
kvstore.set("foo", {"bar": "baz"})
assert kvstore.get("foo") == {"bar": "baz"}
assert kvstore.get("FOOBAR") is None
def test_serialize_deserialize_bad_callable(tmpdir):
"""Test serialize/deserialize with bad values"""
dbpath = tmpdir / "kvtest.db"
with pytest.raises(TypeError):
osxphotos.sqlitekvstore.SQLiteKeyValueStore(
dbpath, serialize=1, deserialize=None
)
with pytest.raises(TypeError):
osxphotos.sqlitekvstore.SQLiteKeyValueStore(
dbpath, serialize=None, deserialize=1
)
def test_iter(tmpdir):
"""Test generator behavior"""
dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath)
kvstore.set("foo", "bar")
kvstore.set("baz", "qux")
kvstore.set("quux", "corge")
kvstore.set("grault", "garply")
assert len(kvstore) == 4
assert sorted(iter(kvstore)) == ["baz", "foo", "grault", "quux"]
def test_keys_values_items(tmpdir):
"""Test keys, values, items"""
dbpath = tmpdir / "kvtest.db"
kvstore = osxphotos.sqlitekvstore.SQLiteKeyValueStore(dbpath)
kvstore.set("foo", "bar")
kvstore.set("baz", "qux")
kvstore.set("quux", "corge")
kvstore.set("grault", "garply")
assert sorted(kvstore.keys()) == ["baz", "foo", "grault", "quux"]
assert sorted(kvstore.values()) == ["bar", "corge", "garply", "qux"]
assert sorted(kvstore.items()) == [
("baz", "qux"),
("foo", "bar"),
("grault", "garply"),
("quux", "corge"),
]