Skip to content

Commit

Permalink
Merge pull request #276 from jacebrowning/delete-invalid-yaml
Browse files Browse the repository at this point in the history
Delete unparseable YAML files in manager methods
  • Loading branch information
jacebrowning committed Aug 19, 2022
2 parents bae3642 + b8064e9 commit 2f8c5d4
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 44 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release Notes

## 1.4.3 (2022-08-19)

- Fixed handling of unparseable YAML files in manager methods.

## 1.4.2 (2022-07-29)

- Fixed exception when `Union[int, float]` or `Union[str, ...]` is used.
Expand Down
8 changes: 7 additions & 1 deletion datafiles/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import log
from parse import parse
from ruamel.yaml.parser import ParserError

from . import hooks

Expand Down Expand Up @@ -40,7 +41,12 @@ def get(self, *args, **kwargs) -> Model:

with hooks.disabled():
instance = self.model(*args, **kwargs)
instance.datafile.load()
try:
instance.datafile.load()
except ParserError:
log.critical(f"Deleting unparseable YAML: {instance.datafile.path}")
instance.datafile.path.unlink()
instance.datafile.load()

return instance

Expand Down
15 changes: 15 additions & 0 deletions datafiles/tests/test_manager.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# pylint: disable=unused-variable

import os
import shutil
from dataclasses import dataclass
from pathlib import Path
from typing import Optional
from unittest.mock import patch

Expand All @@ -26,6 +28,7 @@ class MyClass:
def describe_manager():
@pytest.fixture
def manager():
shutil.rmtree(Path(__file__).parent / "files", ignore_errors=True)
model = create_model(MyClass, pattern="files/{self.foo}.yml")
return Manager(model)

Expand All @@ -46,6 +49,12 @@ def when_file_exists(mock_load, expect, manager):
def when_file_missing(expect, manager):
expect(manager.get_or_none(foo=3, bar=4)).is_(None)

def when_file_corrupt(expect, manager):
instance = manager.get_or_create(foo=2, bar=1)
instance.datafile.path.write_text("{")
instance = manager.get_or_none(foo=2, bar=2)
expect(instance).is_(None)

def describe_get_or_create():
@patch("datafiles.mapper.Mapper.save")
@patch("datafiles.mapper.Mapper.load")
Expand All @@ -64,6 +73,12 @@ def when_file_missing(mock_save, mock_load, expect, manager):
expect(mock_save.called).is_(True)
expect(mock_load.called).is_(True)

def when_file_corrupt(expect, manager):
instance = manager.get_or_create(foo=2, bar=1)
instance.datafile.path.write_text("{")
instance = manager.get_or_create(foo=2, bar=2)
expect(instance.bar) == 2

def describe_all():
@patch("datafiles.mapper.Mapper.exists", False)
def when_no_files_exist(expect, manager):
Expand Down
1 change: 1 addition & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
jinja2==3.0.3; python_version >= "3.6"
markdown==3.3.4; python_version >= "3.6"
mkdocs==1.3.1; python_version >= "3.6"
jupyterlab-pygments==0.2.2; python_version >= "3.7"
pygments==2.10.0; python_version >= "3.5"
84 changes: 42 additions & 42 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tool.poetry]

name = "datafiles"
version = "1.4.2"
version = "1.4.3"
description = "File-based ORM for dataclasses."

license = "MIT"
Expand Down

0 comments on commit 2f8c5d4

Please sign in to comment.