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: 12 13 def __init__(self): 14 self.anchors = {} 15 16 def check_node(self): 17 # Drop the STREAM-START event. 18 if self.check_event(StreamStartEvent): 19 self.get_event() 20 21 # If there are more documents available? 22 return not self.check_event(StreamEndEvent) 23 24 def get_node(self): 25 # Get the root node of the next document. 26 if not self.check_event(StreamEndEvent): 27 return self.compose_document() 28 29 def get_single_node(self): 30 # Drop the STREAM-START event. 31 self.get_event() 32 33 # Compose a document if the stream is not empty. 34 document = None 35 if not self.check_event(StreamEndEvent): 36 document = self.compose_document() 37 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", 43 event.start_mark) 44 45 # Drop the STREAM-END event. 46 self.get_event() 47 48 return document 49 50 def compose_document(self): 51 # Drop the DOCUMENT-START event. 52 self.get_event() 53 54 # Compose the root node. 55 node = self.compose_node(None, None) 56 57 # Drop the DOCUMENT-END event. 58 self.get_event() 59 60 self.anchors = {} 61 return node 62 63 def compose_node(self, parent, index): 64 if self.check_event(AliasEvent): 65 event = self.get_event() 66 anchor = event.anchor 67 if anchor not in self.anchors: 68 raise ComposerError(None, None, "found undefined alias %r" 69 % anchor, event.start_mark) 70 return self.anchors[anchor] 71 event = self.peek_event() 72 anchor = event.anchor 73 if anchor is not None: 74 if anchor in self.anchors: 75 raise ComposerError("found duplicate anchor %r; first occurrence" 76 % anchor, self.anchors[anchor].start_mark, 77 "second occurrence", 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() 86 return node 87 88 def compose_scalar_node(self, anchor): 89 event = self.get_event() 90 tag = event.tag 91 if tag is None or tag == '!': 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 97 return node 98 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 == '!': 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 109 index = 0 110 while not self.check_event(SequenceEndEvent): 111 node.value.append(self.compose_node(node, index)) 112 index += 1 113 end_event = self.get_event() 114 node.end_mark = end_event.end_mark 115 return node 116 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 == '!': 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 138 return node 139 140