The Python Oracle

Formatting custom class output in PyYAML

Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzling Curiosities

--

Chapters
00:00 Question
01:01 Accepted answer (Score 16)
02:56 Thank you

--

Full question
https://stackoverflow.com/questions/2674...

Accepted answer links:
[PyYAML 'representers' and 'constructors']: http://pyyaml.org/wiki/PyYAMLDocumentati...
[Docs for YAMLObject]: http://pyyaml.org/wiki/PyYAMLDocumentati...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #yaml #pyyaml

#avk47



ACCEPTED ANSWER

Score 18


Redefine time format for all times in a document

You can define your own serialization format for any datetime.time instances in your documents using PyYAML 'representers' and 'constructors'.

import datetime

import yaml

time_format = '%H:%M:%S'


def time_representer(dumper, data):
    return dumper.represent_scalar(u'!time', data.strftime(time_format))


def time_constructor(loader, node):
    value = loader.construct_scalar(node)
    return datetime.datetime.strptime(value, time_format).time()


yaml.add_representer(datetime.time, time_representer)
yaml.add_constructor(u'!time', time_constructor)


class A(yaml.YAMLObject):
    yaml_tag = u'!A'

    def __init__(self, val):
        self.val = val


if __name__ == '__main__':
    t = datetime.time()
    a = A(t)
    print yaml.dump(a, default_flow_style=False)
    print yaml.load(yaml.dump(a)).val == t

Will output:

!A
val: !time '00:00:00'

True

Redefine time format only for a particular class

You can also define how to a particular class serializes and deserializes. This way you can just change how time is represented for A only. Docs for YAMLObject

import datetime

import yaml

time_format = '%H:%M:%S'

class A(yaml.YAMLObject):
    yaml_tag = u'!A'

    def __init__(self, val):
        self.val = val

    @classmethod
    def to_yaml(cls, dumper, data):
        dict_representation = {
            'val':data.val.strftime(time_format)
        }
        node = dumper.represent_mapping(u'!A', dict_representation)
        return node

    @classmethod
    def from_yaml(cls, loader, node):
        dict_representation = loader.construct_mapping(node)
        val = datetime.datetime.strptime(
            dict_representation['val'], time_format).time()
        return A(val)

if __name__ == '__main__':
    t = datetime.time()
    a = A(t)
    print yaml.dump([t,a], default_flow_style=False)

    loaded = yaml.load(yaml.dump([t,a]))
    print loaded[0] == t
    print loaded[1].val == t

Will output:

- !!python/object/apply:datetime.time
  - "\0\0\0\0\0\0"
- !A
  val: 00:00:00

True
True