import yaml
import numpy as np
# CLoader and CDumper do not support custom serialisation logic.
# *DO NOT USE* CDumper
from yaml import Loader, Dumper
_NUMPY_ARRAY_TAG = '!nparray'
#-- Special dump functions --------------------------------------------------------------------------------------------
[docs]class SerialisableObject(yaml.YAMLObject):
@classmethod
[docs] def from_yaml(cls, loader, node):
mapping = loader.construct_mapping(node, deep=True)
return cls(**mapping)
[docs] def to_file(self, filename_or_file_object):
"""
Save the object to the file, specified by filename `file_` or the buffer provided in `file_`
:param filename_or_file_object: filename of the file to save the object to, or already open file buffer
"""
to_file(self, filename_or_file_object)
@classmethod
[docs] def from_file(cls, filename_or_file_object):
"""
Create new instance of the object from the file.
:param filename_or_file_object: the filename of the file to read from or already opened file buffer
:type filename_or_file_object: basestring|file
"""
object_ = from_file(filename_or_file_object)
if not isinstance(object_, cls):
raise ValueError('Expected to read {0!r} object, but got {1!r} instead'.format(cls, type(object_)))
return object_
[docs]class MeansDumper(Dumper):
def __init__(self, stream, default_style=None, default_flow_style=None, canonical=None, indent=None, width=None,
allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None,
version=None, tags=None):
super(MeansDumper, self).__init__(stream, default_style, default_flow_style, canonical, indent, width,
allow_unicode, line_break, encoding, explicit_start, explicit_end, version,
tags)
self.add_representer(np.ndarray, _ndarray_representer)
self.add_multi_representer(np.float, _numpy_float_representer)
[docs]class MeansLoader(Loader):
def __init__(self, stream):
super(MeansLoader, self).__init__(stream)
self.add_constructor(_NUMPY_ARRAY_TAG, _generic_constructor(np.array))
[docs]def dump(object_):
return yaml.dump(object_, Dumper=MeansDumper)
[docs]def load(data):
return yaml.load(data, Loader=MeansLoader)
[docs]def to_file(data, filename_or_file_object):
"""
Write ``data`` to a file specified by either filename of the file or an opened :class:`file` buffer.
:param data: Object to write to file
:param filename_or_file_object: filename/or opened file buffer to write to
:type filename_or_file_object: basestring|file
"""
if isinstance(filename_or_file_object, basestring):
file_ = open(filename_or_file_object, 'w')
we_opened = True
else:
file_ = filename_or_file_object
we_opened = False
try:
file_.write(dump(data))
finally:
if we_opened:
file_.close()
[docs]def from_file(filename_or_file_object):
"""
Read data from the specified file.
:param filename_or_file_object: filename of the file or an opened :class:`file` buffer to that file
:type filename_or_file_object: basestring|file
:return:
"""
if isinstance(filename_or_file_object, basestring):
file_ = open(filename_or_file_object, 'r')
we_opened = True
else:
we_opened = False
file_ = filename_or_file_object
try:
data = load(file_.read())
finally:
if we_opened:
file_.close()
return data
#-- Generic constructor ------------------------------
def _generic_constructor(class_):
def f(loader, node):
mapping = loader.construct_mapping(node, deep=True)
return class_(**mapping)
return f
#-- Representers/Constructors for numpy objects ------------------------------------------------------------------------
def _ndarray_representer(dumper, data):
"""
:param dumper:
:param data:
:type data: :class:`numpy.ndarray`
:return:
"""
mapping = [('object', data.tolist()), ('dtype', data.dtype.name)]
return dumper.represent_mapping(_NUMPY_ARRAY_TAG, mapping)
def _numpy_float_representer(dumper, data):
"""
Get rid of the annoying representations of simple numbers, ie::
!!python/object/apply:numpy.core.multiarray.scalar
- !!python/object/apply:numpy.dtype
args: [f8, 0, 1]
state: !!python/tuple [3, <, null, null, null, -1, -1, 0]
- !!binary |
/Knx0k1iQD8=
:param dumper:
:param data:
:return:
"""
return dumper.represent_data(float(data))