Skip to content

Commit e8c78fb

Browse files
committed
First version of the documentation
Slightly renamed typevars
1 parent d662ff4 commit e8c78fb

5 files changed

Lines changed: 89 additions & 15 deletions

File tree

docs/index.md

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44

55
[![Build Status](https://travis-ci.org/smarie/python-yamlable.svg?branch=master)](https://travis-ci.org/smarie/python-yamlable) [![Tests Status](https://smarie.github.io/python-yamlable/junit/junit-badge.svg?dummy=8484744)](https://smarie.github.io/python-yamlable/junit/report.html) [![codecov](https://codecov.io/gh/smarie/python-yamlable/branch/master/graph/badge.svg)](https://codecov.io/gh/smarie/python-yamlable) [![Documentation](https://img.shields.io/badge/docs-latest-blue.svg)](https://smarie.github.io/python-yamlable/) [![PyPI](https://img.shields.io/badge/PyPI-yamlable-blue.svg)](https://pypi.python.org/pypi/yamlable/)
66

7+
PyYaml is a great library. However it is a bit hard for anyone to add the yaml capability to their classes. Its `YamlObject` helper class is a first step but it has two drawbacks:
8+
* one has to master PyYaml Loader/Dumper internal features to understand what they are doing
9+
* there is a mandatory metaclass, which can prevent wide adoption (multiple inheritance with metaclasses...)
10+
11+
`yamlable` provides a very easy way for you to leverage PyYaml without suffering the complexity: simply inherit from `YamlAble`, decorate with `@yaml_info`, implement the abstract methods to write to / load from a dictionary, and you're set!
12+
13+
In addition `yamlable` provides
14+
* a way to creade Yaml codecs for several object types at the same time (`YamlCodec`).
15+
* an alternative to `YamlAble` that relies strictly on `YamlObject`: `YamlObject2`
716

817

918
## Installing
@@ -14,14 +23,79 @@
1423

1524
## Usage
1625

17-
TODO
26+
Let's make a class yaml-able: we have to
27+
- inherit from `YamlAble`
28+
- decorate it with the `@yaml_info` annotation to declare the associated yaml tag
29+
- implement `from_yaml_dict` (class method called during decoding) and `to_yaml_dict` (instance method called during encoding)
30+
31+
```python
32+
from yamlable import yaml_info, YamlAble
33+
34+
@yaml_info(yaml_tag_ns='com.yamlable.example')
35+
class Foo(YamlAble):
36+
37+
def __init__(self, a, b):
38+
""" Constructor """
39+
self.a = a
40+
self.b = b
41+
self.irrelevant = 37
42+
43+
def __str__(self):
44+
""" String representation for prints """
45+
return "Foo - " + str(dict(a=self.a, b=self.b))
46+
47+
def to_yaml_dict(self):
48+
""" This method is called when you call yaml.dump()"""
49+
return {'a': self.a, 'b': self.b}
50+
51+
@classmethod
52+
def from_yaml_dict(cls, dct, yaml_tag):
53+
""" This method is called when you call yaml.load()"""
54+
return Foo(dct['a'], dct['b'])
55+
```
56+
57+
That's it! Let's check that our class is correct and allows us to create instances:
58+
59+
```python
60+
>>> f = Foo(1, 'hello')
61+
>>> print(f)
62+
63+
Foo - {'a': 1, 'b': 'hello'}
64+
```
65+
66+
The object directly has the `dump_yaml` (dumping to file) / `dumps_yaml` (dumping to string) methods:
67+
68+
```python
69+
>>> print(f.dumps_yaml())
70+
71+
!yamlable/com.yamlable.example.Foo {a: 1, b: hello}
72+
```
73+
74+
The class directly has the `load_yaml` (load from file) / `loads_yaml` (load from string) methods
75+
76+
```python
77+
>>> print(Foo.loads_yaml("!yamlable/com.yamlable.example.Foo {a: 0, b: hey}"))
78+
79+
Foo - {'a': 0, 'b': 'hey'}
80+
```
81+
82+
See pyyaml help page for the various formatting arguments that you can use..
83+
84+
```python
85+
>>> print(f.dumps_yaml(default_flow_style=False))
86+
87+
!yamlable/com.yamlable.example.Foo
88+
a: 1
89+
b: hello
90+
```
1891

19-
See [Usage](./usage) for a complete example with exceptions handling and more.
92+
See [Usage](./usage) for other possibilities of `yamlable`.
2093

2194

2295
## Main features / benefits
2396

24-
* TODO
97+
* Add yaml-ability to any class easily through inheritance without metaclass (as opposed to `YamlObject`) and without knowledge of internal PyYaml loader/dumper logic.
98+
* Write codecs to support several types at a time with `YamlCodec`
2599

26100

27101
## See Also

yamlable/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from yamlable.base import AbstractYamlObject, NONE_IGNORE_CHECKS, AYO, read_yaml_node_as_dict
1+
from yamlable.base import AbstractYamlObject, NONE_IGNORE_CHECKS, Y, read_yaml_node_as_dict
22
from yamlable.main import YamlCodec, register_yamlable_codec, yaml_info_decorate, yaml_info, YamlAble, YA, \
33
AbstractYamlAble, YAMLABLE_PREFIX
4-
from yamlable.yaml_objects import YO2, YamlObject2, ABCYAMLMeta, YAMLObjectMetaclassStrict
4+
from yamlable.yaml_objects import YamlObject2, ABCYAMLMeta, YAMLObjectMetaclassStrict
55

66
__all__ = ['base',
77
'main',

yamlable/base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
pass # normal for old versions of typing
1010

1111

12-
AYO = TypeVar('AYO', bound='AbstractYamlObject')
12+
Y = TypeVar('Y', bound='AbstractYamlObject')
1313

1414

1515
class AbstractYamlObject(ABC):
@@ -30,7 +30,7 @@ def to_yaml_dict(self) -> Dict[str, Any]:
3030

3131
@classmethod
3232
@abstractmethod
33-
def from_yaml_dict(cls: 'Type[AYO]', dct: Dict, yaml_tag: str) -> AYO:
33+
def from_yaml_dict(cls: 'Type[Y]', dct: Dict[Any, Any], yaml_tag: str) -> Y:
3434
"""
3535
Implementors should transform the given dictionary (read from yaml by the pyYaml stack) into an object instance.
3636
The yaml tag associated to this object, read in the yaml document, is provided in parameter.
@@ -71,7 +71,7 @@ def dumps_yaml(self, **pyyaml_kwargs):
7171
return dump(self, **pyyaml_kwargs)
7272

7373
@classmethod
74-
def loads_yaml(cls: 'Type[AYO]', yaml_str: str) -> AYO:
74+
def loads_yaml(cls: 'Type[Y]', yaml_str: str) -> Y:
7575
"""
7676
Utility method to
7777
:param yaml_str
@@ -80,7 +80,7 @@ def loads_yaml(cls: 'Type[AYO]', yaml_str: str) -> AYO:
8080
return cls.load_yaml(StringIO(yaml_str))
8181

8282
@classmethod
83-
def load_yaml(cls: 'Type[AYO]', file_path_or_stream: Union[str, TextIOBase]) -> AYO:
83+
def load_yaml(cls: 'Type[Y]', file_path_or_stream: Union[str, TextIOBase]) -> Y:
8484
"""
8585
Parses the given file path or stream as a yaml document with the
8686

yamlable/tests/test_yamlable.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pytest
55
from yaml import dump, load
66

7-
from yamlable import YamlAble, yaml_info, AYO
7+
from yamlable import YamlAble, yaml_info, Y
88

99

1010
def test_yamlable_incomplete_description():
@@ -16,7 +16,7 @@ def to_yaml_dict(self) -> Dict[str, Any]:
1616
return copy(vars(self))
1717

1818
@classmethod
19-
def from_yaml_dict(cls: 'Type[AYO]', dct: Dict, yaml_tag: str) -> AYO:
19+
def from_yaml_dict(cls: 'Type[Y]', dct: Dict, yaml_tag: str) -> Y:
2020
return Foo(**dct)
2121

2222
# instantiate
@@ -46,7 +46,7 @@ def to_yaml_dict(self) -> Dict[str, Any]:
4646
return copy(vars(self))
4747

4848
@classmethod
49-
def from_yaml_dict(cls: 'Type[AYO]', dct: Dict, yaml_tag: str) -> AYO:
49+
def from_yaml_dict(cls: 'Type[Y]', dct: Dict, yaml_tag: str) -> Y:
5050
return Foo(**dct)
5151

5252
# instantiate
@@ -84,7 +84,7 @@ def to_yaml_dict(self) -> Dict[str, Any]:
8484
return copy(vars(self))
8585

8686
@classmethod
87-
def from_yaml_dict(cls: 'Type[AYO]', dct: Dict, yaml_tag: str) -> AYO:
87+
def from_yaml_dict(cls: 'Type[Y]', dct: Dict, yaml_tag: str) -> Y:
8888
return Foo_Err(**dct)
8989

9090
@classmethod

yamlable/tests/test_yamlobjects.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import pytest
55

6-
from yamlable import YamlObject2, AYO
6+
from yamlable import YamlObject2, Y
77

88

99
def test_yamlobject_incomplete_description():
@@ -33,7 +33,7 @@ def to_yaml_dict(self) -> Dict[str, Any]:
3333
return copy(vars(self))
3434

3535
@classmethod
36-
def from_yaml_dict(cls: 'Type[AYO]', dct: Dict, yaml_tag: str) -> AYO:
36+
def from_yaml_dict(cls: 'Type[Y]', dct: Dict, yaml_tag: str) -> Y:
3737
return Foo(**dct)
3838

3939
# instantiate

0 commit comments

Comments
 (0)