source: pyyaml/trunk/lib/yaml/composer.py @ 222

Revision 222, 4.1 KB checked in by xi, 8 years ago (diff)

Subclass all base classes from object.

Hold references to the objects being represented (should fix #22).

The value of a mapping node is represented as a list of pairs (key, value)
now.

Sort dictionary items (fix #23).

Recursive structures are now loaded and dumped correctly, including complex
structures like recursive tuples (fix #5). Thanks Peter Murphy for the patches.
To make it possible, representer functions are allowed to be generators.
In this case, the first generated value is an object. Other values produced
by the representer are ignored.

Make Representer not try to guess !!pairs when a list is represented.
You need to construct a !!pairs node explicitly now.

Do not check for duplicate mapping keys as it didn't work correctly anyway.

Line 
1
2__all__ = ['Composer', 'ComposerError']
3
4from error import MarkedYAMLError
5from events import *
6from nodes import *
7
8class ComposerError(MarkedYAMLError):
9    pass
10
11class Composer(object):
12
13    def __init__(self):
14        self.anchors = {}
15
16    def check_node(self):
17        # If there are more documents available?
18        return not self.check_event(StreamEndEvent)
19
20    def get_node(self):
21        # Get the root node of the next document.
22        if not self.check_event(StreamEndEvent):
23            return self.compose_document()
24
25    def compose_document(self):
26
27        # Drop the STREAM-START event.
28        if self.check_event(StreamStartEvent):
29            self.get_event()
30
31        # Drop the DOCUMENT-START event.
32        self.get_event()
33
34        # Compose the root node.
35        node = self.compose_node(None, None)
36
37        # Drop the DOCUMENT-END event.
38        self.get_event()
39
40        self.complete_anchors = {}
41        return node
42
43    def compose_node(self, parent, index):
44        if self.check_event(AliasEvent):
45            event = self.get_event()
46            anchor = event.anchor
47            if anchor not in self.anchors:
48                raise ComposerError(None, None, "found undefined alias %r"
49                        % anchor.encode('utf-8'), event.start_mark)
50            return self.anchors[anchor]
51        event = self.peek_event()
52        anchor = event.anchor
53        if anchor is not None:
54            if anchor in self.anchors:
55                raise ComposerError("found duplicate anchor %r; first occurence"
56                        % anchor.encode('utf-8'), self.anchors[anchor].start_mark,
57                        "second occurence", event.start_mark)
58        self.descend_resolver(parent, index)
59        if self.check_event(ScalarEvent):
60            node = self.compose_scalar_node(anchor)
61        elif self.check_event(SequenceStartEvent):
62            node = self.compose_sequence_node(anchor)
63        elif self.check_event(MappingStartEvent):
64            node = self.compose_mapping_node(anchor)
65        self.ascend_resolver()
66        return node
67
68    def compose_scalar_node(self, anchor):
69        event = self.get_event()
70        tag = event.tag
71        if tag is None or tag == u'!':
72            tag = self.resolve(ScalarNode, event.value, event.implicit)
73        node = ScalarNode(tag, event.value,
74                event.start_mark, event.end_mark, style=event.style)
75        if anchor is not None:
76            self.anchors[anchor] = node
77        return node
78
79    def compose_sequence_node(self, anchor):
80        start_event = self.get_event()
81        tag = start_event.tag
82        if tag is None or tag == u'!':
83            tag = self.resolve(SequenceNode, None, start_event.implicit)
84        node = SequenceNode(tag, [],
85                start_event.start_mark, None,
86                flow_style=start_event.flow_style)
87        if anchor is not None:
88            self.anchors[anchor] = node
89        index = 0
90        while not self.check_event(SequenceEndEvent):
91            node.value.append(self.compose_node(node, index))
92            index += 1
93        end_event = self.get_event()
94        node.end_mark = end_event.end_mark
95        return node
96
97    def compose_mapping_node(self, anchor):
98        start_event = self.get_event()
99        tag = start_event.tag
100        if tag is None or tag == u'!':
101            tag = self.resolve(MappingNode, None, start_event.implicit)
102        node = MappingNode(tag, [],
103                start_event.start_mark, None,
104                flow_style=start_event.flow_style)
105        if anchor is not None:
106            self.anchors[anchor] = node
107        while not self.check_event(MappingEndEvent):
108            #key_event = self.peek_event()
109            item_key = self.compose_node(node, None)
110            #if item_key in node.value:
111            #    raise ComposerError("while composing a mapping", start_event.start_mark,
112            #            "found duplicate key", key_event.start_mark)
113            item_value = self.compose_node(node, item_key)
114            #node.value[item_key] = item_value
115            node.value.append((item_key, item_value))
116        end_event = self.get_event()
117        node.end_mark = end_event.end_mark
118        return node
119
Note: See TracBrowser for help on using the repository browser.