Fix ordered yaml load
Change-Id: I0db23722017f31839d5449af64185ec4b6a35c61
diff --git a/_modules/keystone_policy.py b/_modules/keystone_policy.py
index 4803150..2e79f22 100644
--- a/_modules/keystone_policy.py
+++ b/_modules/keystone_policy.py
@@ -2,11 +2,55 @@
import json
import logging
-from collections import OrderedDict
+LOG = logging.getLogger(__name__)
import yaml
+import yaml.constructor
-LOG = logging.getLogger(__name__)
+try:
+ # included in standard lib from Python 2.7
+ from collections import OrderedDict
+except ImportError:
+ # try importing the backported drop-in replacement
+ # it's available on PyPI
+ from ordereddict import OrderedDict
+
+# https://stackoverflow.com/questions/5121931/in-python-how-can-you-load-yaml-mappings-as-ordereddicts
+class OrderedDictYAMLLoader(yaml.Loader):
+ """
+ A YAML loader that loads mappings into ordered dictionaries.
+ """
+
+ def __init__(self, *args, **kwargs):
+ yaml.Loader.__init__(self, *args, **kwargs)
+
+ self.add_constructor(u'tag:yaml.org,2002:map', type(self).construct_yaml_map)
+ self.add_constructor(u'tag:yaml.org,2002:omap', type(self).construct_yaml_map)
+
+ def construct_yaml_map(self, node):
+ data = OrderedDict()
+ yield data
+ value = self.construct_mapping(node)
+ data.update(value)
+
+ def construct_mapping(self, node, deep=False):
+ if isinstance(node, yaml.MappingNode):
+ self.flatten_mapping(node)
+ else:
+ raise yaml.constructor.ConstructorError(None, None,
+ 'expected a mapping node, but found %s' % node.id, node.start_mark)
+
+ mapping = OrderedDict()
+ for key_node, value_node in node.value:
+ key = self.construct_object(key_node, deep=deep)
+ try:
+ hash(key)
+ except TypeError, exc:
+ raise yaml.constructor.ConstructorError('while constructing a mapping',
+ node.start_mark, 'found unacceptable key (%s)' % exc, key_node.start_mark)
+ value = self.construct_object(value_node, deep=deep)
+ mapping[key] = value
+ return mapping
def __virtual__():
@@ -16,8 +60,7 @@
def rule_list(path, **kwargs):
try:
with io.open(path, 'r') as file_handle:
- rules = yaml.safe_load(file_handle) or {}
- rules = OrderedDict(str(k): str(v) for (k, v) in rules.items())
+ rules = yaml.load(file_handle, OrderedDictYAMLLoader) or OrderedDict()
except Exception as e:
msg = "Unable to load policy file %s: %s" % (path, repr(e))
LOG.debug(msg)