Skip to content

Commit 2f8c5d4

Browse files
authored
Merge pull request #276 from jacebrowning/delete-invalid-yaml
Delete unparseable YAML files in manager methods
2 parents bae3642 + b8064e9 commit 2f8c5d4

6 files changed

Lines changed: 70 additions & 44 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Release Notes
22

3+
## 1.4.3 (2022-08-19)
4+
5+
- Fixed handling of unparseable YAML files in manager methods.
6+
37
## 1.4.2 (2022-07-29)
48

59
- Fixed exception when `Union[int, float]` or `Union[str, ...]` is used.

datafiles/manager.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import log
1414
from parse import parse
15+
from ruamel.yaml.parser import ParserError
1516

1617
from . import hooks
1718

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

4142
with hooks.disabled():
4243
instance = self.model(*args, **kwargs)
43-
instance.datafile.load()
44+
try:
45+
instance.datafile.load()
46+
except ParserError:
47+
log.critical(f"Deleting unparseable YAML: {instance.datafile.path}")
48+
instance.datafile.path.unlink()
49+
instance.datafile.load()
4450

4551
return instance
4652

datafiles/tests/test_manager.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# pylint: disable=unused-variable
22

33
import os
4+
import shutil
45
from dataclasses import dataclass
6+
from pathlib import Path
57
from typing import Optional
68
from unittest.mock import patch
79

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

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

52+
def when_file_corrupt(expect, manager):
53+
instance = manager.get_or_create(foo=2, bar=1)
54+
instance.datafile.path.write_text("{")
55+
instance = manager.get_or_none(foo=2, bar=2)
56+
expect(instance).is_(None)
57+
4958
def describe_get_or_create():
5059
@patch("datafiles.mapper.Mapper.save")
5160
@patch("datafiles.mapper.Mapper.load")
@@ -64,6 +73,12 @@ def when_file_missing(mock_save, mock_load, expect, manager):
6473
expect(mock_save.called).is_(True)
6574
expect(mock_load.called).is_(True)
6675

76+
def when_file_corrupt(expect, manager):
77+
instance = manager.get_or_create(foo=2, bar=1)
78+
instance.datafile.path.write_text("{")
79+
instance = manager.get_or_create(foo=2, bar=2)
80+
expect(instance.bar) == 2
81+
6782
def describe_all():
6883
@patch("datafiles.mapper.Mapper.exists", False)
6984
def when_no_files_exist(expect, manager):

docs/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
jinja2==3.0.3; python_version >= "3.6"
22
markdown==3.3.4; python_version >= "3.6"
33
mkdocs==1.3.1; python_version >= "3.6"
4+
jupyterlab-pygments==0.2.2; python_version >= "3.7"
45
pygments==2.10.0; python_version >= "3.5"

poetry.lock

Lines changed: 42 additions & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tool.poetry]
22

33
name = "datafiles"
4-
version = "1.4.2"
4+
version = "1.4.3"
55
description = "File-based ORM for dataclasses."
66

77
license = "MIT"

0 commit comments

Comments
 (0)