Skip to content

Commit cd6058e

Browse files
author
Thomas Rabaix
committed
Fix issue with ordering information when loading data from yaml source
1 parent 0dea57a commit cd6058e

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

ioc/loader.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# vim: set fileencoding=utf-8 :
22

3-
import yaml
3+
import yaml, collections
44

55
from ioc.component import Definition, Reference, WeakReference
66
import ioc.helper, ioc.exceptions
7+
from misc import OrderedDictYAMLLoader
78

89
class Loader(object):
910
def fix_config(self, config):
@@ -20,7 +21,7 @@ def support(self, file):
2021
def load(self, file, container_builder):
2122

2223
try:
23-
data = yaml.load(open(file).read())
24+
data = yaml.load(open(file).read(), OrderedDictYAMLLoader)
2425
except yaml.scanner.ScannerError, e:
2526
raise ioc.exceptions.LoadingError("file %s, \nerror: %s" % (file, e))
2627

ioc/misc.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
The default yaml loader does not respect the ordering key while loading a dictionay.
3+
This can lead to error while ordering is defining key by key
4+
5+
reference: https://gist.github.com/enaeseth/844388
6+
7+
"""
8+
9+
import yaml
10+
import yaml.constructor
11+
12+
try:
13+
# included in standard lib from Python 2.7
14+
from collections import OrderedDict
15+
except ImportError:
16+
# try importing the backported drop-in replacement
17+
# it's available on PyPI
18+
from ordereddict import OrderedDict
19+
20+
class OrderedDictYAMLLoader(yaml.Loader):
21+
"""
22+
A YAML loader that loads mappings into ordered dictionaries.
23+
"""
24+
25+
def __init__(self, *args, **kwargs):
26+
yaml.Loader.__init__(self, *args, **kwargs)
27+
28+
self.add_constructor(u'tag:yaml.org,2002:map', type(self).construct_yaml_map)
29+
self.add_constructor(u'tag:yaml.org,2002:omap', type(self).construct_yaml_map)
30+
31+
def construct_yaml_map(self, node):
32+
data = OrderedDict()
33+
yield data
34+
value = self.construct_mapping(node)
35+
data.update(value)
36+
37+
def construct_mapping(self, node, deep=False):
38+
if isinstance(node, yaml.MappingNode):
39+
self.flatten_mapping(node)
40+
else:
41+
raise yaml.constructor.ConstructorError(None, None,
42+
'expected a mapping node, but found %s' % node.id, node.start_mark)
43+
44+
mapping = OrderedDict()
45+
for key_node, value_node in node.value:
46+
key = self.construct_object(key_node, deep=deep)
47+
try:
48+
hash(key)
49+
except TypeError, exc:
50+
raise yaml.constructor.ConstructorError('while constructing a mapping',
51+
node.start_mark, 'found unacceptable key (%s)' % exc, key_node.start_mark)
52+
value = self.construct_object(value_node, deep=deep)
53+
mapping[key] = value
54+
return mapping
55+

0 commit comments

Comments
 (0)