Skip to content

Commit

Permalink
Fixed backup database to be conformant JSON, #56
Browse files Browse the repository at this point in the history
  • Loading branch information
RhetTbull committed Jul 16, 2022
1 parent 57af40b commit a01c4bb
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 28 deletions.
4 changes: 2 additions & 2 deletions dev_requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pytest==6.2.4
pyinstaller==4.3
pytest==7.1.2
pyinstaller==5.2
2 changes: 1 addition & 1 deletion osxmetadata/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
""" osxmetadata version """

__version__ = "0.99.37"
__version__ = "0.99.38"
66 changes: 45 additions & 21 deletions osxmetadata/backup.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,63 @@
""" Functions for writing and loading backup files """

import json
import logging
import os
from enum import Enum

""" Functions for writing and loading backup files """

class BackupDatabaseType(Enum):
SINGLE_RECORD_JSON = 1
JSON = 2


def backup_database_type(path: str) -> BackupDatabaseType:
"""Return BackupDatabaseType enum indicating type of backup file for path"""
with open(path) as fp:
line = fp.readline()
if not line:
raise ValueError("Unknown backup file type")
ch = line[0]
if ch == "{":
return BackupDatabaseType.SINGLE_RECORD_JSON
elif ch == "[":
return BackupDatabaseType.JSON
else:
raise ValueError("Unknown backup file type")


def write_backup_file(backup_file, backup_data):
""" Write backup_data to backup_file as JSON
backup_data: dict where key is filename and value is dict of the attributes
as returned by json.loads(OSXMetaData.to_json()) """
"""Write backup_data to backup_file as JSON
backup_data: dict where key is filename and value is dict of the attributes
as returned by json.loads(OSXMetaData.to_json())"""

with open(backup_file, mode="w") as fp:
for record in backup_data.values():
json_str = json.dumps(record)
fp.write(json_str)
fp.write("\n")
json.dump(list(backup_data.values()), fp)


def load_backup_file(backup_file):
""" Load attribute data from JSON in backup_file
Returns: backup_data dict """
"""Load attribute data from JSON in backup_file
Returns: backup_data dict"""

if not os.path.isfile(backup_file):
raise FileNotFoundError(f"Could not find backup file: {backup_file}")

backup_data = {}
with open(backup_file, mode="r") as fp:
for line in fp:
data = json.loads(line)
fname = data["_filename"]
if fname in backup_data:
logging.warning(
f"WARNING: duplicate filename {fname} found in {backup_file}"
)

backup_data[fname] = data
if backup_database_type(backup_file) == BackupDatabaseType.SINGLE_RECORD_JSON:
# old style single record of json per file
backup_data = {}
with open(backup_file, mode="r") as fp:
for line in fp:
data = json.loads(line)
fname = data["_filename"]
if fname in backup_data:
logging.warning(
f"WARNING: duplicate filename {fname} found in {backup_file}"
)

backup_data[fname] = data
else:
with open(backup_file, mode="r") as fp:
backup_records = json.load(fp)
backup_data = {data["_filename"]: data for data in backup_records}

return backup_data
2 changes: 1 addition & 1 deletion osxmetadata/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,4 +557,4 @@ def set_value(self, value):

def __len__(self):
self._load_data()
return self.data.__len__() if self.data else 0
return self.data.__len__() if self.data else 0
6 changes: 3 additions & 3 deletions osxmetadata/osxmetadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from ._version import __version__
from .attributes import ATTRIBUTES, Attribute, validate_attribute_value
from .classes import _AttributeOSXPhotosDetectedText, _AttributeList, _AttributeTagsList
from .classes import _AttributeList, _AttributeOSXPhotosDetectedText, _AttributeTagsList
from .constants import (
_FINDER_COMMENT_NAMES,
FINDER_COLOR_NONE,
Expand Down Expand Up @@ -297,12 +297,12 @@ def get_attribute_str(self, attribute_name):
e.g. if attribute is a datedate.datetime object, will
format using datetime.isoformat()
attribute_name: name of attribute"""

attribute = ATTRIBUTES[attribute_name]
value = self.get_attribute(attribute_name)
if attribute.class_ == _AttributeOSXPhotosDetectedText:
return json.dumps(value)

if type(value) in [list, set]:
if value:
if type(value[0]) == datetime.datetime:
Expand Down

0 comments on commit a01c4bb

Please sign in to comment.