| 1 |
|
|---|
| 2 |
__all__ = ['BaseComposer', 'Composer', 'ComposerError'] |
|---|
| 3 |
|
|---|
| 4 |
# This contains revisions to allow recursive loads in this file. |
|---|
| 5 |
# All modifications are marked by PKM2006 |
|---|
| 6 |
|
|---|
| 7 |
from error import MarkedYAMLError |
|---|
| 8 |
from events import * |
|---|
| 9 |
from nodes import * |
|---|
| 10 |
|
|---|
| 11 |
class ComposerError(MarkedYAMLError): |
|---|
| 12 |
pass |
|---|
| 13 |
|
|---|
| 14 |
class BaseComposer: |
|---|
| 15 |
|
|---|
| 16 |
yaml_resolvers = {} |
|---|
| 17 |
|
|---|
| 18 |
def __init__(self): |
|---|
| 19 |
self.all_anchors = {} |
|---|
| 20 |
# PKM2006 - unnecessary: self.complete_anchors = {} |
|---|
| 21 |
self.resolver_tags = [] |
|---|
| 22 |
self.resolver_paths = [] |
|---|
| 23 |
|
|---|
| 24 |
def check_node(self): |
|---|
| 25 |
# If there are more documents available? |
|---|
| 26 |
return not self.check_event(StreamEndEvent) |
|---|
| 27 |
|
|---|
| 28 |
def get_node(self): |
|---|
| 29 |
# Get the root node of the next document. |
|---|
| 30 |
if not self.check_event(StreamEndEvent): |
|---|
| 31 |
return self.compose_document() |
|---|
| 32 |
|
|---|
| 33 |
def __iter__(self): |
|---|
| 34 |
# Iterator protocol. |
|---|
| 35 |
while not self.check_event(StreamEndEvent): |
|---|
| 36 |
yield self.compose_document() |
|---|
| 37 |
|
|---|
| 38 |
def compose_document(self): |
|---|
| 39 |
|
|---|
| 40 |
# Drop the STREAM-START event. |
|---|
| 41 |
if self.check_event(StreamStartEvent): |
|---|
| 42 |
self.get_event() |
|---|
| 43 |
|
|---|
| 44 |
# Drop the DOCUMENT-START event. |
|---|
| 45 |
self.get_event() |
|---|
| 46 |
|
|---|
| 47 |
# Compose the root node. |
|---|
| 48 |
node = self.compose_node([]) |
|---|
| 49 |
|
|---|
| 50 |
# Drop the DOCUMENT-END event. |
|---|
| 51 |
self.get_event() |
|---|
| 52 |
|
|---|
| 53 |
self.all_anchors = {} |
|---|
| 54 |
# PKM2006 - unnecessary: self.complete_anchors = {} |
|---|
| 55 |
self.resolver_tags = [] |
|---|
| 56 |
self.resolver_paths = [] |
|---|
| 57 |
return node |
|---|
| 58 |
|
|---|
| 59 |
def increase_resolver_depth(self, path): |
|---|
| 60 |
depth = len(path) |
|---|
| 61 |
tag = None |
|---|
| 62 |
paths = [] |
|---|
| 63 |
if not depth: |
|---|
| 64 |
for resolver_path in self.yaml_resolvers.keys(): |
|---|
| 65 |
if resolver_path: |
|---|
| 66 |
paths.append(resolver_path) |
|---|
| 67 |
else: |
|---|
| 68 |
tag = self.yaml_resolvers[resolver_path] |
|---|
| 69 |
else: |
|---|
| 70 |
base, index = path[-1] |
|---|
| 71 |
if isinstance(index, ScalarNode) \ |
|---|
| 72 |
and index.tag == self.DEFAULT_SCALAR_TAG: |
|---|
| 73 |
index = index.value |
|---|
| 74 |
elif isinstance(index, Node): |
|---|
| 75 |
index = None |
|---|
| 76 |
for resolver_path in self.resolver_paths[-1]: |
|---|
| 77 |
resolver_index = resolver_path[depth-1] |
|---|
| 78 |
if resolver_index is None or resolver_index == index: |
|---|
| 79 |
if len(resolver_index) > depth: |
|---|
| 80 |
paths.append(resolver_path) |
|---|
| 81 |
else: |
|---|
| 82 |
tag = self.yaml_resolvers[resolver_path] |
|---|
| 83 |
self.resolver_tags.append(tag) |
|---|
| 84 |
self.resolver_paths.append(paths) |
|---|
| 85 |
|
|---|
| 86 |
def decrease_resolver_depth(self): |
|---|
| 87 |
del self.resolver_tags[-1] |
|---|
| 88 |
del self.resolver_paths[-1] |
|---|
| 89 |
|
|---|
| 90 |
def compose_node(self, path): |
|---|
| 91 |
if self.check_event(AliasEvent): |
|---|
| 92 |
event = self.get_event() |
|---|
| 93 |
anchor = event.anchor |
|---|
| 94 |
if anchor not in self.all_anchors: |
|---|
| 95 |
raise ComposerError(None, None, "found undefined alias %r" |
|---|
| 96 |
% anchor.encode('utf-8'), event.start_mark) |
|---|
| 97 |
|
|---|
| 98 |
# PKM2006 - This code is utterly unsuited for what we want to do. |
|---|
| 99 |
# We want to allow recursion. |
|---|
| 100 |
# if anchor not in self.complete_anchors: |
|---|
| 101 |
# collection_event = self.all_anchors[anchor] |
|---|
| 102 |
# raise ComposerError("while composing a collection", |
|---|
| 103 |
# collection_event.start_mark, |
|---|
| 104 |
# "found recursive anchor %r" % anchor.encode('utf-8'), |
|---|
| 105 |
# event.start_mark) |
|---|
| 106 |
|
|---|
| 107 |
# PKM2006 - now we use the right map here. |
|---|
| 108 |
# return self.complete_anchors[anchor] |
|---|
| 109 |
return self.all_anchors[anchor]; |
|---|
| 110 |
self.increase_resolver_depth(path) |
|---|
| 111 |
event = self.peek_event() |
|---|
| 112 |
anchor = event.anchor |
|---|
| 113 |
print "This is an event" |
|---|
| 114 |
print event |
|---|
| 115 |
anchor = event.anchor |
|---|
| 116 |
print "This is the anchor" |
|---|
| 117 |
print anchor |
|---|
| 118 |
|
|---|
| 119 |
if anchor is not None: |
|---|
| 120 |
if anchor in self.all_anchors: |
|---|
| 121 |
raise ComposerError("found duplicate anchor %r; first occurence" |
|---|
| 122 |
% anchor.encode('utf-8'), self.all_anchors[anchor].start_mark, |
|---|
| 123 |
"second occurence", event.start_mark) |
|---|
| 124 |
self.all_anchors[anchor] = event |
|---|
| 125 |
|
|---|
| 126 |
# PKM2006 - we now add arguments to the compose functions. |
|---|
| 127 |
if self.check_event(ScalarEvent): |
|---|
| 128 |
node = self.compose_scalar_node(path, anchor) #PKM2006 |
|---|
| 129 |
elif self.check_event(SequenceStartEvent): |
|---|
| 130 |
node = self.compose_sequence_node(path, anchor) #PKM2006 |
|---|
| 131 |
elif self.check_event(MappingStartEvent): |
|---|
| 132 |
node = self.compose_mapping_node(path, anchor) #PKM2006 |
|---|
| 133 |
|
|---|
| 134 |
# PKM2006 - we don't need this code any more - we now key nodes |
|---|
| 135 |
# by anchors in the appropriate sub-compose function. |
|---|
| 136 |
# if anchor is not None: |
|---|
| 137 |
# self.complete_anchors[anchor] = node |
|---|
| 138 |
self.decrease_resolver_depth() |
|---|
| 139 |
return node |
|---|
| 140 |
|
|---|
| 141 |
# PKM2006 - extra anchor argument. |
|---|
| 142 |
def compose_scalar_node(self, path, anchor = None): |
|---|
| 143 |
event = self.get_event() |
|---|
| 144 |
tag = self.resolve_scalar(path, event.tag, event.implicit, event.value) |
|---|
| 145 |
ourNode = ScalarNode(tag, event.value, |
|---|
| 146 |
event.start_mark, event.end_mark, style=event.style); #PKM2006 |
|---|
| 147 |
if anchor is not None: #PKM2006 |
|---|
| 148 |
self.all_anchors[anchor] = ourNode; #PKM2006 |
|---|
| 149 |
return ourNode; #PKM2006 |
|---|
| 150 |
|
|---|
| 151 |
# PKM2006 - extra anchor argument. |
|---|
| 152 |
def compose_sequence_node(self, path, anchor = None): |
|---|
| 153 |
start_event = self.get_event() |
|---|
| 154 |
tag = self.resolve_sequence(path, start_event.tag) |
|---|
| 155 |
node = SequenceNode(tag, [], |
|---|
| 156 |
start_event.start_mark, None, |
|---|
| 157 |
flow_style=start_event.flow_style) |
|---|
| 158 |
if anchor is not None: #PKM2006 |
|---|
| 159 |
self.all_anchors[anchor] = node; #PKM2006 |
|---|
| 160 |
index = 0 |
|---|
| 161 |
while not self.check_event(SequenceEndEvent): |
|---|
| 162 |
node.value.append(self.compose_node(path+[(node, index)])) |
|---|
| 163 |
index += 1 |
|---|
| 164 |
end_event = self.get_event() |
|---|
| 165 |
node.end_mark = end_event.end_mark |
|---|
| 166 |
return node |
|---|
| 167 |
|
|---|
| 168 |
# PKM2006 - extra anchor argument. |
|---|
| 169 |
def compose_mapping_node(self, path, anchor = None): |
|---|
| 170 |
start_event = self.get_event() |
|---|
| 171 |
tag = self.resolve_mapping(path, start_event.tag) |
|---|
| 172 |
node = MappingNode(tag, {}, |
|---|
| 173 |
start_event.start_mark, None, |
|---|
| 174 |
flow_style=start_event.flow_style) |
|---|
| 175 |
if anchor is not None: #PKM2006 |
|---|
| 176 |
self.all_anchors[anchor] = node; #PKM2006 |
|---|
| 177 |
while not self.check_event(MappingEndEvent): |
|---|
| 178 |
key_event = self.peek_event() |
|---|
| 179 |
item_key = self.compose_node(path+[(node, None)]) |
|---|
| 180 |
item_value = self.compose_node(path+[(node, item_key)]) |
|---|
| 181 |
if item_key in node.value: |
|---|
| 182 |
raise ComposerError("while composing a mapping", start_event.start_mark, |
|---|
| 183 |
"found duplicate key", key_event.start_mark) |
|---|
| 184 |
node.value[item_key] = item_value |
|---|
| 185 |
end_event = self.get_event() |
|---|
| 186 |
node.end_mark = end_event.end_mark |
|---|
| 187 |
return node |
|---|
| 188 |
|
|---|
| 189 |
def resolve_scalar(self, path, tag, implicit, value): |
|---|
| 190 |
if implicit: |
|---|
| 191 |
tag = self.detect(value) |
|---|
| 192 |
if tag is None and self.resolver_tags[-1]: |
|---|
| 193 |
tag = self.resolver_tags[-1] |
|---|
| 194 |
if tag is None or tag == u'!': |
|---|
| 195 |
tag = self.DEFAULT_SCALAR_TAG |
|---|
| 196 |
return tag |
|---|
| 197 |
|
|---|
| 198 |
def resolve_sequence(self, path, tag): |
|---|
| 199 |
if tag is None and self.resolver_tags[-1]: |
|---|
| 200 |
tag = self.resolver_tags[-1] |
|---|
| 201 |
if tag is None or tag == u'!': |
|---|
| 202 |
tag = self.DEFAULT_SEQUENCE_TAG |
|---|
| 203 |
return tag |
|---|
| 204 |
|
|---|
| 205 |
def resolve_mapping(self, path, tag): |
|---|
| 206 |
if tag is None and self.resolver_tags[-1]: |
|---|
| 207 |
tag = self.resolver_tags[-1] |
|---|
| 208 |
if tag is None or tag == u'!': |
|---|
| 209 |
tag = self.DEFAULT_MAPPING_TAG |
|---|
| 210 |
return tag |
|---|
| 211 |
|
|---|
| 212 |
def add_resolver(self, tag, path): |
|---|
| 213 |
if not 'yaml_resolvers' in cls.__dict__: |
|---|
| 214 |
cls.yaml_resolvers = cls.yaml_resolvers.copy() |
|---|
| 215 |
cls.yaml_resolvers[tuple(path)] = tag |
|---|
| 216 |
add_resolver = classmethod(add_resolver) |
|---|
| 217 |
|
|---|
| 218 |
class Composer(BaseComposer): |
|---|
| 219 |
pass |
|---|
| 220 |
|
|---|