Added retry to export_db for #674

This commit is contained in:
Rhet Turnbull 2022-04-24 15:06:13 -07:00
parent ad13565dfd
commit e4b6c0f1e0
6 changed files with 486 additions and 356 deletions

File diff suppressed because it is too large Load Diff

View File

@ -396,7 +396,7 @@ If called in context manager, returns True (execution is delayed until exiting c
<dt class="sig sig-object py" id="osxphotos.ExportDB.get_file_record">
<span class="sig-name descname"><span class="pre">get_file_record</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">filename</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Union</span><span class="p"><span class="pre">[</span></span><span class="pre">pathlib.Path</span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">str</span><span class="p"><span class="pre">]</span></span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon"></span> <span class="sig-return-typehint"><span class="pre">osxphotos.export_db.ExportRecord</span></span></span><a class="reference internal" href="_modules/osxphotos/export_db.html#ExportDB.get_file_record"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.ExportDB.get_file_record" title="Permalink to this definition">#</a></dt>
<dd><p>get info for filename and uuid</p>
<p>Returns: an ExportRecord object</p>
<p>Returns: an ExportRecord object or None if filename not found</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="osxphotos.ExportDB.get_photoinfo_for_uuid">

Binary file not shown.

View File

@ -1,6 +1,7 @@
""" Helper class for managing database used by PhotoExporter for tracking state of exports and updates """
import contextlib
import datetime
import json
import logging
@ -13,6 +14,8 @@ from sqlite3 import Error
from tempfile import TemporaryDirectory
from typing import Optional, Tuple, Union
from tenacity import retry, stop_after_attempt
from ._constants import OSXPHOTOS_EXPORT_DB
from ._version import __version__
from .fileutil import FileUtil
@ -27,6 +30,9 @@ __all__ = [
OSXPHOTOS_EXPORTDB_VERSION = "6.0"
OSXPHOTOS_ABOUT_STRING = f"Created by osxphotos version {__version__} (https://github.com/RhetTbull/osxphotos) on {datetime.datetime.now()}"
# max retry attempts for methods which use tenacity.retry
MAX_RETRY_ATTEMPTS = 5
class ExportDB:
"""Interface to sqlite3 database used to store state information for osxphotos export command"""
@ -63,20 +69,19 @@ class ExportDB:
def get_file_record(self, filename: Union[pathlib.Path, str]) -> "ExportRecord":
"""get info for filename and uuid
Returns: an ExportRecord object
Returns: an ExportRecord object or None if filename not found
"""
filename = self._relative_filepath(filename)
filename_normalized = self._normalize_filepath(filename)
conn = self._conn
c = conn.cursor()
row = c.execute(
if _ := c.execute(
"SELECT uuid FROM export_data WHERE filepath_normalized = ?;",
(filename_normalized,),
).fetchone()
if not row:
return None
return ExportRecord(conn, filename_normalized)
).fetchone():
return ExportRecord(conn, filename_normalized)
return None
def create_file_record(
self, filename: Union[pathlib.Path, str], uuid: str
@ -362,13 +367,11 @@ class ExportDB:
def __del__(self):
"""ensure the database connection is closed"""
try:
with contextlib.suppress(Exception):
self._conn.close()
except:
pass
def _insert_run_info(self):
dt = datetime.datetime.utcnow().isoformat()
dt = datetime.datetime.now(datetime.timezone.utc).isoformat()
python_path = sys.executable
cmd = sys.argv[0]
args = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else ""
@ -593,6 +596,7 @@ class ExportDBInMemory(ExportDB):
self._conn = self._open_export_db(self._dbfile)
self._insert_run_info()
@retry(stop=stop_after_attempt(MAX_RETRY_ATTEMPTS))
def write_to_disk(self):
"""Write changes from in-memory database back to disk"""
@ -677,10 +681,8 @@ class ExportDBInMemory(ExportDB):
def __del__(self):
"""close the database connection"""
try:
with contextlib.suppress(Error):
self.close()
except Error as e:
pass
class ExportDBTemp(ExportDBInMemory):
@ -720,11 +722,10 @@ class ExportRecord:
"""return filepath"""
conn = self._conn
c = conn.cursor()
row = c.execute(
if row := c.execute(
"SELECT filepath FROM export_data WHERE filepath_normalized = ?;",
(self._filepath_normalized,),
).fetchone()
if row:
).fetchone():
return row[0]
raise ValueError(
@ -741,11 +742,10 @@ class ExportRecord:
"""return uuid"""
conn = self._conn
c = conn.cursor()
row = c.execute(
if row := c.execute(
"SELECT uuid FROM export_data WHERE filepath_normalized = ?;",
(self._filepath_normalized,),
).fetchone()
if row:
).fetchone():
return row[0]
raise ValueError(f"No uuid found in database for {self._filepath_normalized}")
@ -755,11 +755,10 @@ class ExportRecord:
"""returns the digest value"""
conn = self._conn
c = conn.cursor()
row = c.execute(
if row := c.execute(
"SELECT digest FROM export_data WHERE filepath_normalized = ?;",
(self._filepath_normalized,),
).fetchone()
if row:
).fetchone():
return row[0]
raise ValueError(f"No digest found in database for {self._filepath_normalized}")
@ -781,11 +780,10 @@ class ExportRecord:
"""returns exifdata value for record"""
conn = self._conn
c = conn.cursor()
row = c.execute(
if row := c.execute(
"SELECT exifdata FROM export_data WHERE filepath_normalized = ?;",
(self._filepath_normalized,),
).fetchone()
if row:
).fetchone():
return row[0]
raise ValueError(
@ -812,11 +810,10 @@ class ExportRecord:
"""return source file signature value"""
conn = self._conn
c = conn.cursor()
row = c.execute(
if row := c.execute(
"SELECT src_mode, src_size, src_mtime FROM export_data WHERE filepath_normalized = ?;",
(self._filepath_normalized,),
).fetchone()
if row:
).fetchone():
mtime = int(row[2]) if row[2] is not None else None
return (row[0], row[1], mtime)
@ -846,11 +843,10 @@ class ExportRecord:
"""return destination file signature"""
conn = self._conn
c = conn.cursor()
row = c.execute(
if row := c.execute(
"SELECT dest_mode, dest_size, dest_mtime FROM export_data WHERE filepath_normalized = ?;",
(self._filepath_normalized,),
).fetchone()
if row:
).fetchone():
mtime = int(row[2]) if row[2] is not None else None
return (row[0], row[1], mtime)

View File

@ -23,6 +23,7 @@ PyYAML>=5.4.1,<6.0.0
requests>=2.27.1,<3.0.0
rich>=11.2.0,<13.0.0
rich_theme_manager>=0.7.0
tenacity>=8.0.1,<9.0.0
textx>=2.3.0,<2.4.0
toml>=0.10.2,<0.11.0
wrapt>=1.13.3,<1.14.0

View File

@ -98,6 +98,7 @@ setup(
"requests>=2.27.1,<3.0.0",
"rich>=11.2.0,<13.0.0",
"rich_theme_manager>=0.7.0",
"tenacity>=8.0.1,<9.0.0",
"textx>=2.3.0,<3.0.0",
"toml>=0.10.2,<0.11.0",
"wrapt>=1.13.3,<1.14.0",