summaryrefslogtreecommitdiff
path: root/_doc/dumpcls.ryd
blob: 8e9ac6e71086d87bc00b100525c827813c93a833 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
version: 0.2
text: rst
fix_inline_single_backquotes: true
pdf: true
# code_directory: ../_example
--- |

**********************
Dumping Python classes
**********************

Only ``yaml = YAML(typ='unsafe')`` loads and dumps Python objects out-of-the-box. And
since it loads **any** Python object, this can be unsafe.

If you have instances of some class(es) that you want to dump or load, it is
easy to allow the YAML instance to do that explicitly. You can either register the
class with the ``YAML`` instance or decorate the class.

Registering is done with ``YAML.register_class()``:

--- !python |

import sys
import ruamel.yaml


class User(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age


yaml = ruamel.yaml.YAML()
yaml.register_class(User)
yaml.dump([User('Anthon', 18)], sys.stdout)
--- !stdout |
which gives as output::
--- |
The tag ``!User`` originates from the name of the class.

You can specify a different tag by adding the attribute ``yaml_tag``, and
explicitly specify dump and/or load *classmethods* which have to be called
``to_yaml`` resp. ``from_yaml``:

--- !python |
import sys
import ruamel.yaml


class User:
    yaml_tag = u'!user'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(cls.yaml_tag,
                                            u'{.name}-{.age}'.format(node, node))

    @classmethod
    def from_yaml(cls, constructor, node):
        return cls(*node.value.split('-'))


yaml = ruamel.yaml.YAML()
yaml.register_class(User)
yaml.dump([User('Anthon', 18)], sys.stdout)
--- !stdout |
which gives as output::

--- |

When using the decorator, which takes the ``YAML()`` instance as a parameter,
the ``yaml = YAML()`` line needs to be moved up in the file:

--- !python |
import sys
from ruamel.yaml import YAML, yaml_object

yaml = YAML()


@yaml_object(yaml)
class User:
    yaml_tag = u'!user'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(cls.yaml_tag,
                                            u'{.name}-{.age}'.format(node, node))

    @classmethod
    def from_yaml(cls, constructor, node):
        return cls(*node.value.split('-'))


yaml.dump([User('Anthon', 18)], sys.stdout)

--- |
The ``yaml_tag``, ``from_yaml`` and ``to_yaml`` work in the same way as when using
``.register_class()``.