summaryrefslogtreecommitdiff
path: root/morphlib/yamlparse.py
diff options
context:
space:
mode:
authorLars Wirzenius <lars.wirzenius@codethink.co.uk>2013-01-29 13:50:46 +0000
committerLars Wirzenius <lars.wirzenius@codethink.co.uk>2013-01-29 14:32:49 +0000
commite06eafcbf0784271f51c0936852d1e97c0ccce8b (patch)
treee7e914cd82348e79b7662e6bd06851a0100e7751 /morphlib/yamlparse.py
parent63f608d7c05095c16d1a8863b13c55634c0cae8b (diff)
downloadmorph-e06eafcbf0784271f51c0936852d1e97c0ccce8b.tar.gz
Make yaml be an optional dependency
This can go away when we have made a release with yaml in it, and its staging filler.
Diffstat (limited to 'morphlib/yamlparse.py')
-rw-r--r--morphlib/yamlparse.py185
1 files changed, 100 insertions, 85 deletions
diff --git a/morphlib/yamlparse.py b/morphlib/yamlparse.py
index 7f8b00e5..a2832b89 100644
--- a/morphlib/yamlparse.py
+++ b/morphlib/yamlparse.py
@@ -13,13 +13,18 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-import yaml
-import yaml.constructor
+import morphlib
from morphlib.util import OrderedDict
-class OrderedDictYAMLLoader(yaml.Loader):
- """A YAML loader that loads mappings into ordered dictionaries.
+if morphlib.got_yaml: # pragma: no cover
+ yaml = morphlib.yaml
+
+
+if morphlib.got_yaml: # pragma: no cover
+
+ class OrderedDictYAMLLoader(yaml.Loader):
+ """A YAML loader that loads mappings into ordered dictionaries.
When YAML is loaded with this Loader, it loads mappings as ordered
dictionaries, so the order the keys were written in is maintained.
@@ -27,47 +32,48 @@ class OrderedDictYAMLLoader(yaml.Loader):
When combined with the OrderedDictYAMLDumper, this allows yaml documents
to be written out in a similar format to they were read.
- """
-
- def __init__(self, *args, **kwargs):
- yaml.Loader.__init__(self, *args, **kwargs)
-
- # When YAML encounters a mapping (which YAML identifies with
- # the given tag), it will use construct_yaml_map to read it as
- # an OrderedDict.
- self.add_constructor(u'tag:yaml.org,2002:map',
- 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 __init__(self, *args, **kwargs):
+ yaml.Loader.__init__(self, *args, **kwargs)
-class OrderedDictYAMLDumper(yaml.Dumper):
- """A YAML dumper that will dump OrderedDicts as mappings.
+ # When YAML encounters a mapping (which YAML identifies with
+ # the given tag), it will use construct_yaml_map to read it as
+ # an OrderedDict.
+ self.add_constructor(u'tag:yaml.org,2002:map',
+ 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
+
+ class OrderedDictYAMLDumper(yaml.Dumper):
+ """A YAML dumper that will dump OrderedDicts as mappings.
When YAML is dumped with this Dumper, it dumps OrderedDicts as
mappings, preserving the key order, so the order the keys were
@@ -76,44 +82,53 @@ class OrderedDictYAMLDumper(yaml.Dumper):
When combined with the OrderedDictYAMLDumper, this allows yaml documents
to be written out in a similar format to they were read.
- """
-
- def __init__(self, *args, **kwargs):
- yaml.Dumper.__init__(self, *args, **kwargs)
-
- # When YAML sees an OrderedDict, use represent_ordered_dict to dump it
- self.add_representer(OrderedDict,
- type(self).represent_ordered_dict)
-
- def represent_ordered_dict(self, odict):
- return self.represent_ordered_mapping(u'tag:yaml.org,2002:map', odict)
-
- def represent_ordered_mapping(self, tag, omap):
- value = []
- node = yaml.MappingNode(tag, value)
- if self.alias_key is not None:
- self.represented_objects[self.alias_key] = node
- best_style = True
- for item_key, item_value in omap.iteritems():
- node_key = self.represent_data(item_key)
- node_value = self.represent_data(item_value)
- if not (isinstance(node_key, yaml.ScalarNode) and
- not node_key.style):
- best_style = False # pragma: no cover
- if not (isinstance(node_value, yaml.ScalarNode) and
- not node_value.style):
- best_style = False # pragma: no cover
- value.append((node_key, node_value))
- if self.default_flow_style is not None:
- node.flow_style = self.default_flow_style
- else:
- node.flow_style = best_style # pragma: no cover
- return node
-
-def load(*args, **kwargs):
- return yaml.load(Loader=OrderedDictYAMLLoader, *args, **kwargs)
-
-def dump(*args, **kwargs):
- if 'default_flow_style' not in kwargs:
- kwargs['default_flow_style'] = False
- return yaml.dump(Dumper=OrderedDictYAMLDumper, *args, **kwargs)
+ """
+
+ def __init__(self, *args, **kwargs):
+ yaml.Dumper.__init__(self, *args, **kwargs)
+
+ # When YAML sees an OrderedDict, use represent_ordered_dict to
+ # dump it
+ self.add_representer(OrderedDict,
+ type(self).represent_ordered_dict)
+
+ def represent_ordered_dict(self, odict):
+ return self.represent_ordered_mapping(
+ u'tag:yaml.org,2002:map', odict)
+
+ def represent_ordered_mapping(self, tag, omap):
+ value = []
+ node = yaml.MappingNode(tag, value)
+ if self.alias_key is not None:
+ self.represented_objects[self.alias_key] = node
+ best_style = True
+ for item_key, item_value in omap.iteritems():
+ node_key = self.represent_data(item_key)
+ node_value = self.represent_data(item_value)
+ if not (isinstance(node_key, yaml.ScalarNode) and
+ not node_key.style):
+ best_style = False # pragma: no cover
+ if not (isinstance(node_value, yaml.ScalarNode) and
+ not node_value.style):
+ best_style = False # pragma: no cover
+ value.append((node_key, node_value))
+ if self.default_flow_style is not None:
+ node.flow_style = self.default_flow_style
+ else:
+ node.flow_style = best_style # pragma: no cover
+ return node
+
+ def load(*args, **kwargs):
+ return yaml.load(Loader=OrderedDictYAMLLoader, *args, **kwargs)
+
+ def dump(*args, **kwargs):
+ if 'default_flow_style' not in kwargs:
+ kwargs['default_flow_style'] = False
+ return yaml.dump(Dumper=OrderedDictYAMLDumper, *args, **kwargs)
+
+else: # pragma: no cover
+ def load(*args, **kwargs):
+ raise morphlib.Error('YAML not available')
+ def dump(*args, **kwargs):
+ raise morphlib.Error('YAML not available')
+