Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

We can now save changes to metadata #58

Merged
merged 1 commit into from
Aug 16, 2024
Merged
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
49 changes: 40 additions & 9 deletions genweb/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

from glob import glob
from copy import deepcopy
from os.path import splitext
from datetime import datetime

from yaml import safe_load
from yaml import safe_load, safe_dump


def load_yaml(path: str) -> dict[str, dict]:
Expand All @@ -24,20 +26,47 @@ def load_yaml(path: str) -> dict[str, dict]:


class Metadata:
"""read-only-dict-like object"""
"""dict-like object
When loading from file name.ext revisions are saved to name YYYY-MM-DD HH:MM:SS.ext
Revisions saved earlier are preserved, but overridden by later revisions
"""

def __init__(self, path: str):
self.path = path # original file

def __init__(self, path_pattern: str):
self.path = path_pattern
self.original = Metadata.__load(path_pattern)
# Calculate the file we will save any changes to
base, extension = splitext(path)
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.revision_path = f"{base} {now}{extension}"

# load all the revisions
self.original = Metadata.__load(path)
self.updated = {}

def save(self) -> None:
"""If there are changes saves them to the revision file"""
if not self.updated:
return

with open(self.revision_path, "w", encoding="utf-8") as revision_file:
safe_dump(self.updated, revision_file)

@staticmethod
def __load(path_pattern: str) -> dict[str:dict]:
def __load(path: str) -> dict[str:dict]:
result = {}

for path in sorted(glob(path_pattern)):
result.update(Metadata.__validate(load_yaml(path)))

# Revisions are stored as: base YYYY-mm-dd HH:MM:SS.ext
base, extension = splitext(path)
revisions = glob(base + "*" + extension)
# ensure we load the original file first
revisions.remove(path)
revisions.sort()
revisions.insert(0, path)

# load them in order to have later override earlier
for revision_path in revisions:
revision = Metadata.__validate(load_yaml(revision_path))
result.update(revision)
return result

@staticmethod
Expand All @@ -54,6 +83,8 @@ def __combined(self, deep=False) -> dict[str:dict]:

return combined

# MARK: dict methods

def __getitem__(self, key: str) -> dict:
if key in self.updated:
return deepcopy(self.updated[key])
Expand Down
File renamed without changes.
File renamed without changes.
32 changes: 30 additions & 2 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@


from os.path import dirname, join
from shutil import copy
from tempfile import TemporaryDirectory


from genweb.metadata import load_yaml, Metadata
Expand All @@ -12,8 +14,33 @@
DATA_DIR = join(dirname(__file__), "data")


def test_metadata_save() -> None:
with TemporaryDirectory() as working_dir:
src_file = join(DATA_DIR, "example.yml")
metadata_file = join(working_dir, "example.yml")
copy(src_file, metadata_file)
metadata = Metadata(metadata_file)
johns_picture = metadata["1700000000WilliamsJohn1665DavisRebecca1639"]
johns_picture["width"] = 500
metadata["1700000000WilliamsJohn1665DavisRebecca1639"] = johns_picture
assert metadata["1700000000WilliamsJohn1665DavisRebecca1639"]["width"] == 500
metadata.save()

metadata = Metadata(metadata_file)
assert metadata["1700000000WilliamsJohn1665DavisRebecca1639"]["width"] == 500
metadata.save()

with open(src_file, "r", encoding="utf-8") as file:
original = file.read()

with open(metadata_file, "r", encoding="utf-8") as file:
copied = file.read()

assert original == copied, "base metadata file was modified"


def test_metadata_update() -> None:
metadata = Metadata(join(DATA_DIR, "layered.*.yml"))
metadata = Metadata(join(DATA_DIR, "layered.yml"))
metadata["0000000000PageMarcA1973HislopMickieL1949"] = {
"type": "inline",
"content": "hello",
Expand All @@ -38,7 +65,7 @@ def test_metadata_update() -> None:


def test_metadata() -> None:
metadata = Metadata(join(DATA_DIR, "layered.*.yml"))
metadata = Metadata(join(DATA_DIR, "layered.yml"))
assert "0000000000SmithCaleb1765JonesMary1724" in metadata
assert "0000000000JohnsonSamI1892MillerJane1860" in metadata
assert "1700000000WilliamsJohn1665DavisRebecca1639" in metadata
Expand Down Expand Up @@ -99,3 +126,4 @@ def test_load_yaml() -> None:
test_load_yaml()
test_metadata()
test_metadata_update()
test_metadata_save()
Loading