You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

82 lines
3.0 KiB

  1. import yaml
  2. from collections import OrderedDict
  3. def construct_odict(load, node):
  4. """This is the same as SafeConstructor.construct_yaml_omap(),
  5. except the data type is changed to OrderedDict() and setitem is
  6. used instead of append in the loop.
  7. >>> yaml.load('''
  8. ... !!omap
  9. ... - foo: bar
  10. ... - mumble: quux
  11. ... - baz: gorp
  12. ... ''')
  13. OrderedDict([('foo', 'bar'), ('mumble', 'quux'), ('baz', 'gorp')])
  14. >>> yaml.load('''!!omap [ foo: bar, mumble: quux, baz : gorp ]''')
  15. OrderedDict([('foo', 'bar'), ('mumble', 'quux'), ('baz', 'gorp')])
  16. """
  17. omap = OrderedDict()
  18. yield omap
  19. if not isinstance(node, yaml.SequenceNode):
  20. raise yaml.constructor.ConstructorError(
  21. "while constructing an ordered map",
  22. node.start_mark,
  23. "expected a sequence, but found %s" % node.id, node.start_mark
  24. )
  25. for subnode in node.value:
  26. if not isinstance(subnode, yaml.MappingNode):
  27. raise yaml.constructor.ConstructorError(
  28. "while constructing an ordered map", node.start_mark,
  29. "expected a mapping of length 1, but found %s" % subnode.id,
  30. subnode.start_mark
  31. )
  32. if len(subnode.value) != 1:
  33. raise yaml.constructor.ConstructorError(
  34. "while constructing an ordered map", node.start_mark,
  35. "expected a single mapping item, but found %d items" % len(subnode.value),
  36. subnode.start_mark
  37. )
  38. key_node, value_node = subnode.value[0]
  39. key = load.construct_object(key_node)
  40. value = load.construct_object(value_node)
  41. omap[key] = value
  42. yaml.add_constructor(u'tag:yaml.org,2002:omap', construct_odict)
  43. def repr_pairs(dump, tag, sequence, flow_style=None):
  44. """This is the same code as BaseRepresenter.represent_sequence(),
  45. but the value passed to dump.represent_data() in the loop is a
  46. dictionary instead of a tuple."""
  47. value = []
  48. node = yaml.SequenceNode(tag, value, flow_style=flow_style)
  49. if dump.alias_key is not None:
  50. dump.represented_objects[dump.alias_key] = node
  51. best_style = True
  52. for (key, val) in sequence:
  53. item = dump.represent_data({key: val})
  54. if not (isinstance(item, yaml.ScalarNode) and not item.style):
  55. best_style = False
  56. value.append(item)
  57. if flow_style is None:
  58. if dump.default_flow_style is not None:
  59. node.flow_style = dump.default_flow_style
  60. else:
  61. node.flow_style = best_style
  62. return node
  63. def repr_odict(dumper, data):
  64. """
  65. >>> data = OrderedDict([('foo', 'bar'), ('mumble', 'quux'), ('baz', 'gorp')])
  66. >>> yaml.dump(data, default_flow_style=False)
  67. '!!omap\\n- foo: bar\\n- mumble: quux\\n- baz: gorp\\n'
  68. >>> yaml.dump(data, default_flow_style=True)
  69. '!!omap [foo: bar, mumble: quux, baz: gorp]\\n'
  70. """
  71. return repr_pairs(dumper, u'tag:yaml.org,2002:omap', data.iteritems())
  72. yaml.add_representer(OrderedDict, repr_odict)