Mercurial > hgrepos > Python > libs > ConfigMix
comparison configmix/yaml.py @ 5:dc058099a4cb
Renamed the project from "MixConfig" to "ConfigMix"
| author | Franz Glasner <hg@dom66.de> |
|---|---|
| date | Tue, 08 Mar 2016 20:11:17 +0100 |
| parents | mixconfig/yaml.py@bedc4f95b9e9 |
| children | ce290b10dac5 |
comparison
equal
deleted
inserted
replaced
| 4:f76d85ccc5b9 | 5:dc058099a4cb |
|---|---|
| 1 # -*- coding: utf-8 -*- | |
| 2 r"""Simple wrapper for yaml to support all-unicode strings when loading | |
| 3 configuration files. | |
| 4 | |
| 5 """ | |
| 6 | |
| 7 from __future__ import division, print_function, absolute_import | |
| 8 | |
| 9 try: | |
| 10 from collections import OrderedDict | |
| 11 except ImportError: | |
| 12 try: | |
| 13 from ordereddict import OrderedDict | |
| 14 except ImportError: | |
| 15 OrderedDict = None | |
| 16 import yaml | |
| 17 import yaml.constructor | |
| 18 | |
| 19 | |
| 20 __all__ = ["safe_load", "safe_load_all", "load", "load_all"] | |
| 21 | |
| 22 | |
| 23 class ConfigLoader(yaml.Loader): | |
| 24 | |
| 25 """A YAML loader, which makes all !!str strings to Unicode. Standard | |
| 26 PyYAML does this only in the non-ASCII case. | |
| 27 | |
| 28 If an `OrderedDict` implementation is available then all "map" and | |
| 29 "omap" nodes are constructed as `OrderedDict`. | |
| 30 This is against YAML specs but within configuration files it seems | |
| 31 more natural. | |
| 32 | |
| 33 """ | |
| 34 | |
| 35 def construct_yaml_str(self, node): | |
| 36 return self.construct_scalar(node) | |
| 37 | |
| 38 if OrderedDict: | |
| 39 | |
| 40 # | |
| 41 # From https://pypi.python.org/pypi/yamlordereddictloader/0.1.1 | |
| 42 # (MIT License) | |
| 43 # | |
| 44 | |
| 45 def construct_yaml_map(self, node): | |
| 46 data = OrderedDict() | |
| 47 yield data | |
| 48 value = self.construct_mapping(node) | |
| 49 data.update(value) | |
| 50 | |
| 51 def construct_mapping(self, node, deep=False): | |
| 52 if isinstance(node, yaml.MappingNode): | |
| 53 self.flatten_mapping(node) | |
| 54 else: | |
| 55 raise yaml.constructor.ConstructorError(None, None, | |
| 56 'expected a mapping node, but found %s' % node.id, | |
| 57 node.start_mark) | |
| 58 | |
| 59 mapping = OrderedDict() | |
| 60 for key_node, value_node in node.value: | |
| 61 key = self.construct_object(key_node, deep=deep) | |
| 62 try: | |
| 63 hash(key) | |
| 64 except TypeError as err: | |
| 65 raise yaml.constructor.ConstructorError( | |
| 66 'while constructing a mapping', node.start_mark, | |
| 67 'found unacceptable key (%s)' % err, key_node.start_mark) | |
| 68 value = self.construct_object(value_node, deep=deep) | |
| 69 mapping[key] = value | |
| 70 return mapping | |
| 71 | |
| 72 | |
| 73 ConfigLoader.add_constructor( | |
| 74 "tag:yaml.org,2002:str", | |
| 75 ConfigLoader.construct_yaml_str) | |
| 76 if OrderedDict: | |
| 77 ConfigLoader.add_constructor( | |
| 78 "tag:yaml.org,2002:map", | |
| 79 ConfigLoader.construct_yaml_map) | |
| 80 ConfigLoader.add_constructor( | |
| 81 "tag:yaml.org,2002:omap", | |
| 82 ConfigLoader.construct_yaml_map) | |
| 83 | |
| 84 | |
| 85 class ConfigSafeLoader(yaml.SafeLoader): | |
| 86 | |
| 87 """A safe YAML loader, which makes all !!str strings to Unicode. | |
| 88 Standard PyYAML does this only in the non-ASCII case. | |
| 89 | |
| 90 If an `OrderedDict` implementation is available then all "map" and | |
| 91 "omap" nodes are constructed as `OrderedDict`. | |
| 92 This is against YAML specs but within configuration files it seems | |
| 93 more natural. | |
| 94 | |
| 95 """ | |
| 96 | |
| 97 def construct_yaml_str(self, node): | |
| 98 return self.construct_scalar(node) | |
| 99 | |
| 100 if OrderedDict: | |
| 101 | |
| 102 # | |
| 103 # From https://pypi.python.org/pypi/yamlordereddictloader/0.1.1 | |
| 104 # (MIT License) | |
| 105 # | |
| 106 | |
| 107 def construct_yaml_map(self, node): | |
| 108 data = OrderedDict() | |
| 109 yield data | |
| 110 value = self.construct_mapping(node) | |
| 111 data.update(value) | |
| 112 | |
| 113 def construct_mapping(self, node, deep=False): | |
| 114 if isinstance(node, yaml.MappingNode): | |
| 115 self.flatten_mapping(node) | |
| 116 else: | |
| 117 raise yaml.constructor.ConstructorError(None, None, | |
| 118 'expected a mapping node, but found %s' % node.id, | |
| 119 node.start_mark) | |
| 120 | |
| 121 mapping = OrderedDict() | |
| 122 for key_node, value_node in node.value: | |
| 123 key = self.construct_object(key_node, deep=deep) | |
| 124 try: | |
| 125 hash(key) | |
| 126 except TypeError as err: | |
| 127 raise yaml.constructor.ConstructorError( | |
| 128 'while constructing a mapping', node.start_mark, | |
| 129 'found unacceptable key (%s)' % err, key_node.start_mark) | |
| 130 value = self.construct_object(value_node, deep=deep) | |
| 131 mapping[key] = value | |
| 132 return mapping | |
| 133 | |
| 134 | |
| 135 ConfigSafeLoader.add_constructor( | |
| 136 "tag:yaml.org,2002:str", | |
| 137 ConfigSafeLoader.construct_yaml_str) | |
| 138 if OrderedDict: | |
| 139 ConfigSafeLoader.add_constructor( | |
| 140 "tag:yaml.org,2002:map", | |
| 141 ConfigSafeLoader.construct_yaml_map) | |
| 142 ConfigSafeLoader.add_constructor( | |
| 143 "tag:yaml.org,2002:omap", | |
| 144 ConfigSafeLoader.construct_yaml_map) | |
| 145 | |
| 146 | |
| 147 def load(stream, Loader=ConfigLoader): | |
| 148 return yaml.load(stream, Loader) | |
| 149 | |
| 150 | |
| 151 def load_all(stream, Loader=ConfigLoader): | |
| 152 return yaml.load_all(stream, Loader) | |
| 153 | |
| 154 | |
| 155 def safe_load(stream): | |
| 156 return yaml.load(stream, Loader=ConfigSafeLoader) | |
| 157 | |
| 158 | |
| 159 def safe_load_all(stream): | |
| 160 return yaml.load_all(stream, Loader=ConfigSafeLoader) |
