2 __all__
= ['Composer', 'ComposerError']
4 from error
import MarkedYAMLError
8 class ComposerError(MarkedYAMLError
):
11 class Composer(object):
17 # Drop the STREAM-START event.
18 if self
.check_event(StreamStartEvent
):
21 # If there are more documents available?
22 return not self
.check_event(StreamEndEvent
)
25 # Get the root node of the next document.
26 if not self
.check_event(StreamEndEvent
):
27 return self
.compose_document()
29 def get_single_node(self
):
30 # Drop the STREAM-START event.
33 # Compose a document if the stream is not empty.
35 if not self
.check_event(StreamEndEvent
):
36 document
= self
.compose_document()
38 # Ensure that the stream contains no more documents.
39 if not self
.check_event(StreamEndEvent
):
40 event
= self
.get_event()
41 raise ComposerError("expected a single document in the stream",
42 document
.start_mark
, "but found another document",
45 # Drop the STREAM-END event.
50 def compose_document(self
):
51 # Drop the DOCUMENT-START event.
54 # Compose the root node.
55 node
= self
.compose_node(None, None)
57 # Drop the DOCUMENT-END event.
63 def compose_node(self
, parent
, index
):
64 if self
.check_event(AliasEvent
):
65 event
= self
.get_event()
67 if anchor
not in self
.anchors
:
68 raise ComposerError(None, None, "found undefined alias %r"
69 % anchor
.encode('utf-8'), event
.start_mark
)
70 return self
.anchors
[anchor
]
71 event
= self
.peek_event()
73 if anchor
is not None:
74 if anchor
in self
.anchors
:
75 raise ComposerError("found duplicate anchor %r; first occurence"
76 % anchor
.encode('utf-8'), self
.anchors
[anchor
].start_mark
,
77 "second occurence", event
.start_mark
)
78 self
.descend_resolver(parent
, index
)
79 if self
.check_event(ScalarEvent
):
80 node
= self
.compose_scalar_node(anchor
)
81 elif self
.check_event(SequenceStartEvent
):
82 node
= self
.compose_sequence_node(anchor
)
83 elif self
.check_event(MappingStartEvent
):
84 node
= self
.compose_mapping_node(anchor
)
85 self
.ascend_resolver()
88 def compose_scalar_node(self
, anchor
):
89 event
= self
.get_event()
91 if tag
is None or tag
== u
'!':
92 tag
= self
.resolve(ScalarNode
, event
.value
, event
.implicit
)
93 node
= ScalarNode(tag
, event
.value
,
94 event
.start_mark
, event
.end_mark
, style
=event
.style
)
95 if anchor
is not None:
96 self
.anchors
[anchor
] = node
99 def compose_sequence_node(self
, anchor
):
100 start_event
= self
.get_event()
101 tag
= start_event
.tag
102 if tag
is None or tag
== u
'!':
103 tag
= self
.resolve(SequenceNode
, None, start_event
.implicit
)
104 node
= SequenceNode(tag
, [],
105 start_event
.start_mark
, None,
106 flow_style
=start_event
.flow_style
)
107 if anchor
is not None:
108 self
.anchors
[anchor
] = node
110 while not self
.check_event(SequenceEndEvent
):
111 node
.value
.append(self
.compose_node(node
, index
))
113 end_event
= self
.get_event()
114 node
.end_mark
= end_event
.end_mark
117 def compose_mapping_node(self
, anchor
):
118 start_event
= self
.get_event()
119 tag
= start_event
.tag
120 if tag
is None or tag
== u
'!':
121 tag
= self
.resolve(MappingNode
, None, start_event
.implicit
)
122 node
= MappingNode(tag
, [],
123 start_event
.start_mark
, None,
124 flow_style
=start_event
.flow_style
)
125 if anchor
is not None:
126 self
.anchors
[anchor
] = node
127 while not self
.check_event(MappingEndEvent
):
128 #key_event = self.peek_event()
129 item_key
= self
.compose_node(node
, None)
130 #if item_key in node.value:
131 # raise ComposerError("while composing a mapping", start_event.start_mark,
132 # "found duplicate key", key_event.start_mark)
133 item_value
= self
.compose_node(node
, item_key
)
134 #node.value[item_key] = item_value
135 node
.value
.append((item_key
, item_value
))
136 end_event
= self
.get_event()
137 node
.end_mark
= end_event
.end_mark