Skip to content

Commit

Permalink
Use item name ask PK in demo
Browse files Browse the repository at this point in the history
  • Loading branch information
jacebrowning committed Dec 20, 2018
1 parent d6d0334 commit accdbd0
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 124 deletions.
17 changes: 7 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ and decorate it with a directory pattern to synchronize instances:
from dataclasses import dataclass
from datafiles import sync

@sync("inventory/items/{self.pk}.yml")
@sync("inventory/items/{self.name}.yml")
@dataclass
class InventoryItem:
"""Class for keeping track of an item in inventory."""

pk: int

name: str
unit_price: float
quantity_on_hand: int = 0
Expand All @@ -49,13 +47,12 @@ class InventoryItem:
Then, work with instances of the class as normal:

```python
>>> item = InventoryItem(123, "Widget", 3)
>>> item = InventoryItem("widget", 3)
```

```yaml
# inventory/items/123.yml
# inventory/items/widget.yml

name: Widget
unit_price: 3.0
```

Expand All @@ -66,19 +63,17 @@ Changes to the object are automatically saved to the filesystem:
```

```yaml
# inventory/items/123.yml
# inventory/items/widget.yml

name: Widget
unit_price: 3.0
quantity_on_hand: 100
```

Changes to the filesystem are automatically reflected in the object:

```yaml
# inventory/items/123.yml
# inventory/items/widget.yml

name: Widget
unit_price: 2.5 # was 3.0
quantity_on_hand: 100
```
Expand All @@ -88,6 +83,8 @@ quantity_on_hand: 100
2.5
```

Demo: [Jupyter Notebook](https://github.com/jacebrowning/datafiles/blob/develop/notebooks/readme.ipynb)

## Installation

Because datafiles relies on dataclasses and type annotations, Python 3.7+ is required. Install it directly into an activated virtual environment:
Expand Down
14 changes: 7 additions & 7 deletions datafiles/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,17 @@ def _get_text(self, **kwargs):
extension = self.path.suffix if self.path else '.yml'
data = self._get_data(**kwargs)
text = formats.serialize(data, extension)
log.info(f'Serialized data to text ({extension}): {text!r}')
log.debug(f'Serialized data to text ({extension}): {text!r}')
return text

@prevent_recursion
def load(self, *, first_load=False) -> None:
log.info(f'Loading values for {self._instance.__class__} instance')
log.debug(f'Loading values for {self._instance.__class__} instance')

if not self.path:
raise RuntimeError("'pattern' must be set to load the model")

message = f'Deserializing: {self.relpath}'
message = f'Reading file: {self.relpath}'
frame = '=' * len(message)
log.info(message)
data = formats.deserialize(self.path, self.path.suffix)
Expand All @@ -167,7 +167,7 @@ def load(self, *, first_load=False) -> None:
else:
self._set_attribute_value(data, name, converter, first_load)

log.info(f'Loaded values for object: {self._instance}')
log.info(f'Loaded object: {self._instance}')

def _set_dataclass_value(self, data, name, converter, first_load):
# TODO: Support nesting unlimited levels
Expand Down Expand Up @@ -232,7 +232,7 @@ def _set_attribute_value(self, data, name, converter, first_load):
else:
value = converter.to_python_value(file_value, target=init_value)

log.info(f"Setting '{name}' value: {value!r}")
log.debug(f"Setting '{name}' value: {value!r}")
setattr(self._instance, name, value)

def _get_default_field_value(self, name):
Expand All @@ -251,7 +251,7 @@ def _get_default_field_value(self, name):

@prevent_recursion
def save(self, include_default_values: Trilean = None) -> None:
log.info(f'Saving data for object: {self._instance}')
log.info(f'Saving object: {self._instance}')

if not self.path:
raise RuntimeError(f"'pattern' must be set to save the model")
Expand All @@ -260,7 +260,7 @@ def save(self, include_default_values: Trilean = None) -> None:

self.path.parent.mkdir(parents=True, exist_ok=True)

message = f'Writing: {self.relpath}'
message = f'Writing file: {self.relpath}'
frame = '=' * len(message)
log.info(message)
log.debug(frame + '\n\n' + (text or '<nothing>\n'))
Expand Down
60 changes: 24 additions & 36 deletions notebooks/format_options.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Serialized data to text (.json): '{\\n \"my_dict\": {\\n \"value\": 0\\n },\\n \"my_list\": [\\n {\\n \"value\": 1\\n },\\n {\\n \"value\": 2\\n }\\n ],\\n \"my_bool\": true,\\n \"my_float\": 1.23,\\n \"my_int\": 42,\\n \"my_str\": \"Hello, world!\",\\n \"fmt\": \"JavaScript Object Notation\"\\n}'\n",
"INFO: datafiles.managers: Writing: files/format_options.json\n"
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Writing file: files/format_options.json\n"
]
}
],
Expand Down Expand Up @@ -120,18 +119,14 @@
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Serialized data to text (.json): '{\\n \"my_dict\": {\\n \"value\": 0\\n },\\n \"my_list\": [\\n {\\n \"value\": 1\\n },\\n {\\n \"value\": 2\\n }\\n ],\\n \"my_bool\": true,\\n \"my_float\": 1.23,\\n \"my_int\": 42,\\n \"my_str\": \"Hello, world!\",\\n \"fmt\": \"JavaScript Object Notation\"\\n}'\n",
"INFO: datafiles.managers: Writing: files/format_options.json\n",
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Serialized data to text (.json): '{\\n \"my_dict\": {\\n \"value\": 0\\n },\\n \"my_list\": [\\n {\\n \"value\": 1\\n },\\n {\\n \"value\": 2\\n }\\n ],\\n \"my_bool\": true,\\n \"my_float\": 1.23,\\n \"my_int\": 42,\\n \"my_str\": \"Hello, world!\",\\n \"fmt\": \"JavaScript Object Notation\"\\n}'\n",
"INFO: datafiles.managers: Writing: files/format_options.json\n",
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Serialized data to text (.json): '{\\n \"my_dict\": {\\n \"value\": 0\\n },\\n \"my_list\": [\\n {\\n \"value\": 1\\n },\\n {\\n \"value\": 2\\n }\\n ],\\n \"my_bool\": true,\\n \"my_float\": 1.23,\\n \"my_int\": 42,\\n \"my_str\": \"Hello, world!\",\\n \"fmt\": \"JavaScript Object Notation\"\\n}'\n",
"INFO: datafiles.managers: Writing: files/format_options.json\n",
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt=\"Tom's Obvious Minimal Language\")\n",
"INFO: datafiles.managers: Serialized data to text (.toml): 'fmt = \"Tom\\'s Obvious Minimal Language\"\\nmy_bool = true\\nmy_float = 1.23\\nmy_int = 42\\nmy_str = \"Hello, world!\"\\n\\n[[my_list]]\\nvalue = 1\\n\\n[[my_list]]\\nvalue = 2\\n\\n[my_dict]\\nvalue = 0\\n'\n",
"INFO: datafiles.managers: Writing: files/format_options.toml\n"
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Writing file: files/format_options.json\n",
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Writing file: files/format_options.json\n",
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Writing file: files/format_options.json\n",
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt=\"Tom's Obvious Minimal Language\")\n",
"INFO: datafiles.managers: Writing file: files/format_options.toml\n"
]
}
],
Expand Down Expand Up @@ -195,27 +190,20 @@
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Serialized data to text (.json): '{\\n \"my_dict\": {\\n \"value\": 0\\n },\\n \"my_list\": [\\n {\\n \"value\": 1\\n },\\n {\\n \"value\": 2\\n }\\n ],\\n \"my_bool\": true,\\n \"my_float\": 1.23,\\n \"my_int\": 42,\\n \"my_str\": \"Hello, world!\",\\n \"fmt\": \"JavaScript Object Notation\"\\n}'\n",
"INFO: datafiles.managers: Writing: files/format_options.json\n",
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt=\"Tom's Obvious Minimal Language\")\n",
"INFO: datafiles.managers: Serialized data to text (.toml): 'fmt = \"Tom\\'s Obvious Minimal Language\"\\nmy_bool = true\\nmy_float = 1.23\\nmy_int = 42\\nmy_str = \"Hello, world!\"\\n\\n[[my_list]]\\nvalue = 1\\n\\n[[my_list]]\\nvalue = 2\\n\\n[my_dict]\\nvalue = 0\\n'\n",
"INFO: datafiles.managers: Writing: files/format_options.toml\n",
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Serialized data to text (.json): '{\\n \"my_dict\": {\\n \"value\": 0\\n },\\n \"my_list\": [\\n {\\n \"value\": 1\\n },\\n {\\n \"value\": 2\\n }\\n ],\\n \"my_bool\": true,\\n \"my_float\": 1.23,\\n \"my_int\": 42,\\n \"my_str\": \"Hello, world!\",\\n \"fmt\": \"JavaScript Object Notation\"\\n}'\n",
"INFO: datafiles.managers: Writing: files/format_options.json\n",
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt=\"Tom's Obvious Minimal Language\")\n",
"INFO: datafiles.managers: Serialized data to text (.toml): 'fmt = \"Tom\\'s Obvious Minimal Language\"\\nmy_bool = true\\nmy_float = 1.23\\nmy_int = 42\\nmy_str = \"Hello, world!\"\\n\\n[[my_list]]\\nvalue = 1\\n\\n[[my_list]]\\nvalue = 2\\n\\n[my_dict]\\nvalue = 0\\n'\n",
"INFO: datafiles.managers: Writing: files/format_options.toml\n",
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Serialized data to text (.json): '{\\n \"my_dict\": {\\n \"value\": 0\\n },\\n \"my_list\": [\\n {\\n \"value\": 1\\n },\\n {\\n \"value\": 2\\n }\\n ],\\n \"my_bool\": true,\\n \"my_float\": 1.23,\\n \"my_int\": 42,\\n \"my_str\": \"Hello, world!\",\\n \"fmt\": \"JavaScript Object Notation\"\\n}'\n",
"INFO: datafiles.managers: Writing: files/format_options.json\n",
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt=\"Tom's Obvious Minimal Language\")\n",
"INFO: datafiles.managers: Serialized data to text (.toml): 'fmt = \"Tom\\'s Obvious Minimal Language\"\\nmy_bool = true\\nmy_float = 1.23\\nmy_int = 42\\nmy_str = \"Hello, world!\"\\n\\n[[my_list]]\\nvalue = 1\\n\\n[[my_list]]\\nvalue = 2\\n\\n[my_dict]\\nvalue = 0\\n'\n",
"INFO: datafiles.managers: Writing: files/format_options.toml\n",
"INFO: datafiles.managers: Saving data for object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt=\"YAML Ain't Markup Language\")\n",
"INFO: datafiles.managers: Serialized data to text (.yml): \"my_dict:\\n value: 0\\nmy_list:\\n- value: 1\\n- value: 2\\nmy_bool: true\\nmy_float: 1.23\\nmy_int: 42\\nmy_str: Hello, world!\\nfmt: YAML Ain't Markup Language\\n\"\n",
"INFO: datafiles.managers: Writing: files/format_options.yml\n"
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Writing file: files/format_options.json\n",
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt=\"Tom's Obvious Minimal Language\")\n",
"INFO: datafiles.managers: Writing file: files/format_options.toml\n",
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Writing file: files/format_options.json\n",
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt=\"Tom's Obvious Minimal Language\")\n",
"INFO: datafiles.managers: Writing file: files/format_options.toml\n",
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt='JavaScript Object Notation')\n",
"INFO: datafiles.managers: Writing file: files/format_options.json\n",
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt=\"Tom's Obvious Minimal Language\")\n",
"INFO: datafiles.managers: Writing file: files/format_options.toml\n",
"INFO: datafiles.managers: Saving object: Sample(my_dict=Nested(value=0), my_list=[Nested(value=1), Nested(value=2)], my_bool=True, my_float=1.23, my_int=42, my_str='Hello, world!', fmt=\"YAML Ain't Markup Language\")\n",
"INFO: datafiles.managers: Writing file: files/format_options.yml\n"
]
}
],
Expand Down
16 changes: 6 additions & 10 deletions notebooks/nested_dataclass.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: datafiles.managers: Loading values for <class '__main__.Sample'> instance\n",
"INFO: datafiles.managers: Deserializing: files/nested_dataclass.yml\n",
"INFO: datafiles.managers: Loaded values for object: Sample(foo=42, bar=Nested(alpha=1, beta=0))\n"
"INFO: datafiles.managers: Reading file: files/nested_dataclass.yml\n",
"INFO: datafiles.managers: Loaded object: Sample(foo=42, bar=Nested(alpha=1, beta=0))\n"
]
}
],
Expand Down Expand Up @@ -104,13 +103,10 @@
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: datafiles.managers: Loading values for <class '__main__.Sample'> instance\n",
"INFO: datafiles.managers: Deserializing: files/nested_dataclass.yml\n",
"INFO: datafiles.managers: Setting 'foo' value: 42\n",
"INFO: datafiles.managers: Loaded values for object: Sample(foo=42, bar=Nested(alpha=True, beta=True))\n",
"INFO: datafiles.managers: Saving data for object: Sample(foo=42, bar=Nested(alpha=True, beta=1))\n",
"INFO: datafiles.managers: Serialized data to text (.yml): 'foo: 42\\nbar:\\n alpha: true\\n beta: true\\n'\n",
"INFO: datafiles.managers: Writing: files/nested_dataclass.yml\n"
"INFO: datafiles.managers: Reading file: files/nested_dataclass.yml\n",
"INFO: datafiles.managers: Loaded object: Sample(foo=42, bar=Nested(alpha=True, beta=True))\n",
"INFO: datafiles.managers: Saving object: Sample(foo=42, bar=Nested(alpha=True, beta=1))\n",
"INFO: datafiles.managers: Writing file: files/nested_dataclass.yml\n"
]
}
],
Expand Down

0 comments on commit accdbd0

Please sign in to comment.