Skip to content

Commit

Permalink
Merge 688716f into 49f5bd5
Browse files Browse the repository at this point in the history
  • Loading branch information
jacebrowning committed Feb 16, 2019
2 parents 49f5bd5 + 688716f commit 460ae7f
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 18 deletions.
2 changes: 1 addition & 1 deletion datafiles/converters/__init__.py
Expand Up @@ -57,7 +57,7 @@ def map_type(cls, *, name: str = '', item_cls: Optional[type] = None):
else:
converter = List.subclass(converter)

if cls.__origin__ == dict:
elif cls.__origin__ == dict:
if item_cls:
key = map_type(str)
value = map_type(item_cls)
Expand Down
8 changes: 3 additions & 5 deletions datafiles/managers.py
Expand Up @@ -11,7 +11,7 @@

from . import formats, hooks
from .converters import Converter, List, map_type
from .utils import prettify
from .utils import prettify, recursive_update


Trilean = Optional[bool]
Expand Down Expand Up @@ -124,11 +124,9 @@ def _get_data(self, include_default_values: Trilean = None) -> Dict:
include_default_values = self.defaults

if self.auto_attr:
self._last_data.update(self._instance.__dict__)
data = recursive_update(self._last_data, self._instance.__dict__)
else:
self._last_data.update(dataclasses.asdict(self._instance))

data = self._last_data
data = recursive_update(self._last_data, dataclasses.asdict(self._instance))

for name in list(data.keys()):
if name not in self.attrs:
Expand Down
51 changes: 51 additions & 0 deletions datafiles/tests/test_utils.py
@@ -0,0 +1,51 @@
# pylint: disable=unused-variable

from datafiles.utils import recursive_update


def describe_recursive_update():
def it_preserves_root_id(expect):
old = {} # type: ignore
new = {'a': 1}
id_ = id(old)

old = recursive_update(old, new)

expect(old) == new
expect(id(old)) == id_

def it_preserves_nested_dict_id(expect):
old = {'a': {'b': 1}}
new = {'a': {'b': 2}}
id_ = id(old['a'])

old = recursive_update(old, new)

expect(old) == new
expect(id(old['a'])) == id_

def it_preserves_nested_list_id(expect):
old = {'a': [1]}
new = {'a': [2]}
id_ = id(old['a'])

old = recursive_update(old, new)

expect(old) == new
expect(id(old['a'])) == id_

def it_adds_missing_dict(expect):
old = {} # type: ignore
new = {'a': {'b': 2}}

old = recursive_update(old, new)

expect(old) == new

def it_adds_missing_list(expect):
old = {} # type: ignore
new = {'a': [1]}

old = recursive_update(old, new)

expect(old) == new
20 changes: 20 additions & 0 deletions datafiles/utils.py
Expand Up @@ -22,3 +22,23 @@ def dictify(value: Any) -> Dict:
return [dictify(x) for x in value]

return value


def recursive_update(old: Dict, new: Dict):
"""Recursively update a dictionary."""

for key, value in new.items():
if isinstance(value, dict):
if key in old:
recursive_update(old[key], value)
else:
old[key] = value
elif isinstance(value, list):
if key in old:
old[key][:] = value
else:
old[key] = value
else:
old[key] = value

return old
10 changes: 2 additions & 8 deletions notebooks/file_inference.ipynb
Expand Up @@ -100,16 +100,10 @@
"text": [
"language: python\n",
"matrix:\n",
" include:\n",
" - python: 3.7\n",
" dist: xenial\n",
" sudo: true\n",
"\n",
" include: []\n",
"cache:\n",
" pip: true\n",
" directories:\n",
" - ${VIRTUAL_ENV}\n",
"\n",
" directories: []\n",
"before_install:\n",
"- curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py\n",
" | python\n",
Expand Down
31 changes: 27 additions & 4 deletions tests/test_file_inference.py
@@ -1,7 +1,10 @@
import pytest

from datafiles import auto


def test_auto(write, logbreak, expect):
@pytest.mark.xfail(reason='https://bitbucket.org/ruamel/yaml/issues/73')
def test_auto_with_sample_file(write, logbreak, expect, read, dedent):

write(
'tmp/sample.yml',
Expand All @@ -28,7 +31,27 @@ def test_auto(write, logbreak, expect):
expect(sample.heterogeneous_list) == [1, 'abc']
expect(sample.empty_list) == []

logbreak("Updating attribute")
sample.homogeneous_list.append(3.4)
sample.heterogeneous_list.append(5.6)
sample.empty_list.append(7.8)

logbreak("Reading file")
expect(read('tmp/sample.yml')) == dedent(
"""
homogeneous_list:
- 1
- 2
- 3
def test_auto_travis(expect):
travis = auto('.travis.yml')
expect(travis.language) == 'python'
heterogeneous_list:
- 1
- abc
- 5.6
empty_list:
- 7.8
"""
)

0 comments on commit 460ae7f

Please sign in to comment.