Source code for inginious.common.custom_yaml

# -*- coding: utf-8 -*-
#
# This file is part of INGInious. See the LICENSE and the COPYRIGHTS files for
# more information about the licensing of this file.

""" A custom YAML based on PyYAML, that provides Ordered Dicts """
# Most ideas for this implementation comes from http://stackoverflow.com/questions/5121931/in-python-how-can-you-load-yaml-mappings-as-ordereddicts
from collections import OrderedDict

import yaml as original_yaml
try:
    from yaml import CSafeLoader as SafeLoader
    from yaml import CSafeDumper as SafeDumper
except ImportError:
    from yaml import SafeLoader, SafeDumper

[docs]def load(stream): """ Parse the first YAML document in a stream and produce the corresponding Python object. Use OrderedDicts to produce dicts. Safe version. """ class OrderedLoader(SafeLoader): pass def construct_mapping(loader, node): loader.flatten_mapping(node) return OrderedDict(loader.construct_pairs(node)) OrderedLoader.add_constructor( original_yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping) return original_yaml.load(stream, OrderedLoader)
[docs]def dump(data, stream=None, **kwds): """ Serialize a Python object into a YAML stream. If stream is None, return the produced string instead. Dict keys are produced in the order in which they appear in OrderedDicts. Safe version. If objects are not "conventional" objects, they will be dumped converted to string with the str() function. They will then not be recovered when loading with the load() function. """ # Display OrderedDicts correctly class OrderedDumper(SafeDumper): pass def _dict_representer(dumper, data): return dumper.represent_mapping( original_yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, list(data.items())) # Display long strings correctly def _long_str_representer(dumper, data): if data.find("\n") != -1: # Drop some unneeded data # \t are forbidden in YAML data = data.replace("\t", " ") # empty spaces at end of line are always useless in INGInious, and forbidden in YAML data = "\n".join([p.rstrip() for p in data.split("\n")]) return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|') else: return dumper.represent_scalar('tag:yaml.org,2002:str', data) # Default representation for some odd objects def _default_representer(dumper, data): return _long_str_representer(dumper, str(data)) OrderedDumper.add_representer(str, _long_str_representer) OrderedDumper.add_representer(str, _long_str_representer) OrderedDumper.add_representer(OrderedDict, _dict_representer) OrderedDumper.add_representer(None, _default_representer) s = original_yaml.dump(data, stream, OrderedDumper, encoding='utf-8', allow_unicode=True, default_flow_style=False, indent=4, **kwds) if s is not None: return s.decode('utf-8') else: return