Changeset 136 for pyyaml/trunk/lib
- Timestamp:
- 04/15/06 19:54:52 (6 years ago)
- Location:
- pyyaml/trunk/lib/yaml
- Files:
-
- 2 added
- 2 removed
- 13 modified
-
__init__.py (modified) (2 diffs)
-
composer.py (modified) (4 diffs)
-
constructor.py (modified) (4 diffs)
-
detector.py (modified) (1 diff)
-
dumper.py (added)
-
emitter.py (modified) (34 diffs)
-
error.py (modified) (2 diffs)
-
events.py (modified) (2 diffs)
-
loader.py (added)
-
nodes.py (modified) (1 diff)
-
parser.py (modified) (29 diffs)
-
reader.py (modified) (2 diffs)
-
representer.py (modified) (5 diffs)
-
resolver.py (deleted)
-
scanner.py (modified) (63 diffs)
-
serializer.py (modified) (3 diffs)
-
yaml_object.py (deleted)
Legend:
- Unmodified
- Added
- Removed
-
pyyaml/trunk/lib/yaml/__init__.py
r135 r136 6 6 from parser import * 7 7 from composer import * 8 from resolver import *9 8 from constructor import * 10 9 … … 19 18 from nodes import * 20 19 21 from yaml_object import * 22 23 def parse(data, Reader=Reader, Scanner=Scanner, Parser=Parser): 24 reader = Reader(data) 25 scanner = Scanner(reader) 26 parser = Parser(scanner) 27 return parser 28 29 def load_all(data, Reader=Reader, Scanner=Scanner, Parser=Parser, 30 Composer=Composer, Resolver=Resolver, Constructor=Constructor): 31 reader = Reader(data) 32 scanner = Scanner(reader) 33 parser = Parser(scanner) 34 composer = Composer(parser) 35 resolver = Resolver(composer) 36 constructor = Constructor(resolver) 37 return constructor 38 39 def safe_load_all(data, Reader=Reader, Scanner=Scanner, Parser=Parser, 40 Composer=Composer, Resolver=Resolver, Constructor=SafeConstructor): 41 return load_all(data, Reader, Scanner, Parser, Composer, Resolver, 42 Constructor) 43 44 def load(data, *args, **kwds): 45 for document in load_all(data, *args, **kwds): 46 return document 47 48 def safe_load(data, *args, **kwds): 49 for document in safe_load_all(data, *args, **kwds): 50 return document 51 52 def emit(events, writer=None, Emitter=Emitter): 53 if writer is None: 20 from loader import * 21 from dumper import * 22 23 def scan(stream, Loader=Loader): 24 """ 25 Scan a YAML stream and produce scanning tokens. 26 """ 27 loader = Loader(stream) 28 while loader.check_token(): 29 yield loader.get_token() 30 31 def parse(stream, Loader=Loader): 32 """ 33 Parse a YAML stream and produce parsing events. 34 """ 35 loader = Loader(stream) 36 while loader.check_event(): 37 yield loader.get_event() 38 39 def compose(stream, Loader=Loader): 40 """ 41 Parse the first YAML document in a stream 42 and produce the corresponding representation tree. 43 """ 44 loader = Loader(stream) 45 if loader.check_node(): 46 return loader.get_node() 47 48 def compose_all(stream, Loader=Loader): 49 """ 50 Parse all YAML documents in a stream 51 and produce corresponsing representation trees. 52 """ 53 loader = Loader(stream) 54 while loader.check_node(): 55 yield loader.get_node() 56 57 def load_all(stream, Loader=Loader): 58 """ 59 Parse all YAML documents in a stream 60 and produce corresponding Python objects. 61 """ 62 loader = Loader(stream) 63 while loader.check_data(): 64 yield loader.get_data() 65 66 def load(stream, Loader=Loader): 67 """ 68 Parse the first YAML document in a stream 69 and produce the corresponding Python object. 70 """ 71 loader = Loader(stream) 72 if loader.check_data(): 73 return loader.get_data() 74 75 def safe_load_all(stream): 76 """ 77 Parse all YAML documents in a stream 78 and produce corresponding Python objects. 79 Resolve only basic YAML tags. 80 """ 81 return load_all(stream, SafeLoader) 82 83 def safe_load(stream): 84 """ 85 Parse the first YAML document in a stream 86 and produce the corresponding Python object. 87 Resolve only basic YAML tags. 88 """ 89 return load(stream, SafeLoader) 90 91 def emit(events, stream=None, Dumper=Dumper, 92 canonical=None, indent=None, width=None, 93 allow_unicode=None, line_break=None): 94 """ 95 Emit YAML parsing events into a stream. 96 If stream is None, return the produced string instead. 97 """ 98 getvalue = None 99 if stream is None: 54 100 try: 55 101 from cStringIO import StringIO 56 102 except ImportError: 57 103 from StringIO import StringIO 58 writer = StringIO() 59 return_value = True 60 else: 61 return_value = False 62 emitter = Emitter(writer) 104 stream = StringIO() 105 getvalue = stream.getvalue 106 dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, 107 allow_unicode=allow_unicode, line_break=line_break) 63 108 for event in events: 64 emitter.emit(event) 65 if return_value: 66 return writer.getvalue() 67 68 def dump_all(natives, writer=None, Emitter=Emitter, 69 Serializer=Serializer, Representer=Representer, 70 encoding='utf-8', line_break=None, canonical=None, 71 indent=None, width=None, allow_unicode=None): 72 if writer is None: 109 dumper.emit(event) 110 if getvalue: 111 return getvalue() 112 113 def serialize_all(nodes, stream=None, Dumper=Dumper, 114 canonical=None, indent=None, width=None, 115 allow_unicode=None, line_break=None, 116 encoding='utf-8', explicit_start=None, explicit_end=None, 117 version=None, tags=None): 118 """ 119 Serialize a sequence of representation trees into a YAML stream. 120 If stream is None, return the produced string instead. 121 """ 122 getvalue = None 123 if stream is None: 73 124 try: 74 125 from cStringIO import StringIO 75 126 except ImportError: 76 127 from StringIO import StringIO 77 writer = StringIO() 78 return_value = True 79 else: 80 return_value = False 81 emitter = Emitter(writer) 82 serializer = Serializer(emitter, encoding=encoding, line_break=line_break, 83 canonical=canonical, indent=indent, width=width, 84 allow_unicode=allow_unicode) 85 representer = Representer(serializer) 86 for native in natives: 87 representer.represent(native) 88 representer.close() 89 if return_value: 90 return writer.getvalue() 91 92 def safe_dump_all(natives, writer=None, Emitter=Emitter, 93 Serializer=Serializer, Representer=SafeRepresenter, 94 encoding='utf-8', line_break=None, canonical=None, 95 indent=None, width=None, allow_unicode=None): 96 return dump_all(natives, writer, Emitter, Serializer, Representer, 97 encoding, line_break, canonical, indent, width, allow_unicode) 98 99 def dump(native, *args, **kwds): 100 return dump_all([native], *args, **kwds) 101 102 def safe_dump(native, *args, **kwds): 103 return safe_dump_all([native], *args, **kwds) 104 128 stream = StringIO() 129 getvalue = stream.getvalue 130 dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, 131 allow_unicode=allow_unicode, line_break=line_break, 132 encoding=encoding, version=version, tags=tags, 133 explicit_start=explicit_start, explicit_end=explicit_end) 134 dumper.open() 135 for node in nodes: 136 dumper.serialize(node) 137 dumper.close() 138 if getvalue: 139 return getvalue() 140 141 def serialize(node, stream=None, Dumper=Dumper, **kwds): 142 """ 143 Serialize a representation tree into a YAML stream. 144 If stream is None, return the produced string instead. 145 """ 146 return serialize_all([node], stream, Dumper=Dumper, **kwds) 147 148 def dump_all(documents, stream=None, Dumper=Dumper, 149 canonical=None, indent=None, width=None, 150 allow_unicode=None, line_break=None, 151 encoding='utf-8', explicit_start=None, explicit_end=None, 152 version=None, tags=None): 153 """ 154 Serialize a sequence of Python objects into a YAML stream. 155 If stream is None, return the produced string instead. 156 """ 157 getvalue = None 158 if stream is None: 159 try: 160 from cStringIO import StringIO 161 except ImportError: 162 from StringIO import StringIO 163 stream = StringIO() 164 getvalue = stream.getvalue 165 dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, 166 allow_unicode=allow_unicode, line_break=line_break, 167 encoding=encoding, version=version, tags=tags, 168 explicit_start=explicit_start, explicit_end=explicit_end) 169 dumper.open() 170 for data in documents: 171 dumper.represent(data) 172 dumper.close() 173 if getvalue: 174 return getvalue() 175 176 def dump(data, stream=None, Dumper=Dumper, **kwds): 177 """ 178 Serialize a Python object into a YAML stream. 179 If stream is None, return the produced string instead. 180 """ 181 return dump_all([data], stream, Dumper=Dumper, **kwds) 182 183 def safe_dump_all(documents, stream=None, **kwds): 184 """ 185 Serialize a sequence of Python objects into a YAML stream. 186 Produce only basic YAML tags. 187 If stream is None, return the produced string instead. 188 """ 189 return dump_all(documents, stream, Dumper=SafeDumper, **kwds) 190 191 def safe_dump(data, stream=None, **kwds): 192 """ 193 Serialize a Python object into a YAML stream. 194 Produce only basic YAML tags. 195 If stream is None, return the produced string instead. 196 """ 197 return dump_all([data], stream, Dumper=SafeDumper, **kwds) 198 199 def add_detector(tag, regexp, first=None, Loader=Loader, Dumper=Dumper): 200 """ 201 Add an implicit scalar detector. 202 If an implicit scalar value matches the given regexp, 203 the corresponding tag is assigned to the scalar. 204 first is a sequence of possible initial characters or None. 205 """ 206 Loader.add_detector(tag, regexp, first) 207 Dumper.add_detector(tag, regexp, first) 208 209 def add_resolver(tag, path, Loader=Loader): 210 """ 211 Add a path based resolver for the given tag. 212 A path is a list of keys that forms a path 213 to a node in the representation tree. 214 Keys can be string values, integers, or None. 215 """ 216 Loader.add_resolver(tag, path) 217 218 def add_constructor(tag, constructor, Loader=Loader): 219 """ 220 Add a constructor for the given tag. 221 Constructor is a function that accepts a Loader instance 222 and a node object and produces the corresponding Python object. 223 """ 224 Loader.add_constructor(tag, constructor) 225 226 def add_multi_constructor(tag_prefix, multi_constructor, Loader=Loader): 227 """ 228 Add a multi-constructor for the given tag prefix. 229 Multi-constructor is called for a node if its tag starts with tag_prefix. 230 Multi-constructor accepts a Loader instance, a tag suffix, 231 and a node object and produces the corresponding Python object. 232 """ 233 Loader.add_multi_constructor(tag_prefix, multi_constructor) 234 235 class YAMLObjectMetaclass(type): 236 """ 237 The metaclass for YAMLObject. 238 """ 239 def __init__(cls, name, bases, kwds): 240 super(YAMLObjectMetaclass, cls).__init__(name, bases, kwds) 241 if 'yaml_tag' in kwds and kwds['yaml_tag'] is not None: 242 cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml) 243 cls.yaml_dumper.add_representer(cls, cls.to_yaml) 244 245 class YAMLObject(object): 246 """ 247 An object that can dump itself to a YAML stream 248 and load itself from a YAML stream. 249 """ 250 251 __metaclass__ = YAMLObjectMetaclass 252 253 yaml_loader = Loader 254 yaml_dumper = Dumper 255 256 yaml_tag = None 257 yaml_flow_style = None 258 259 def from_yaml(cls, loader, node): 260 """ 261 Convert a representation node to a Python object. 262 """ 263 return loader.construct_yaml_object(node, cls) 264 from_yaml = classmethod(from_yaml) 265 266 def to_yaml(cls, dumper, data): 267 """ 268 Convert a Python object to a representation node. 269 """ 270 return dumper.represent_yaml_object(cls.yaml_tag, data, cls, 271 flow_style=cls.yaml_flow_style) 272 to_yaml = classmethod(to_yaml) 273 -
pyyaml/trunk/lib/yaml/composer.py
r133 r136 1 1 2 __all__ = [' Composer', 'ComposerError']2 __all__ = ['BaseComposer', 'Composer', 'ComposerError'] 3 3 4 4 from error import MarkedYAMLError … … 9 9 pass 10 10 11 class Composer:11 class BaseComposer: 12 12 13 def __init__(self, parser): 14 self.parser = parser 13 yaml_resolvers = {} 14 15 def __init__(self): 15 16 self.all_anchors = {} 16 17 self.complete_anchors = {} 18 self.resolver_tags = [] 19 self.resolver_paths = [] 17 20 18 # Drop the STREAM-START event. 19 self.parser.get() 21 def check_node(self): 22 # If there are more documents available? 23 return not self.check_event(StreamEndEvent) 20 24 21 def check(self): 22 # If there are more documents available? 23 return not self.parser.check(StreamEndEvent) 24 25 def get(self): 25 def get_node(self): 26 26 # Get the root node of the next document. 27 if not self. parser.check(StreamEndEvent):27 if not self.check_event(StreamEndEvent): 28 28 return self.compose_document() 29 29 30 30 def __iter__(self): 31 31 # Iterator protocol. 32 while not self. parser.check(StreamEndEvent):32 while not self.check_event(StreamEndEvent): 33 33 yield self.compose_document() 34 34 35 35 def compose_document(self): 36 36 37 # Drop the STREAM-START event. 38 if self.check_event(StreamStartEvent): 39 self.get_event() 40 37 41 # Drop the DOCUMENT-START event. 38 self. parser.get()42 self.get_event() 39 43 40 44 # Compose the root node. 41 node = self.compose_node( )45 node = self.compose_node([]) 42 46 43 47 # Drop the DOCUMENT-END event. 44 self. parser.get()48 self.get_event() 45 49 46 50 self.all_anchors = {} 47 51 self.complete_anchors = {} 52 self.resolver_tags = [] 53 self.resolver_paths = [] 48 54 return node 49 55 50 def compose_node(self): 51 if self.parser.check(AliasEvent): 52 event = self.parser.get() 56 def increase_resolver_depth(self, path): 57 depth = len(path) 58 tag = None 59 paths = [] 60 if not depth: 61 for resolver_path in self.yaml_resolvers.keys(): 62 if resolver_path: 63 paths.append(resolver_path) 64 else: 65 tag = self.yaml_resolvers[resolver_path] 66 else: 67 base, index = path[-1] 68 if isinstance(index, ScalarNode) \ 69 and index.tag == self.DEFAULT_SCALAR_TAG: 70 index = index.value 71 elif isinstance(index, Node): 72 index = None 73 for resolver_path in self.resolver_paths[-1]: 74 resolver_index = resolver_path[depth-1] 75 if resolver_index is None or resolver_index == index: 76 if len(resolver_index) > depth: 77 paths.append(resolver_path) 78 else: 79 tag = self.yaml_resolvers[resolver_path] 80 self.resolver_tags.append(tag) 81 self.resolver_paths.append(paths) 82 83 def decrease_resolver_depth(self): 84 del self.resolver_tags[-1] 85 del self.resolver_paths[-1] 86 87 def compose_node(self, path): 88 if self.check_event(AliasEvent): 89 event = self.get_event() 53 90 anchor = event.anchor 54 91 if anchor not in self.all_anchors: … … 62 99 event.start_mark) 63 100 return self.complete_anchors[anchor] 64 event = self.parser.peek() 101 self.increase_resolver_depth(path) 102 event = self.peek_event() 65 103 anchor = event.anchor 66 104 if anchor is not None: … … 70 108 "second occurence", event.start_mark) 71 109 self.all_anchors[anchor] = event 72 if self. parser.check(ScalarEvent):73 node = self.compose_scalar_node( )74 elif self. parser.check(SequenceStartEvent):75 node = self.compose_sequence_node( )76 elif self. parser.check(MappingStartEvent):77 node = self.compose_mapping_node( )110 if self.check_event(ScalarEvent): 111 node = self.compose_scalar_node(path) 112 elif self.check_event(SequenceStartEvent): 113 node = self.compose_sequence_node(path) 114 elif self.check_event(MappingStartEvent): 115 node = self.compose_mapping_node(path) 78 116 if anchor is not None: 79 117 self.complete_anchors[anchor] = node 118 self.decrease_resolver_depth() 80 119 return node 81 120 82 def compose_scalar_node(self): 83 event = self.parser.get() 84 return ScalarNode(event.tag, event.value, event.implicit, 121 def compose_scalar_node(self, path): 122 event = self.get_event() 123 tag = self.resolve_scalar(path, event.tag, event.implicit, event.value) 124 return ScalarNode(tag, event.value, 85 125 event.start_mark, event.end_mark, style=event.style) 86 126 87 def compose_sequence_node(self): 88 start_event = self.parser.get() 89 value = [] 90 while not self.parser.check(SequenceEndEvent): 91 value.append(self.compose_node()) 92 end_event = self.parser.get() 93 return SequenceNode(start_event.tag, value, 94 start_event.start_mark, end_event.end_mark, 127 def compose_sequence_node(self, path): 128 start_event = self.get_event() 129 tag = self.resolve_sequence(path, start_event.tag) 130 node = SequenceNode(tag, [], 131 start_event.start_mark, None, 95 132 flow_style=start_event.flow_style) 133 index = 0 134 while not self.check_event(SequenceEndEvent): 135 node.value.append(self.compose_node(path+[(node, index)])) 136 index += 1 137 end_event = self.get_event() 138 node.end_mark = end_event.end_mark 139 return node 96 140 97 def compose_mapping_node(self): 98 start_event = self.parser.get() 99 value = {} 100 while not self.parser.check(MappingEndEvent): 101 key_event = self.parser.peek() 102 item_key = self.compose_node() 103 item_value = self.compose_node() 104 if item_key in value: 141 def compose_mapping_node(self, path): 142 start_event = self.get_event() 143 tag = self.resolve_mapping(path, start_event.tag) 144 node = MappingNode(tag, {}, 145 start_event.start_mark, None, 146 flow_style=start_event.flow_style) 147 while not self.check_event(MappingEndEvent): 148 key_event = self.peek_event() 149 item_key = self.compose_node(path+[(node, None)]) 150 item_value = self.compose_node(path+[(node, item_key)]) 151 if item_key in node.value: 105 152 raise ComposerError("while composing a mapping", start_event.start_mark, 106 153 "found duplicate key", key_event.start_mark) 107 value[item_key] = item_value 108 end_event = self.parser.get() 109 return MappingNode(start_event.tag, value, 110 start_event.start_mark, end_event.end_mark, 111 flow_style=start_event.flow_style) 154 node.value[item_key] = item_value 155 end_event = self.get_event() 156 node.end_mark = end_event.end_mark 157 return node 112 158 159 def resolve_scalar(self, path, tag, implicit, value): 160 if implicit: 161 tag = self.detect(value) 162 if tag is None and self.resolver_tags[-1]: 163 tag = self.resolver_tags[-1] 164 if tag is None or tag == u'!': 165 tag = self.DEFAULT_SCALAR_TAG 166 return tag 167 168 def resolve_sequence(self, path, tag): 169 if tag is None and self.resolver_tags[-1]: 170 tag = self.resolver_tags[-1] 171 if tag is None or tag == u'!': 172 tag = self.DEFAULT_SEQUENCE_TAG 173 return tag 174 175 def resolve_mapping(self, path, tag): 176 if tag is None and self.resolver_tags[-1]: 177 tag = self.resolver_tags[-1] 178 if tag is None or tag == u'!': 179 tag = self.DEFAULT_MAPPING_TAG 180 return tag 181 182 def add_resolver(self, tag, path): 183 if not 'yaml_resolvers' in cls.__dict__: 184 cls.yaml_resolvers = cls.yaml_resolvers.copy() 185 cls.yaml_resolvers[tuple(path)] = tag 186 add_resolver = classmethod(add_resolver) 187 188 class Composer(BaseComposer): 189 pass 190 -
pyyaml/trunk/lib/yaml/constructor.py
r133 r136 5 5 from error import * 6 6 from nodes import * 7 from composer import * 7 8 8 9 try: … … 22 23 pass 23 24 24 class BaseConstructor: 25 26 def __init__(self, resolver): 27 self.resolver = resolver 25 class BaseConstructor(Composer): 26 27 yaml_constructors = {} 28 yaml_multi_constructors = {} 29 30 def __init__(self): 28 31 self.constructed_objects = {} 29 32 30 def check (self):33 def check_data(self): 31 34 # If there are more documents available? 32 return self. resolver.check()33 34 def get (self):35 return self.check_node() 36 37 def get_data(self): 35 38 # Construct and return the next document. 36 if self. resolver.check():37 return self.construct_document(self. resolver.get())39 if self.check_node(): 40 return self.construct_document(self.get_node()) 38 41 39 42 def __iter__(self): 40 43 # Iterator protocol. 41 while self. resolver.check():42 yield self.construct_document(self. resolver.get())44 while self.check_node(): 45 yield self.construct_document(self.get_node()) 43 46 44 47 def construct_document(self, node): 45 native= self.construct_object(node)48 data = self.construct_object(node) 46 49 self.constructed_objects = {} 47 return native50 return data 48 51 49 52 def construct_object(self, node): 50 53 if node in self.constructed_objects: 51 54 return self.constructed_objects[node] 55 constructor = None 52 56 if node.tag in self.yaml_constructors: 53 native = self.yaml_constructors[node.tag](self, node) 54 elif None in self.yaml_constructors: 55 native = self.yaml_constructors[None](self, node) 56 elif isinstance(node, ScalarNode): 57 native = self.construct_scalar(node) 58 elif isinstance(node, SequenceNode): 59 native = self.construct_sequence(node) 60 elif isinstance(node, MappingNode): 61 native = self.construct_mapping(node) 62 self.constructed_objects[node] = native 63 return native 57 constructor = lambda node: self.yaml_constructors[node.tag](self, node) 58 else: 59 for tag_prefix in self.yaml_multi_constructors: 60 if node.tag.startswith(tag_prefix): 61 tag_suffix = node.tag[len(tag_prefix):] 62 constructor = lambda node: \ 63 self.yaml_multi_constructors[tag_prefix](self, tag_suffix, node) 64 break 65 else: 66 if None in self.yaml_multi_constructors: 67 constructor = lambda node: \ 68 self.yaml_multi_constructors[None](self, node.tag, node) 69 elif None in self.yaml_constructors: 70 constructor = lambda node: \ 71 self.yaml_constructors[None](self, node) 72 elif isinstance(node, ScalarNode): 73 constructor = self.construct_scalar 74 elif isinstance(node, SequenceNode): 75 constructor = self.construct_sequence 76 elif isinstance(node, MappingNode): 77 constructor = self.construct_mapping 78 data = constructor(node) 79 self.constructed_objects[node] = data 80 return data 64 81 65 82 def construct_scalar(self, node): … … 153 170 add_constructor = classmethod(add_constructor) 154 171 155 yaml_constructors = {} 172 def add_multi_constructor(cls, tag_prefix, multi_constructor): 173 if not 'yaml_multi_constructors' in cls.__dict__: 174 cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy() 175 cls.yaml_multi_constructors[tag_prefix] = multi_constructor 176 add_multi_constructor = classmethod(add_multi_constructor) 156 177 157 178 class SafeConstructor(BaseConstructor): … … 328 349 return self.construct_mapping(node) 329 350 351 def construct_yaml_object(self, node, cls): 352 mapping = self.construct_mapping(node) 353 state = {} 354 for key in mapping: 355 state[key.replace('-', '_')] = mapping[key] 356 data = cls.__new__(cls) 357 if hasattr(data, '__setstate__'): 358 data.__setstate__(mapping) 359 else: 360 data.__dict__.update(mapping) 361 return data 362 330 363 def construct_undefined(self, node): 331 364 raise ConstructorError(None, None, -
pyyaml/trunk/lib/yaml/detector.py
r133 r136 6 6 class BaseDetector: 7 7 8 DEFAULT_SCALAR_TAG = u'tag:yaml.org,2002:str' 9 DEFAULT_SEQUENCE_TAG = u'tag:yaml.org,2002:seq' 10 DEFAULT_MAPPING_TAG = u'tag:yaml.org,2002:map' 11 8 12 yaml_detectors = {} 13 14 def __init__(self): 15 pass 9 16 10 17 def add_detector(cls, tag, regexp, first): -
pyyaml/trunk/lib/yaml/emitter.py
r133 r136 12 12 from events import * 13 13 14 import re 15 14 16 class EmitterError(YAMLError): 15 17 pass … … 18 20 def __init__(self, scalar, empty, multiline, 19 21 allow_flow_plain, allow_block_plain, 20 allow_single_quoted, allow_double_quoted, allow_block): 22 allow_single_quoted, allow_double_quoted, 23 allow_block): 21 24 self.scalar = scalar 22 25 self.empty = empty … … 35 38 } 36 39 37 def __init__(self, writer): 38 39 # The writer should have the methods `write` and possibly `flush`. 40 self.writer = writer 41 42 # Encoding is provided by STREAM-START. 40 def __init__(self, stream, canonical=None, indent=None, width=None, 41 allow_unicode=None, line_break=None): 42 43 # The stream should have the methods `write` and possibly `flush`. 44 self.stream = stream 45 46 # Encoding can be overriden by STREAM-START. 43 47 self.encoding = None 44 48 … … 76 80 77 81 # Formatting details. 78 self.canonical = False 79 self.allow_unicode = False 82 self.canonical = canonical 83 self.allow_unicode = allow_unicode 84 self.best_indent = 2 85 if indent and 1 < indent < 10: 86 self.best_indent = indent 87 self.best_width = 80 88 if width and width > self.best_indent*2: 89 self.best_width = width 80 90 self.best_line_break = u'\n' 81 self.best_indent = 2 82 self.best_width = 80 91 if line_break in [u'\r', u'\n', u'\r\n']: 92 self.best_line_break = line_break 93 94 # Tag prefixes. 83 95 self.tag_prefixes = None 84 96 85 # Analyses cache. 86 self.anchor_text = None 87 self.tag_text = None 88 self.scalar_analysis = None 89 self.scalar_style = None 97 # Prepared anchor and tag. 98 self.prepared_anchor = None 99 self.prepared_tag = None 100 101 # Scalar analysis and style. 102 self.analysis = None 103 self.style = None 90 104 91 105 def emit(self, event): … … 140 154 def expect_stream_start(self): 141 155 if isinstance(self.event, StreamStartEvent): 142 self.encoding = self.event.encoding 143 self.canonical = self.event.canonical 144 self.allow_unicode = self.event.allow_unicode 145 if self.event.indent and self.event.indent > 1: 146 self.best_indent = self.event.indent 147 if self.event.width and self.event.width > self.best_indent: 148 self.best_width = self.event.width 149 if self.event.line_break in [u'\r', u'\n', u'\r\n']: 150 self.best_line_break = self.event.line_break 156 if self.event.encoding: 157 self.encoding = self.event.encoding 151 158 self.write_stream_start() 152 159 self.state = self.expect_first_document_start … … 166 173 if isinstance(self.event, DocumentStartEvent): 167 174 if self.event.version: 168 version_text = self. analyze_version(self.event.version)175 version_text = self.prepare_version(self.event.version) 169 176 self.write_version_directive(version_text) 170 177 self.tag_prefixes = self.DEFAULT_TAG_PREFIXES.copy() … … 175 182 prefix = self.event.tags[handle] 176 183 self.tag_prefixes[prefix] = handle 177 handle_text = self. analyze_tag_handle(handle)178 prefix_text = self. analyze_tag_prefix(prefix)184 handle_text = self.prepare_tag_handle(handle) 185 prefix_text = self.prepare_tag_prefix(prefix) 179 186 self.write_tag_directive(handle_text, prefix_text) 180 187 implicit = (first and not self.event.explicit and not self.canonical … … 200 207 self.write_indicator(u'...', True) 201 208 self.write_indent() 209 self.flush_stream() 202 210 self.state = self.expect_document_start 203 211 else: … … 419 427 length = 0 420 428 if isinstance(self.event, NodeEvent) and self.event.anchor is not None: 421 if self. anchor_textis None:422 self. anchor_text = self.analyze_anchor(self.event.anchor)423 length += len(self. anchor_text)429 if self.prepared_anchor is None: 430 self.prepared_anchor = self.prepare_anchor(self.event.anchor) 431 length += len(self.prepared_anchor) 424 432 if isinstance(self.event, (ScalarEvent, CollectionStartEvent)) \ 425 433 and self.event.tag is not None: 426 if self. tag_textis None:427 self. tag_text = self.analyze_tag(self.event.tag)428 length += len(self. tag_text)434 if self.prepared_tag is None: 435 self.prepared_tag = self.prepare_tag(self.event.tag) 436 length += len(self.prepared_tag) 429 437 if isinstance(self.event, ScalarEvent): 430 if self. scalar_analysis is None:431 self. scalar_analysis = self.analyze_scalar(self.event.value)432 length += len(self. scalar_analysis.scalar)438 if self.analysis is None: 439 self.analysis = self.analyze_scalar(self.event.value) 440 length += len(self.analysis.scalar) 433 441 return (length < 128 and (isinstance(self.event, AliasEvent) 434 or (isinstance(self.event, ScalarEvent) and not self.scalar_analysis.multiline) 442 or (isinstance(self.event, ScalarEvent) 443 and not self.analysis.empty and not self.analysis.multiline) 435 444 or self.check_empty_sequence() or self.check_empty_mapping())) 436 445 … … 439 448 def process_anchor(self, indicator): 440 449 if self.event.anchor is None: 450 self.prepared_anchor = None 441 451 return 442 if self. anchor_textis None:443 self. anchor_text = self.analyze_anchor(self.event.anchor)444 if self. anchor_text:445 self.write_indicator(indicator+self. anchor_text, True)446 self. anchor_text= None452 if self.prepared_anchor is None: 453 self.prepared_anchor = self.prepare_anchor(self.event.anchor) 454 if self.prepared_anchor: 455 self.write_indicator(indicator+self.prepared_anchor, True) 456 self.prepared_anchor = None 447 457 448 458 def process_tag(self): 449 if self.event.tag is None: 459 tag = self.event.tag 460 if isinstance(self.event, ScalarEvent): 461 if self.style is None: 462 self.style = self.choose_scalar_style() 463 if self.style == '': 464 self.prepared_tag = None 465 return 466 if self.event.implicit and not tag: 467 tag = u'!' 468 self.prepared_tag = None 469 if not tag: 470 self.prepared_tag = None 450 471 return 451 if isinstance(self.event, ScalarEvent) and self.best_scalar_style() == '': 452 return 453 if self.tag_text is None: 454 self.tag_text = self.analyze_tag(self.event.tag) 455 if self.tag_text: 456 self.write_indicator(self.tag_text, True) 457 self.tag_text = None 458 459 def best_scalar_style(self): 460 if self.scalar_analysis is None: 461 self.scalar_analysis = self.analyze_scalar(self.event.value) 462 if self.canonical: 472 if self.prepared_tag is None: 473 self.prepared_tag = self.prepare_tag(tag) 474 if self.prepared_tag: 475 self.write_indicator(self.prepared_tag, True) 476 self.prepared_tag = None 477 478 def choose_scalar_style(self): 479 if self.analysis is None: 480 self.analysis = self.analyze_scalar(self.event.value) 481 if self.event.style == '"' or self.canonical: 463 482 return '"' 464 if (self.event.implicit and not self.event.style 465 and ((self.flow_level and self.scalar_analysis.allow_flow_plain) 466 or (not self.flow_level and self.scalar_analysis.allow_block_plain)) 467 and (len(self.scalar_analysis.scalar) > 0 468 or (not self.flow_level and not self.simple_key_context))): 469 return '' 470 elif self.event.style == '\'' and self.scalar_analysis.allow_single_quoted: 471 return '\'' 472 elif self.event.style in ['|', '>'] and not self.flow_level and self.scalar_analysis.allow_block: 473 return self.event.style 474 else: 475 return '"' 476 return style 483 if not self.event.style and self.event.implicit: 484 if (not (self.simple_key_context and 485 (self.analysis.empty or self.analysis.multiline)) 486 and (self.flow_level and self.analysis.allow_flow_plain 487 or (not self.flow_level and self.analysis.allow_block_plain))): 488 return '' 489 if self.event.style and self.event.style in '|>': 490 if not self.flow_level and self.analysis.allow_block: 491 return self.event.style 492 if not self.event.style or self.event.style == '\'': 493 if (self.analysis.allow_single_quoted and 494 not (self.simple_key_context and self.analysis.multiline)): 495 return '\'' 496 return '"' 477 497 478 498 def process_scalar(self): 479 if self. scalar_analysis is None:480 self. scalar_analysis = self.analyze_scalar(self.event.value)481 style = self.best_scalar_style()482 if self.scalar_analysis.multiline and not self.simple_key_context \483 and style not in ['|', '>']:484 self.write_indent()485 if style == '"':486 self.write_double_quoted(self.scalar_analysis.scalar,487 split=(not self.simple_key_context))488 elif style == '\'':489 self.write_single_quoted(self.scalar_analysis.scalar,490 split=(not self.simple_key_context))491 elif s tyle == '>':492 self.write_folded(self. scalar_analysis.scalar)493 elif s tyle == '|':494 self.write_literal(self. scalar_analysis.scalar)495 else: 496 self.write_plain(self. scalar_analysis.scalar,497 split=(not self.simple_key_context))498 self.s calar_analysis= None499 if self.analysis is None: 500 self.analysis = self.analyze_scalar(self.event.value) 501 if self.style is None: 502 self.style = self.choose_scalar_style() 503 split = (not self.simple_key_context) 504 #if self.analysis.multiline and split \ 505 # and (not self.style or self.style in '\'\"'): 506 # self.write_indent() 507 if self.style == '"': 508 self.write_double_quoted(self.analysis.scalar, split) 509 elif self.style == '\'': 510 self.write_single_quoted(self.analysis.scalar, split) 511 elif self.style == '>': 512 self.write_folded(self.analysis.scalar) 513 elif self.style == '|': 514 self.write_literal(self.analysis.scalar) 515 else: 516 self.write_plain(self.analysis.scalar, split) 517 self.analysis = None 518 self.style = None 499 519 500 520 # Analyzers. 501 521 502 def analyze_version(self, version):522 def prepare_version(self, version): 503 523 major, minor = version 504 524 if major != 1: … … 506 526 return u'%d.%d' % (major, minor) 507 527 508 def analyze_tag_handle(self, handle):528 def prepare_tag_handle(self, handle): 509 529 if not handle: 510 530 raise EmitterError("tag handle must not be empty") … … 519 539 return handle 520 540 521 def analyze_tag_prefix(self, prefix):541 def prepare_tag_prefix(self, prefix): 522 542 if not prefix: 523 543 raise EmitterError("tag prefix must not be empty") … … 542 562 return u''.join(chunks) 543 563 544 def analyze_tag(self, tag):564 def prepare_tag(self, tag): 545 565 if not tag: 546 566 raise EmitterError("tag must not be empty") 567 if tag == u'!': 568 return tag 547 569 handle = None 548 570 suffix = tag … … 575 597 return u'!<%s>' % suffix_text 576 598 577 def analyze_anchor(self, anchor):599 def prepare_anchor(self, anchor): 578 600 if not anchor: 579 601 raise EmitterError("anchor must not be empty") … … 585 607 return anchor 586 608 587 def analyze_scalar(self, scalar): # It begs for refactoring. 609 def analyze_scalar(self, scalar): 610 611 # Empty scalar is a special case. 588 612 if not scalar: 589 613 return ScalarAnalysis(scalar=scalar, empty=True, multiline=False, … … 591 615 allow_single_quoted=True, allow_double_quoted=True, 592 616 allow_block=False) 593 contains_block_indicator = False 594 contains_flow_indicator = False 595 contains_line_breaks = False 596 contains_unicode_characters = False 597 contains_special_characters = False 598 contains_inline_spaces = False # non-space space+ non-space 599 contains_inline_breaks = False # non-space break+ non-space 600 contains_leading_spaces = False # ^ space+ (non-space | $) 601 contains_leading_breaks = False # ^ break+ (non-space | $) 602 contains_trailing_spaces = False # non-space space+ $ 603 contains_trailing_breaks = False # non-space break+ $ 604 contains_inline_breaks_spaces = False # non-space break+ space+ non-space 605 contains_mixed_breaks_spaces = False # anything else 617 618 # Indicators and special characters. 619 block_indicators = False 620 flow_indicators = False 621 line_breaks = False 622 special_characters = False 623 624 # Whitespaces. 625 inline_spaces = False # non-space space+ non-space 626 inline_breaks = False # non-space break+ non-space 627 leading_spaces = False # ^ space+ (non-space | $) 628 leading_breaks = False # ^ break+ (non-space | $) 629 trailing_spaces = False # (^ | non-space) space+ $ 630 trailing_breaks = False # (^ | non-space) break+ $ 631 inline_breaks_spaces = False # non-space break+ space+ non-space 632 mixed_breaks_spaces = False # anything else 633 634 # Check document indicators. 606 635 if scalar.startswith(u'---') or scalar.startswith(u'...'): 607 contains_block_indicator = True 608 contains_flow_indicator = True 609 first = True 610 last = (len(scalar) == 1) 611 preceeded_by_space = False 612 followed_by_space = (len(scalar) > 1 and 636 block_indicators = True 637 flow_indicators = True 638 639 # First character or preceded by a whitespace. 640 preceeded_by_space = True 641 642 # Last character or followed by a whitespace. 643 followed_by_space = (len(scalar) == 1 or 613 644 scalar[1] in u'\0 \t\r\n\x85\u2028\u2029') 614 spaces = breaks = mixed = leading = False 645 646 # The current series of whitespaces contain plain spaces. 647 spaces = False 648 649 # The current series of whitespaces contain line breaks. 650 breaks = False 651 652 # The current series of whitespaces contain a space followed by a 653 # break. 654 mixed = False 655 656 # The current series of whitespaces start at the beginning of the 657 # scalar. 658 leading = False 659 615 660 index = 0 616 661 while index < len(scalar): 617 662 ch = scalar[index] 618 if first: 663 664 # Check for indicators. 665 666 if index == 0: 667 # Leading indicators are special characters. 619 668 if ch in u'#,[]{}#&*!|>\'\"%@`': 620 contains_flow_indicator= True621 contains_block_indicator= True669 flow_indicators = True 670 block_indicators = True 622 671 if ch in u'?:': 623 contains_flow_indicator= True624 if followed_by_space or last:625 contains_block_indicator= True626 if ch == u'-' and (followed_by_space or last):627 contains_flow_indicator= True628 contains_block_indicator= True672 flow_indicators = True 673 if followed_by_space: 674 block_indicators = True 675 if ch == u'-' and followed_by_space: 676 flow_indicators = True 677 block_indicators = True 629 678 else: 679 # Some indicators cannot appear within a scalar as well. 630 680 if ch in u',?[]{}': 631 contains_flow_indicator= True681 flow_indicators = True 632 682 if ch == u':': 633 contains_flow_indicator = True 634 if followed_by_space or last: 635 contains_block_indicator = True 636 if ch == u'#' and (preceeded_by_space or first): 637 contains_flow_indicator = True 638 contains_block_indicator = True 683 flow_indicators = True 684 if followed_by_space: 685 block_indicators = True 686 if ch == u'#' and preceeded_by_space: 687 flow_indicators = True 688 block_indicators = True 689 690 # Check for line breaks, special, and unicode characters. 691 639 692 if ch in u'\n\x85\u2028\u2029': 640 contains_line_breaks = True693 line_breaks = True 641 694 if not (ch == u'\n' or u'\x20' <= ch <= u'\x7E'): 642 if ch < u'\x80' :643 contains_special_characters = True695 if ch < u'\x80' or ch == u'\uFEFF': # '\uFEFF' is BOM. 696 special_characters = True 644 697 else: 645 contains_unicode_characters = True 646 if ch == u' ': 647 if not spaces and not breaks: 648 leading = first 649 spaces = True 650 elif ch in u'\n\x85\u2028\u2029': 651 if not spaces and not breaks: 652 leading = first 653 breaks = True 654 if spaces: 655 mixed = True 656 if ch not in u' \n\x85\u2028\u2029': 698 unicode_characters = True 699 if not self.allow_unicode: 700 special_characters = True 701 702 # Spaces, line breaks, and how they are mixed. State machine. 703 704 # Start or continue series of whitespaces. 705 if ch in u' \n\x85\u2028\u2029': 706 if spaces and breaks: 707 if ch != u' ': # break+ (space+ break+) => mixed 708 mixed = True 709 elif spaces: 710 if ch != u' ': # (space+ break+) => mixed 711 breaks = True 712 mixed = True 713 elif breaks: 714 if ch == u' ': # break+ space+ 715 spaces = True 716 else: 717 leading = (index == 0) 718 if ch == u' ': # space+ 719 spaces = True 720 else: # break+ 721 breaks = True 722 723 # Series of whitespaces ended with a non-space. 724 elif spaces or breaks: 657 725 if leading: 658 726 if spaces and breaks: 659 contains_mixed_breaks_spaces = True727 mixed_breaks_spaces = True 660 728 elif spaces: 661 contains_leading_spaces = True729 leading_spaces = True 662 730 elif breaks: 663 contains_leading_breaks = True731 leading_breaks = True 664 732 else: 665 733 if mixed: 666 contains_mixed_break_spaces = True734 mixed_breaks_spaces = True 667 735 elif spaces and breaks: 668 contains_inline_breaks_spaces = True736 inline_breaks_spaces = True 669 737 elif spaces: 670 contains_inline_spaces = True738 inline_spaces = True 671 739 elif breaks: 672 contains_inline_breaks = True740 inline_breaks = True 673 741 spaces = breaks = mixed = leading = False 674 elif last: 742 743 # Series of whitespaces reach the end. 744 if (spaces or breaks) and (index == len(scalar)-1): 675 745 if spaces and breaks: 676 contains_mixed_break_spaces = True746 mixed_breaks_spaces = True 677 747 elif spaces: 748 trailing_spaces = True 678 749 if leading: 679 contains_leading_spaces = True 680 else: 681 contains_trailing_spaces = True 750 leading_spaces = True 682 751 elif breaks: 752 trailing_breaks = True 683 753 if leading: 684 contains_leading_breaks = True 685 else: 686 contains_trailing_breaks = True 754 leading_breaks = True 755 spaces = breaks = mixed = leading = False 756 757 # Prepare for the next character. 687 758 index += 1 688 first = False689 last = (index+1 == len(scalar))690 759 preceeded_by_space = (ch in u'\0 \t\r\n\x85\u2028\u2029') 691 followed_by_space = (index+1 < len(scalar) and760 followed_by_space = (index+1 >= len(scalar) or 692 761 scalar[index+1] in u'\0 \t\r\n\x85\u2028\u2029') 693 if contains_unicode_characters and not self.allow_unicode: 694 contains_special_characters = True 695 allow_flow_plain = not (contains_flow_indicator or contains_special_characters 696 or contains_leading_spaces or contains_leading_breaks 697 or contains_trailing_spaces or contains_trailing_breaks 698 or contains_inline_breaks_spaces or contains_mixed_breaks_spaces) 699 allow_block_plain = not (contains_block_indicator or contains_special_characters 700 or contains_leading_spaces or contains_leading_breaks 701 or contains_trailing_spaces or contains_trailing_breaks 702 or contains_inline_breaks_spaces or contains_mixed_breaks_spaces) 703 allow_single_quoted = not (contains_special_characters 704 or contains_inline_breaks_spaces or contains_mixed_breaks_spaces) 762 763 # Let's decide what styles are allowed. 764 allow_flow_plain = True 765 allow_block_plain = True 766 allow_single_quoted = True 705 767 allow_double_quoted = True 706 allow_block = not (contains_special_characters 707 or contains_leading_spaces or contains_leading_breaks 708 or contains_trailing_spaces or contains_mixed_breaks_spaces) 709 return ScalarAnalysis(scalar=scalar, empty=False, multiline=contains_line_breaks, 710 allow_flow_plain=allow_flow_plain, allow_block_plain=allow_block_plain, 711 allow_single_quoted=allow_single_quoted, allow_double_quoted=allow_double_quoted, 768 allow_block = True 769 770 # Leading and trailing whitespace are bad for plain scalars. We also 771 # do not want to mess with leading whitespaces for block scalars. 772 if leading_spaces or leading_breaks or trailing_spaces: 773 allow_flow_plain = allow_block_plain = allow_block = False 774 775 # Trailing breaks are fine for block scalars, but unacceptable for 776 # plain scalars. 777 if trailing_breaks: 778 allow_flow_plain = allow_block_plain = False 779 780 # The combination of (space+ break+) is only acceptable for block 781 # scalars. 782 if inline_breaks_spaces: 783 allow_flow_plain = allow_block_plain = allow_single_quoted = False 784 785 # Mixed spaces and breaks, as well as special character are only 786 # allowed for double quoted scalars. 787 if mixed_breaks_spaces or special_characters: 788 allow_flow_plain = allow_block_plain = \ 789 allow_single_quoted = allow_block = False 790 791 # We don't emit multiline plain scalars. 792 if line_breaks: 793 allow_flow_plain = allow_block_plain = False 794 795 # Flow indicators are forbidden for flow plain scalars. 796 if flow_indicators: 797 allow_flow_plain = False 798 799 # Block indicators are forbidden for block plain scalars. 800 if block_indicators: 801 allow_block_plain = False 802 803 return ScalarAnalysis(scalar=scalar, 804 empty=False, multiline=line_breaks, 805 allow_flow_plain=allow_flow_plain, 806 allow_block_plain=allow_block_plain, 807 allow_single_quoted=allow_single_quoted, 808 allow_double_quoted=allow_double_quoted, 712 809 allow_block=allow_block) 713 810 714 811 # Writers. 812 813 def flush_stream(self): 814 if hasattr(self.stream, 'flush'): 815 self.stream.flush() 715 816 716 817 def write_stream_start(self): 717 818 # Write BOM if needed. 718 819 if self.encoding and self.encoding.startswith('utf-16'): 719 self. writer.write(u'\xFF\xFE'.encode(self.encoding))820 self.stream.write(u'\xFF\xFE'.encode(self.encoding)) 720 821 721 822 def write_stream_end(self): 722 if hasattr(self.writer, 'flush'): 723 self.writer.flush() 823 self.flush_stream() 724 824 725 825 def write_indicator(self, indicator, need_whitespace, … … 734 834 if self.encoding: 735 835 data = data.encode(self.encoding) 736 self. writer.write(data)836 self.stream.write(data) 737 837 738 838 def write_indent(self): … … 747 847 if self.encoding: 748 848 data = data.encode(self.encoding) 749 self. writer.write(data)849 self.stream.write(data) 750 850 751 851 def write_line_break(self, data=None): … … 758 858 if self.encoding: 759 859 data = data.encode(self.encoding) 760 self. writer.write(data)860 self.stream.write(data) 761 861 762 862 def write_version_directive(self, version_text): … … 764 864 if self.encoding: 765 865 data = data.encode(self.encoding) 766 self. writer.write(data)866 self.stream.write(data) 767 867 self.write_line_break() 768 868 … … 771 871 if self.encoding: 772 872 data = data.encode(self.encoding) 773 self. writer.write(data)873 self.stream.write(data) 774 874 self.write_line_break() 775 875 776 # Scalar writers.876 # Scalar streams. 777 877 778 878 def write_single_quoted(self, text, split=True): … … 795 895 if self.encoding: 796 896 data = data.encode(self.encoding) 797 self. writer.write(data)897 self.stream.write(data) 798 898 start = end 799 899 elif breaks: … … 815 915 if self.encoding: 816 916 data = data.encode(self.encoding) 817 self. writer.write(data)917 self.stream.write(data) 818 918 start = end 819 919 if ch == u'\'': … … 822 922 if self.encoding: 823 923 data = data.encode(self.encoding) 824 self. writer.write(data)924 self.stream.write(data) 825 925 start = end + 1 826 926 if ch is not None: … … 864 964 if self.encoding: 865 965 data = data.encode(self.encoding) 866 self. writer.write(data)966 self.stream.write(data) 867 967 start = end 868 968 if ch is not None: … … 878 978 if self.encoding: 879 979 data = data.encode(self.encoding) 880 self. writer.write(data)980 self.stream.write(data) 881 981 start = end+1 882 982 if 0 < end < len(text)-1 and (ch == u' ' or start >= end) \ … … 888 988 if self.encoding: 889 989 data = data.encode(self.encoding) 890 self. writer.write(data)990 self.stream.write(data) 891 991 self.write_indent() 892 992 self.whitespace = False … … 897 997 if self.encoding: 898 998 data = data.encode(self.encoding) 899 self. writer.write(data)999 self.stream.write(data) 900 1000 end += 1 901 1001 self.write_indicator(u'"', False) … … 948 1048 if self.encoding: 949 1049 data = data.encode(self.encoding) 950 self. writer.write(data)1050 self.stream.write(data) 951 1051 start = end 952 1052 else: … … 955 1055 if self.encoding: 956 1056 data = data.encode(self.encoding) 957 self. writer.write(data)1057 self.stream.write(data) 958 1058 if ch is None: 959 1059 self.write_line_break() … … 989 1089 if self.encoding: 990 1090 data = data.encode(self.encoding) 991 self. writer.write(data)1091 self.stream.write(data) 992 1092 if ch is None: 993 1093 self.write_line_break() … … 1005 1105 if self.encoding: 1006 1106 data = data.encode(self.encoding) 1007 self. writer.write(data)1107 self.stream.write(data) 1008 1108 self.writespace = False 1009 1109 self.indention = False … … 1026 1126 if self.encoding: 1027 1127 data = data.encode(self.encoding) 1028 self. writer.write(data)1128 self.stream.write(data) 1029 1129 start = end 1030 1130 elif breaks: … … 1047 1147 if self.encoding: 1048 1148 data = data.encode(self.encoding) 1049 self. writer.write(data)1149 self.stream.write(data) 1050 1150 start = end 1051 1151 if ch is not None: -
pyyaml/trunk/lib/yaml/error.py
r119 r136 49 49 50 50 def __init__(self, context=None, context_mark=None, 51 problem=None, problem_mark=None ):51 problem=None, problem_mark=None, note=None): 52 52 self.context = context 53 53 self.context_mark = context_mark 54 54 self.problem = problem 55 55 self.problem_mark = problem_mark 56 self.note = note 56 57 57 58 def __str__(self): 58 59 lines = [] 59 #for (place, mark) in [(self.context, self.context_mark),60 # (self.problem, self.problem_mark)]:61 # if place is not None:62 # lines.append(place)63 # if mark is not None:64 # lines.append(str(mark))65 60 if self.context is not None: 66 61 lines.append(self.context) … … 75 70 if self.problem_mark is not None: 76 71 lines.append(str(self.problem_mark)) 72 if self.note is not None: 73 lines.append(self.note) 77 74 return '\n'.join(lines) 78 75 79 80 -
pyyaml/trunk/lib/yaml/events.py
r133 r136 34 34 35 35 class StreamStartEvent(Event): 36 def __init__(self, start_mark=None, end_mark=None, 37 encoding=None, line_break=None, canonical=None, 38 indent=None, width=None, allow_unicode=None): 36 def __init__(self, start_mark=None, end_mark=None, encoding=None): 39 37 self.start_mark = start_mark 40 38 self.end_mark = end_mark 41 39 self.encoding = encoding 42 self.line_break = line_break43 self.canonical = canonical44 self.indent = indent45 self.width = width46 self.allow_unicode = allow_unicode47 40 48 41 class StreamEndEvent(Event): … … 69 62 70 63 class ScalarEvent(NodeEvent): 71 def __init__(self, anchor, tag, value, start_mark=None, end_mark=None,72 implicit=None, style=None):64 def __init__(self, anchor, tag, implicit, value, 65 start_mark=None, end_mark=None, style=None): 73 66 self.anchor = anchor 74 67 self.tag = tag 68 self.implicit = implicit 75 69 self.value = value 76 70 self.start_mark = start_mark 77 71 self.end_mark = end_mark 78 self.implicit = implicit79 72 self.style = style 80 73 -
pyyaml/trunk/lib/yaml/nodes.py
r133 r136 24 24 class ScalarNode(Node): 25 25 id = 'scalar' 26 def __init__(self, tag, value, implicit,26 def __init__(self, tag, value, 27 27 start_mark=None, end_mark=None, style=None): 28 28 self.tag = tag 29 29 self.value = value 30 self.implicit = implicit31 30 self.start_mark = start_mark 32 31 self.end_mark = end_mark -
pyyaml/trunk/lib/yaml/parser.py
r132 r136 25 25 # stream ::= (BOM? implicit_document)? (BOM? explicit_document)* STREAM-END 26 26 27 # Note that there is a slight deviation from the specification. We require a28 # non-empty node content if ANCHOR or TAG is specified. This disallow such29 # documents as30 #31 # key: !!str # empty value32 #33 # This is done to prevent ambiguity in parsing tags and aliases:34 #35 # { !!perl/YAML::Parser: value }36 #37 # What is it? Should it be interpreted as38 # { ? !<tag:yaml.org,2002:perl/YAML::Parser> '' : value }39 # or40 # { ? !<tag:yaml.org,2002:perl/YAML::Parser:> value : '' }41 # Since we disallow non-empty node content, tags are always followed by spaces42 # or line breaks.43 44 27 # FIRST sets: 45 28 # stream: { STREAM-START } … … 67 50 from tokens import * 68 51 from events import * 52 from scanner import * 69 53 70 54 class ParserError(MarkedYAMLError): … … 72 56 73 57 class Parser: 74 # Since writing a n LL(1) parser is a straightforward task, we do not give75 # many comments here.58 # Since writing a recursive-descendant parser is a straightforward task, we 59 # do not give many comments here. 76 60 # Note that we use Python generators. If you rewrite the parser in another 77 61 # language, you may replace all 'yield'-s with event handler calls. … … 82 66 } 83 67 84 def __init__(self, scanner): 85 self.scanner = scanner 68 def __init__(self): 86 69 self.current_event = None 87 70 self.yaml_version = None … … 89 72 self.event_generator = self.parse_stream() 90 73 91 def check (self, *choices):74 def check_event(self, *choices): 92 75 # Check the type of the next event. 93 76 if self.current_event is None: … … 97 80 pass 98 81 if self.current_event is not None: 82 if not choices: 83 return True 99 84 for choice in choices: 100 85 if isinstance(self.current_event, choice): … … 102 87 return False 103 88 104 def peek (self):89 def peek_event(self): 105 90 # Get the next event. 106 91 if self.current_event is None: … … 111 96 return self.current_event 112 97 113 def get (self):98 def get_event(self): 114 99 # Get the next event. 115 100 if self.current_event is None: … … 130 115 131 116 # Parse start of stream. 132 token = self. scanner.get()117 token = self.get_token() 133 118 yield StreamStartEvent(token.start_mark, token.end_mark, 134 119 encoding=token.encoding) 135 120 136 121 # Parse implicit document. 137 if not self. scanner.check(DirectiveToken, DocumentStartToken,122 if not self.check_token(DirectiveToken, DocumentStartToken, 138 123 StreamEndToken): 139 124 self.tag_handles = self.DEFAULT_TAGS 140 token = self. scanner.peek()125 token = self.peek_token() 141 126 start_mark = end_mark = token.start_mark 142 127 yield DocumentStartEvent(start_mark, end_mark, … … 144 129 for event in self.parse_block_node(): 145 130 yield event 146 token = self. scanner.peek()131 token = self.peek_token() 147 132 start_mark = end_mark = token.start_mark 148 133 explicit = False 149 while self. scanner.check(DocumentEndToken):150 token = self. scanner.get()134 while self.check_token(DocumentEndToken): 135 token = self.get_token() 151 136 end_mark = token.end_mark 152 137 explicit = True … … 155 140 156 141 # Parse explicit documents. 157 while not self. scanner.check(StreamEndToken):158 token = self. scanner.peek()142 while not self.check_token(StreamEndToken): 143 token = self.peek_token() 159 144 start_mark = token.start_mark 160 145 version, tags = self.process_directives() 161 if not self. scanner.check(DocumentStartToken):146 if not self.check_token(DocumentStartToken): 162 147 raise ParserError(None, None, 163 148 "expected '<document start>', but found %r" 164 % self. scanner.peek().id,165 self. scanner.peek().start_mark)166 token = self. scanner.get()149 % self.peek_token().id, 150 self.peek_token().start_mark) 151 token = self.get_token() 167 152 end_mark = token.end_mark 168 153 yield DocumentStartEvent(start_mark, end_mark, 169 154 explicit=True, version=version, tags=tags) 170 if self. scanner.check(DirectiveToken,155 if self.check_token(DirectiveToken, 171 156 DocumentStartToken, DocumentEndToken, StreamEndToken): 172 157 yield self.process_empty_scalar(token.end_mark) … … 174 159 for event in self.parse_block_node(): 175 160 yield event 176 token = self. scanner.peek()161 token = self.peek_token() 177 162 start_mark = end_mark = token.start_mark 178 163 explicit = False 179 while self. scanner.check(DocumentEndToken):180 token = self. scanner.get()164 while self.check_token(DocumentEndToken): 165 token = self.get_token() 181 166 end_mark = token.end_mark 182 167 explicit=True … … 185 170 186 171 # Parse end of stream. 187 token = self. scanner.get()172 token = self.get_token() 188 173 yield StreamEndEvent(token.start_mark, token.end_mark) 189 174 … … 192 177 self.yaml_version = None 193 178 self.tag_handles = {} 194 while self. scanner.check(DirectiveToken):195 token = self. scanner.get()179 while self.check_token(DirectiveToken): 180 token = self.get_token() 196 181 if token.name == u'YAML': 197 182 if self.yaml_version is not None: … … 238 223 # block_node_or_indentless_sequence ::= ALIAS | properties? 239 224 # (block_content | indentless_block_sequence) 240 if self. scanner.check(AliasToken):241 token = self. scanner.get()225 if self.check_token(AliasToken): 226 token = self.get_token() 242 227 yield AliasEvent(token.value, token.start_mark, token.end_mark) 243 228 else: … … 245 230 tag = None 246 231 start_mark = end_mark = tag_mark = None 247 if self. scanner.check(AnchorToken):248 token = self. scanner.get()232 if self.check_token(AnchorToken): 233 token = self.get_token() 249 234 start_mark = token.start_mark 250 235 end_mark = token.end_mark 251 236 anchor = token.value 252 if self. scanner.check(TagToken):253 token = self. scanner.get()237 if self.check_token(TagToken): 238 token = self.get_token() 254 239 tag_mark = token.start_mark 255 240 end_mark = token.end_mark 256 241 tag = token.value 257 elif self. scanner.check(TagToken):258 token = self. scanner.get()242 elif self.check_token(TagToken): 243 token = self.get_token() 259 244 start_mark = tag_mark = token.start_mark 260 245 end_mark = token.end_mark 261 246 tag = token.value 262 if self. scanner.check(AnchorToken):263 token = self. scanner.get()247 if self.check_token(AnchorToken): 248 token = self.get_token() 264 249 end_mark = token.end_mark 265 250 anchor = token.value 266 if tag is not None :251 if tag is not None and tag != u'!': 267 252 handle, suffix = tag 268 253 if handle is not None: … … 274 259 else: 275 260 tag = suffix 276 #if tag is None:277 # if not (self.scanner.check(ScalarToken) and278 # self.scanner.peek().implicit):279 # tag = u'!'261 #if tag == u'!': 262 # raise ParserError("while parsing a node", start_mark, 263 # "found non-specific tag '!'", tag_mark, 264 # "Please check 'http://pyyaml.org/wiki/YAMLNonSpecificTag' and share your opinion.") 280 265 if start_mark is None: 281 start_mark = end_mark = self. scanner.peek().start_mark266 start_mark = end_mark = self.peek_token().start_mark 282 267 event = None 283 268 collection_events = None 284 if indentless_sequence and self. scanner.check(BlockEntryToken):285 end_mark = self. scanner.peek().end_mark269 if indentless_sequence and self.check_token(BlockEntryToken): 270 end_mark = self.peek_token().end_mark 286 271 event = SequenceStartEvent(anchor, tag, start_mark, end_mark) 287 272 collection_events = self.parse_indentless_sequence() 288 273 else: 289 if self. scanner.check(ScalarToken):290 token = self. scanner.get()274 if self.check_token(ScalarToken): 275 token = self.get_token() 291 276 end_mark = token.end_mark 292 implicit = (tag is None and token.implicit) 293 event = ScalarEvent(anchor, tag, token.value, 294 start_mark, end_mark, 295 implicit=implicit, style=token.style) 296 elif self.scanner.check(FlowSequenceStartToken): 297 end_mark = self.scanner.peek().end_mark 277 implicit = ((tag is None or tag == u'!') and token.implicit) 278 event = ScalarEvent(anchor, tag, implicit, token.value, 279 start_mark, end_mark, style=token.style) 280 elif self.check_token(FlowSequenceStartToken): 281 end_mark = self.peek_token().end_mark 298 282 event = SequenceStartEvent(anchor, tag, start_mark, end_mark, 299 283 flow_style=True) 300 284 collection_events = self.parse_flow_sequence() 301 elif self. scanner.check(FlowMappingStartToken):302 end_mark = self. scanner.peek().end_mark285 elif self.check_token(FlowMappingStartToken): 286 end_mark = self.peek_token().end_mark 303 287 event = MappingStartEvent(anchor, tag, start_mark, end_mark, 304 288 flow_style=True) 305 289 collection_events = self.parse_flow_mapping() 306 elif block and self. scanner.check(BlockSequenceStartToken):307 end_mark = self. scanner.peek().start_mark290 elif block and self.check_token(BlockSequenceStartToken): 291 end_mark = self.peek_token().start_mark 308 292 event = SequenceStartEvent(anchor, tag, start_mark, end_mark, 309 293 flow_style=False) 310 294 collection_events = self.parse_block_sequence() 311 elif block and self. scanner.check(BlockMappingStartToken):312 end_mark = self. scanner.peek().start_mark295 elif block and self.check_token(BlockMappingStartToken): 296 end_mark = self.peek_token().start_mark 313 297 event = MappingStartEvent(anchor, tag, start_mark, end_mark, 314 298 flow_style=False) … … 317 301 # Empty scalars are allowed even if a tag or an anchor is 318 302 # specified. 319 event = ScalarEvent(anchor, tag, u'', start_mark, end_mark, 320 implicit=True) 303 implicit = (tag is None or tag == u'!') 304 event = ScalarEvent(anchor, tag, implicit, u'', 305 start_mark, end_mark) 321 306 else: 322 307 if block: … … 324 309 else: 325 310 node = 'flow' 326 token = self. scanner.peek()311 token = self.peek_token() 327 312 raise ParserError("while scanning a %s node" % node, start_mark, 328 313 "expected the node content, but found %r" % token.id, … … 335 320 def parse_block_sequence(self): 336 321 # BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END 337 token = self. scanner.get()322 token = self.get_token() 338 323 start_mark = token.start_mark 339 while self. scanner.check(BlockEntryToken):340 token = self. scanner.get()341 if not self. scanner.check(BlockEntryToken, BlockEndToken):324 while self.check_token(BlockEntryToken): 325 token = self.get_token() 326 if not self.check_token(BlockEntryToken, BlockEndToken): 342 327 for event in self.parse_block_node(): 343 328 yield event 344 329 else: 345 330 yield self.process_empty_scalar(token.end_mark) 346 if not self. scanner.check(BlockEndToken):347 token = self. scanner.peek()331 if not self.check_token(BlockEndToken): 332 token = self.peek_token() 348 333 raise ParserError("while scanning a block collection", start_mark, 349 334 "expected <block end>, but found %r" % token.id, token.start_mark) 350 token = self. scanner.get()335 token = self.get_token() 351 336 yield SequenceEndEvent(token.start_mark, token.end_mark) 352 337 353 338 def parse_indentless_sequence(self): 354 339 # (BLOCK-ENTRY block_node?)+ 355 while self. scanner.check(BlockEntryToken):356 token = self. scanner.get()357 if not self. scanner.check(BlockEntryToken,340 while self.check_token(BlockEntryToken): 341 token = self.get_token() 342 if not self.check_token(BlockEntryToken, 358 343 KeyToken, ValueToken, BlockEndToken): 359 344 for event in self.parse_block_node(): … … 361 346 else: 362 347 yield self.process_empty_scalar(token.end_mark) 363 token = self. scanner.peek()348 token = self.peek_token() 364 349 yield SequenceEndEvent(token.start_mark, token.start_mark) 365 350 … … 369 354 # (VALUE block_node_or_indentless_sequence?)?)* 370 355 # BLOCK-END 371 token = self. scanner.get()356 token = self.get_token() 372 357 start_mark = token.start_mark 373 while self. scanner.check(KeyToken, ValueToken):374 if self. scanner.check(KeyToken):375 token = self. scanner.get()376 if not self. scanner.check(KeyToken, ValueToken, BlockEndToken):358 while self.check_token(KeyToken, ValueToken): 359 if self.check_token(KeyToken): 360 token = self.get_token() 361 if not self.check_token(KeyToken, ValueToken, BlockEndToken): 377 362 for event in self.parse_block_node_or_indentless_sequence(): 378 363 yield event 379 364 else: 380 365 yield self.process_empty_scalar(token.end_mark) 381 if self. scanner.check(ValueToken):382 token = self. scanner.get()383 if not self. scanner.check(KeyToken, ValueToken, BlockEndToken):366 if self.check_token(ValueToken): 367 token = self.get_token() 368 if not self.check_token(KeyToken, ValueToken, BlockEndToken): 384 369 for event in self.parse_block_node_or_indentless_sequence(): 385 370 yield event … … 387 372 yield self.process_empty_scalar(token.end_mark) 388 373 else: 389 token = self. scanner.peek()374 token = self.peek_token() 390 375 yield self.process_empty_scalar(token.start_mark) 391 if not self. scanner.check(BlockEndToken):392 token = self. scanner.peek()376 if not self.check_token(BlockEndToken): 377 token = self.peek_token() 393 378 raise ParserError("while scanning a block mapping", start_mark, 394 379 "expected <block end>, but found %r" % token.id, token.start_mark) 395 token = self. scanner.get()380 token = self.get_token() 396 381 yield MappingEndEvent(token.start_mark, token.end_mark) 397 382 … … 407 392 # For `flow_sequence_entry`, the part `KEY flow_node? (VALUE flow_node?)?` 408 393 # generate an inline mapping (set syntax). 409 token = self. scanner.get()394 token = self.get_token() 410 395 start_mark = token.start_mark 411 while not self. scanner.check(FlowSequenceEndToken):412 if self. scanner.check(KeyToken):413 token = self. scanner.get()396 while not self.check_token(FlowSequenceEndToken): 397 if self.check_token(KeyToken): 398 token = self.get_token() 414 399 yield MappingStartEvent(None, None, # u'!', 415 400 token.start_mark, token.end_mark, 416 401 flow_style=True) 417 if not self. scanner.check(ValueToken,402 if not self.check_token(ValueToken, 418 403 FlowEntryToken, FlowSequenceEndToken): 419 404 for event in self.parse_flow_node(): … … 421 406 else: 422 407 yield self.process_empty_scalar(token.end_mark) 423 if self. scanner.check(ValueToken):424 token = self. scanner.get()425 if not self. scanner.check(FlowEntryToken, FlowSequenceEndToken):408 if self.check_token(ValueToken): 409 token = self.get_token() 410 if not self.check_token(FlowEntryToken, FlowSequenceEndToken): 426 411 for event in self.parse_flow_node(): 427 412 yield event … … 429 414 yield self.process_empty_scalar(token.end_mark) 430 415 else: 431 token = self. scanner.peek()416 token = self.peek_token() 432 417 yield self.process_empty_scalar(token.start_mark) 433 token = self. scanner.peek()418 token = self.peek_token() 434 419 yield MappingEndEvent(token.start_mark, token.start_mark) 435 420 else: 436 421 for event in self.parse_flow_node(): 437 422 yield event 438 if not self. scanner.check(FlowEntryToken, FlowSequenceEndToken):439 token = self. scanner.peek()423 if not self.check_token(FlowEntryToken, FlowSequenceEndToken): 424 token = self.peek_token() 440 425 raise ParserError("while scanning a flow sequence", start_mark, 441 426 "expected ',' or ']', but got %r" % token.id, token.start_mark) 442 if self. scanner.check(FlowEntryToken):443 self. scanner.get()444 token = self. scanner.get()427 if self.check_token(FlowEntryToken): 428 self.get_token() 429 token = self.get_token() 445 430 yield SequenceEndEvent(token.start_mark, token.end_mark) 446 431 … … 451 436 # FLOW-MAPPING-END 452 437 # flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 453 token = self. scanner.get()438 token = self.get_token() 454 439 start_mark = token.start_mark 455 while not self. scanner.check(FlowMappingEndToken):456 if self. scanner.check(KeyToken):457 token = self. scanner.get()458 if not self. scanner.check(ValueToken,440 while not self.check_token(FlowMappingEndToken): 441 if self.check_token(KeyToken): 442 token = self.get_token() 443 if not self.check_token(ValueToken, 459 444 FlowEntryToken, FlowMappingEndToken): 460 445 for event in self.parse_flow_node(): … … 462 447 else: 463 448 yield self.process_empty_scalar(token.end_mark) 464 if self. scanner.check(ValueToken):465 token = self. scanner.get()466 if not self. scanner.check(FlowEntryToken, FlowMappingEndToken):449 if self.check_token(ValueToken): 450 token = self.get_token() 451 if not self.check_token(FlowEntryToken, FlowMappingEndToken): 467 452 for event in self.parse_flow_node(): 468 453 yield event … … 470 455 yield self.process_empty_scalar(token.end_mark) 471 456 else: 472 token = self. scanner.peek()457 token = self.peek_token() 473 458 yield self.process_empty_scalar(token.start_mark) 474 459 else: 475 460 for event in self.parse_flow_node(): 476 461 yield event 477 yield self.process_empty_scalar(self. scanner.peek().start_mark)478 if not self. scanner.check(FlowEntryToken, FlowMappingEndToken):479 token = self. scanner.peek()462 yield self.process_empty_scalar(self.peek_token().start_mark) 463 if not self.check_token(FlowEntryToken, FlowMappingEndToken): 464 token = self.peek_token() 480 465 raise ParserError("while scanning a flow mapping", start_mark, 481 466 "expected ',' or '}', but got %r" % token.id, token.start_mark) 482 if self. scanner.check(FlowEntryToken):483 self. scanner.get()484 if not self. scanner.check(FlowMappingEndToken):485 token = self. scanner.peek()467 if self.check_token(FlowEntryToken): 468 self.get_token() 469 if not self.check_token(FlowMappingEndToken): 470 token = self.peek_token() 486 471 raise ParserError("while scanning a flow mapping", start_mark, 487 472 "expected '}', but found %r" % token.id, token.start_mark) 488 token = self. scanner.get()473 token = self.get_token() 489 474 yield MappingEndEvent(token.start_mark, token.end_mark) 490 475 491 476 def process_empty_scalar(self, mark): 492 return ScalarEvent(None, None, u'', mark, mark, 493 implicit=True) 494 477 return ScalarEvent(None, None, True, u'', mark, mark) 478 -
pyyaml/trunk/lib/yaml/reader.py
r130 r136 92 92 # Yeah, it's ugly and slow. 93 93 94 def __init__(self, data):94 def __init__(self, stream): 95 95 self.name = None 96 96 self.stream = None … … 105 105 self.line = 0 106 106 self.column = 0 107 if isinstance( data, unicode):107 if isinstance(stream, unicode): 108 108 self.name = "<unicode string>" 109 self.check_printable( data)110 self.buffer = data+u'\0'111 elif isinstance( data, str):109 self.check_printable(stream) 110 self.buffer = stream+u'\0' 111 elif isinstance(stream, str): 112 112 self.name = "<string>" 113 self.raw_buffer = data113 self.raw_buffer = stream 114 114 self.determine_encoding() 115 115 else: 116 self.stream = data117 self.name = getattr( data, 'name', "<file>")116 self.stream = stream 117 self.name = getattr(stream, 'name', "<file>") 118 118 self.eof = False 119 119 self.raw_buffer = '' -
pyyaml/trunk/lib/yaml/representer.py
r135 r136 21 21 pass 22 22 23 class BaseRepresenter(BaseDetector): 24 25 DEFAULT_SCALAR_TAG = u'tag:yaml.org,2002:str' 26 DEFAULT_SEQUENCE_TAG = u'tag:yaml.org,2002:seq' 27 DEFAULT_MAPPING_TAG = u'tag:yaml.org,2002:map' 28 29 def __init__(self, serializer): 30 self.serializer = serializer 23 class BaseRepresenter: 24 25 yaml_representers = {} 26 27 def __init__(self): 31 28 self.represented_objects = {} 32 29 33 def close(self): 34 self.serializer.close() 35 36 def represent(self, native): 37 node = self.represent_object(native) 38 self.serializer.serialize(node) 30 def represent(self, data): 31 node = self.represent_object(data) 32 self.serialize(node) 39 33 self.represented_objects = {} 40 34 41 def represent_object(self, native):42 if self.ignore_aliases( native):35 def represent_object(self, data): 36 if self.ignore_aliases(data): 43 37 alias_key = None 44 38 else: 45 alias_key = id( native)39 alias_key = id(data) 46 40 if alias_key is not None: 47 41 if alias_key in self.represented_objects: 48 42 node = self.represented_objects[alias_key] 49 43 if node is None: 50 raise RepresenterError("recursive objects are not allowed: %r" % native)44 raise RepresenterError("recursive objects are not allowed: %r" % data) 51 45 return node 52 46 self.represented_objects[alias_key] = None 53 for native_type in type(native).__mro__:54 if native_type in self.yaml_representers:55 node = self.yaml_representers[ native_type](self, native)47 for data_type in type(data).__mro__: 48 if data_type in self.yaml_representers: 49 node = self.yaml_representers[data_type](self, data) 56 50 break 57 51 else: 58 52 if None in self.yaml_representers: 59 node = self.yaml_representers[None](self, native)53 node = self.yaml_representers[None](self, data) 60 54 else: 61 node = ScalarNode(None, unicode( native))55 node = ScalarNode(None, unicode(data)) 62 56 if alias_key is not None: 63 57 self.represented_objects[alias_key] = node 64 58 return node 65 59 66 def add_representer(cls, native_type, representer):60 def add_representer(cls, data_type, representer): 67 61 if not 'yaml_representers' in cls.__dict__: 68 62 cls.yaml_representers = cls.yaml_representers.copy() 69 cls.yaml_representers[ native_type] = representer63 cls.yaml_representers[data_type] = representer 70 64 add_representer = classmethod(add_representer) 71 65 72 yaml_representers = {}73 74 66 def represent_scalar(self, tag, value, style=None): 75 detected_tag = self.detect(value) 76 if detected_tag is None: 77 detected_tag = self.DEFAULT_SCALAR_TAG 78 implicit = (tag == detected_tag) 79 if tag == self.DEFAULT_SCALAR_TAG: 80 tag = None 81 return ScalarNode(tag, value, implicit=implicit, style=style) 67 return ScalarNode(tag, value, style=style) 82 68 83 69 def represent_sequence(self, tag, sequence, flow_style=None): 84 if tag == self.DEFAULT_SEQUENCE_TAG:85 tag = None86 70 value = [] 87 71 for item in sequence: … … 90 74 91 75 def represent_mapping(self, tag, mapping, flow_style=None): 92 if tag == self.DEFAULT_MAPPING_TAG:93 tag = None94 76 value = {} 95 77 if hasattr(mapping, 'keys'): … … 104 86 return MappingNode(tag, value, flow_style=flow_style) 105 87 106 def ignore_aliases(self, native):88 def ignore_aliases(self, data): 107 89 return False 108 90 109 class SafeRepresenter( Detector,BaseRepresenter):110 111 def ignore_aliases(self, native):112 if nativein [None, ()]:91 class SafeRepresenter(BaseRepresenter): 92 93 def ignore_aliases(self, data): 94 if data in [None, ()]: 113 95 return True 114 if isinstance( native, (str, unicode, bool, int, float)):96 if isinstance(data, (str, unicode, bool, int, float)): 115 97 return True 116 98 117 def represent_none(self, native):99 def represent_none(self, data): 118 100 return self.represent_scalar(u'tag:yaml.org,2002:null', 119 101 u'null') 120 102 121 def represent_str(self, native):103 def represent_str(self, data): 122 104 encoding = None 123 105 try: 124 unicode( native, 'ascii')106 unicode(data, 'ascii') 125 107 encoding = 'ascii' 126 108 except UnicodeDecodeError: 127 109 try: 128 unicode( native, 'utf-8')110 unicode(data, 'utf-8') 129 111 encoding = 'utf-8' 130 112 except UnicodeDecodeError: … … 132 114 if encoding: 133 115 return self.represent_scalar(u'tag:yaml.org,2002:str', 134 unicode( native, encoding))116 unicode(data, encoding)) 135 117 else: 136 118 return self.represent_scalar(u'tag:yaml.org,2002:binary', 137 unicode( native.encode('base64')), style='|')138 139 def represent_unicode(self, native):140 return self.represent_scalar(u'tag:yaml.org,2002:str', native)141 142 def represent_bool(self, native):143 if native:119 unicode(data.encode('base64')), style='|') 120 121 def represent_unicode(self, data): 122 return self.represent_scalar(u'tag:yaml.org,2002:str', data) 123 124 def represent_bool(self, data): 125 if data: 144 126 value = u'true' 145 127 else: … … 147 129 return self.represent_scalar(u'tag:yaml.org,2002:bool', value) 148 130 149 def represent_int(self, native):150 return self.represent_scalar(u'tag:yaml.org,2002:int', unicode( native))151 152 def represent_long(self, native):153 return self.represent_scalar(u'tag:yaml.org,2002:int', unicode( native))131 def represent_int(self, data): 132 return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data)) 133 134 def represent_long(self, data): 135 return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data)) 154 136 155 137 inf_value = 1e300000 156 138 nan_value = inf_value/inf_value 157 139 158 def represent_float(self, native):159 if native== self.inf_value:140 def represent_float(self, data): 141 if data == self.inf_value: 160 142 value = u'.inf' 161 elif native== -self.inf_value:143 elif data == -self.inf_value: 162 144 value = u'-.inf' 163 elif native == self.nan_value or native != native:145 elif data == self.nan_value or data != data: 164 146 value = u'.nan' 165 147 else: 166 value = unicode( native)148 value = unicode(data) 167 149 return self.represent_scalar(u'tag:yaml.org,2002:float', value) 168 150 169 def represent_list(self, native):170 pairs = (len( native) > 0)171 for item in native:151 def represent_list(self, data): 152 pairs = (len(data) > 0) 153 for item in data: 172 154 if not isinstance(item, tuple) or len(item) != 2: 173 155 pairs = False 174 156 break 175 157 if not pairs: 176 return self.represent_sequence(u'tag:yaml.org,2002:seq', native)158 return self.represent_sequence(u'tag:yaml.org,2002:seq', data) 177 159 value = [] 178 for item_key, item_value in native:160 for item_key, item_value in data: 179 161 value.append(self.represent_mapping(u'tag:yaml.org,2002:map', 180 162 [(item_key, item_value)])) 181 163 return SequenceNode(u'tag:yaml.org,2002:pairs', value) 182 164 183 def represent_dict(self, native):184 return self.represent_mapping(u'tag:yaml.org,2002:map', native)185 186 def represent_set(self, native):165 def represent_dict(self, data): 166 return self.represent_mapping(u'tag:yaml.org,2002:map', data) 167 168 def represent_set(self, data): 187 169 value = {} 188 for key in native:170 for key in data: 189 171 value[key] = None 190 172 return self.represent_mapping(u'tag:yaml.org,2002:set', value) 191 173 192 def represent_date(self, native):193 value = u'%04d-%02d-%02d' % ( native.year, native.month, native.day)174 def represent_date(self, data): 175 value = u'%04d-%02d-%02d' % (data.year, data.month, data.day) 194 176 return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value) 195 177 196 def represent_datetime(self, native):178 def represent_datetime(self, data): 197 179 value = u'%04d-%02d-%02d %02d:%02d:%02d' \ 198 % ( native.year, native.month, native.day,199 native.hour, native.minute, native.second)200 if native.microsecond:201 value += u'.' + unicode( native.microsecond/1000000.0).split(u'.')[1]202 if native.utcoffset():203 value += unicode( native.utcoffset())180 % (data.year, data.month, data.day, 181 data.hour, data.minute, data.second) 182 if data.microsecond: 183 value += u'.' + unicode(data.microsecond/1000000.0).split(u'.')[1] 184 if data.utcoffset(): 185 value += unicode(data.utcoffset()) 204 186 return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value) 205 187 206 def represent_undefined(self, native): 207 raise RepresenterError("cannot represent an object: %s" % native) 188 def represent_yaml_object(self, tag, data, cls, flow_style=None): 189 if hasattr(data, '__getstate__'): 190 state = data.__getstate__() 191 else: 192 state = data.__dict__.copy() 193 mapping = state 194 if hasattr(state, 'keys'): 195 mapping = [] 196 keys = state.keys() 197 keys.sort() 198 for key in keys: 199 mapping.append((key.replace('_', '-'), state[key])) 200 return self.represent_mapping(tag, mapping, flow_style=flow_style) 201 202 def represent_undefined(self, data): 203 raise RepresenterError("cannot represent an object: %s" % data) 208 204 209 205 SafeRepresenter.add_representer(type(None), -
pyyaml/trunk/lib/yaml/scanner.py
r132 r136 46 46 class Scanner: 47 47 48 49 def __init__(self, reader): 48 def __init__(self): 50 49 """Initialize the scanner.""" 51 # The input stream. The Reader class do the dirty work of checking for52 # BOM and converting the input data to Unicode. It also adds NUL to53 # the end.50 # It is assumed that Scanner and Reader will have a common descendant. 51 # Reader do the dirty work of checking for BOM and converting the 52 # input data to Unicode. It also adds NUL to the end. 54 53 # 55 54 # Reader supports the following methods 56 # self.reader.peek(i=0) # peek the next i-th character 57 # self.reader.prefix(l=1) # peek the next l characters 58 # self.reader.forward(l=1) # read the next l characters 59 # and move the pointer 60 self.reader = reader 55 # self.peek(i=0) # peek the next i-th character 56 # self.prefix(l=1) # peek the next l characters 57 # self.forward(l=1) # read the next l characters and move the pointer. 61 58 62 59 # Had we reached the end of the stream? … … 114 111 # Public methods. 115 112 116 def check (self, *choices):113 def check_token(self, *choices): 117 114 # Check if the next token is one of the given types. 118 115 while self.need_more_tokens(): 119 116 self.fetch_more_tokens() 120 117 if self.tokens: 118 if not choices: 119 return True 121 120 for choice in choices: 122 121 if isinstance(self.tokens[0], choice): … … 124 123 return False 125 124 126 def peek (self):125 def peek_token(self): 127 126 # Return the next token, but do not delete if from the queue. 128 127 while self.need_more_tokens(): … … 131 130 return self.tokens[0] 132 131 133 def get (self):132 def get_token(self): 134 133 # Return the next token. 135 134 while self.need_more_tokens(): … … 172 171 # Compare the current indentation and column. It may add some tokens 173 172 # and decrease the current indentation level. 174 self.unwind_indent(self. reader.column)173 self.unwind_indent(self.column) 175 174 176 175 # Peek the next character. 177 ch = self. reader.peek()176 ch = self.peek() 178 177 179 178 # Is it the end of stream? … … 266 265 raise ScannerError("while scanning for the next token", None, 267 266 "found character %r that cannot start any token" 268 % ch.encode('utf-8'), self. reader.get_mark())267 % ch.encode('utf-8'), self.get_mark()) 269 268 270 269 # Simple keys treatment. … … 294 293 for level in self.possible_simple_keys.keys(): 295 294 key = self.possible_simple_keys[level] 296 if key.line != self. reader.line \297 or self. reader.index-key.index > 1024:295 if key.line != self.line \ 296 or self.index-key.index > 1024: 298 297 if key.required: 299 298 raise ScannerError("while scanning a simple key", key.mark, 300 "could not found expected ':'", self. reader.get_mark())299 "could not found expected ':'", self.get_mark()) 301 300 del self.possible_simple_keys[level] 302 301 … … 307 306 308 307 # Check if a simple key is required at the current position. 309 required = not self.flow_level and self.indent == self. reader.column308 required = not self.flow_level and self.indent == self.column 310 309 311 310 # A simple key is required only if it is the first token in the current … … 318 317 self.remove_possible_simple_key() 319 318 token_number = self.tokens_taken+len(self.tokens) 320 index = self.reader.index321 line = self.reader.line322 column = self.reader.column323 mark = self.reader.get_mark()324 319 key = SimpleKey(token_number, required, 325 index, line, column, mark)320 self.index, self.line, self.column, self.get_mark()) 326 321 self.possible_simple_keys[self.flow_level] = key 327 322 … … 335 330 #if key.required: 336 331 # raise ScannerError("while scanning a simple key", key.mark, 337 # "could not found expected ':'", self. reader.get_mark())332 # "could not found expected ':'", self.get_mark()) 338 333 339 334 # Indentation functions. … … 350 345 # raise ScannerError(None, None, 351 346 # "invalid intendation or unclosed '[' or '{'", 352 # self. reader.get_mark())347 # self.get_mark()) 353 348 354 349 # In the flow context, indentation is ignored. We make the scanner less … … 359 354 # In block context, we may need to issue the BLOCK-END tokens. 360 355 while self.indent > column: 361 mark = self. reader.get_mark()356 mark = self.get_mark() 362 357 self.indent = self.indents.pop() 363 358 self.tokens.append(BlockEndToken(mark, mark)) … … 378 373 379 374 # Read the token. 380 mark = self. reader.get_mark()375 mark = self.get_mark() 381 376 382 377 # Add STREAM-START. 383 378 self.tokens.append(StreamStartToken(mark, mark, 384 encoding=self. reader.encoding))379 encoding=self.encoding)) 385 380 386 381 … … 395 390 396 391 # Read the token. 397 mark = self. reader.get_mark()392 mark = self.get_mark() 398 393 399 394 # Add STREAM-END. 400 395 self.tokens.append(StreamEndToken(mark, mark)) 401 396 402 # The reader is ended.397 # The steam is finished. 403 398 self.done = True 404 399 … … 432 427 433 428 # Add DOCUMENT-START or DOCUMENT-END. 434 start_mark = self. reader.get_mark()435 self. reader.forward(3)436 end_mark = self. reader.get_mark()429 start_mark = self.get_mark() 430 self.forward(3) 431 end_mark = self.get_mark() 437 432 self.tokens.append(TokenClass(start_mark, end_mark)) 438 433 … … 455 450 456 451 # Add FLOW-SEQUENCE-START or FLOW-MAPPING-START. 457 start_mark = self. reader.get_mark()458 self. reader.forward()459 end_mark = self. reader.get_mark()452 start_mark = self.get_mark() 453 self.forward() 454 end_mark = self.get_mark() 460 455 self.tokens.append(TokenClass(start_mark, end_mark)) 461 456 … … 478 473 479 474 # Add FLOW-SEQUENCE-END or FLOW-MAPPING-END. 480 start_mark = self. reader.get_mark()481 self. reader.forward()482 end_mark = self. reader.get_mark()475 start_mark = self.get_mark() 476 self.forward() 477 end_mark = self.get_mark() 483 478 self.tokens.append(TokenClass(start_mark, end_mark)) 484 479 … … 492 487 493 488 # Add FLOW-ENTRY. 494 start_mark = self. reader.get_mark()495 self. reader.forward()496 end_mark = self. reader.get_mark()489 start_mark = self.get_mark() 490 self.forward() 491 end_mark = self.get_mark() 497 492 self.tokens.append(FlowEntryToken(start_mark, end_mark)) 498 493 … … 506 501 raise ScannerError(None, None, 507 502 "sequence entries are not allowed here", 508 self. reader.get_mark())503 self.get_mark()) 509 504 510 505 # We may need to add BLOCK-SEQUENCE-START. 511 if self.add_indent(self. reader.column):512 mark = self. reader.get_mark()506 if self.add_indent(self.column): 507 mark = self.get_mark() 513 508 self.tokens.append(BlockSequenceStartToken(mark, mark)) 514 509 … … 525 520 526 521 # Add BLOCK-ENTRY. 527 start_mark = self. reader.get_mark()528 self. reader.forward()529 end_mark = self. reader.get_mark()522 start_mark = self.get_mark() 523 self.forward() 524 end_mark = self.get_mark() 530 525 self.tokens.append(BlockEntryToken(start_mark, end_mark)) 531 526 … … 539 534 raise ScannerError(None, None, 540 535 "mapping keys are not allowed here", 541 self. reader.get_mark())536 self.get_mark()) 542 537 543 538 # We may need to add BLOCK-MAPPING-START. 544 if self.add_indent(self. reader.column):545 mark = self. reader.get_mark()539 if self.add_indent(self.column): 540 mark = self.get_mark() 546 541 self.tokens.append(BlockMappingStartToken(mark, mark)) 547 542 … … 553 548 554 549 # Add KEY. 555 start_mark = self. reader.get_mark()556 self. reader.forward()557 end_mark = self. reader.get_mark()550 start_mark = self.get_mark() 551 self.forward() 552 end_mark = self.get_mark() 558 553 self.tokens.append(KeyToken(start_mark, end_mark)) 559 554 … … 592 587 raise ScannerError(None, None, 593 588 "mapping values are not allowed here", 594 self. reader.get_mark())589 self.get_mark()) 595 590 596 591 # Simple keys are allowed after ':' in the block context. … … 601 596 602 597 # Add VALUE. 603 start_mark = self. reader.get_mark()604 self. reader.forward()605 end_mark = self. reader.get_mark()598 start_mark = self.get_mark() 599 self.forward() 600 end_mark = self.get_mark() 606 601 self.tokens.append(ValueToken(start_mark, end_mark)) 607 602 … … 692 687 # DIRECTIVE: ^ '%' ... 693 688 # The '%' indicator is already checked. 694 if self. reader.column == 0:689 if self.column == 0: 695 690 return True 696 691 … … 698 693 699 694 # DOCUMENT-START: ^ '---' (' '|'\n') 700 if self. reader.column == 0:701 if self. reader.prefix(3) == u'---' \702 and self. reader.peek(3) in u'\0 \t\r\n\x85\u2028\u2029':695 if self.column == 0: 696 if self.prefix(3) == u'---' \ 697 and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 703 698 return True 704 699 … … 706 701 707 702 # DOCUMENT-END: ^ '...' (' '|'\n') 708 if self. reader.column == 0:709 prefix = self. reader.peek(4)710 if self. reader.prefix(3) == u'...' \711 and self. reader.peek(3) in u'\0 \t\r\n\x85\u2028\u2029':703 if self.column == 0: 704 prefix = self.peek(4) 705 if self.prefix(3) == u'...' \ 706 and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 712 707 return True 713 708 … … 715 710 716 711 # BLOCK-ENTRY: '-' (' '|'\n') 717 return self. reader.peek(1) in u'\0 \t\r\n\x85\u2028\u2029'712 return self.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 718 713 719 714 def check_key(self): … … 725 720 # KEY(block context): '?' (' '|'\n') 726 721 else: 727 return self. reader.peek(1) in u'\0 \t\r\n\x85\u2028\u2029'722 return self.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 728 723 729 724 def check_value(self): … … 735 730 # VALUE(block context): ':' (' '|'\n') 736 731 else: 737 return self. reader.peek(1) in u'\0 \t\r\n\x85\u2028\u2029'732 return self.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 738 733 739 734 def check_plain(self): … … 751 746 # '-' character) because we want the flow context to be space 752 747 # independent. 753 ch = self. reader.peek()748 ch = self.peek() 754 749 return ch not in u'\0 \t\r\n\x85\u2028\u2029-?:,[]{}#&*!|>\'\"%@`' \ 755 or (self. reader.peek(1) not in u'\0 \t\r\n\x85\u2028\u2029'750 or (self.peek(1) not in u'\0 \t\r\n\x85\u2028\u2029' 756 751 and (ch == u'-' or (not self.flow_level and ch in u'?:'))) 757 752 … … 778 773 # Scanners for block, flow, and plain scalars need to be modified. 779 774 780 if self. reader.index == 0 and self.reader.peek() == u'\uFEFF':781 self. reader.forward()775 if self.index == 0 and self.peek() == u'\uFEFF': 776 self.forward() 782 777 found = False 783 778 while not found: 784 while self. reader.peek() == u' ':785 self. reader.forward()786 if self. reader.peek() == u'#':787 while self. reader.peek() not in u'\0\r\n\x85\u2028\u2029':788 self. reader.forward()779 while self.peek() == u' ': 780 self.forward() 781 if self.peek() == u'#': 782 while self.peek() not in u'\0\r\n\x85\u2028\u2029': 783 self.forward() 789 784 if self.scan_line_break(): 790 785 if not self.flow_level: … … 795 790 def scan_directive(self): 796 791 # See the specification for details. 797 start_mark = self. reader.get_mark()798 self. reader.forward()792 start_mark = self.get_mark() 793 self.forward() 799 794 name = self.scan_directive_name(start_mark) 800 795 value = None 801 796 if name == u'YAML': 802 797 value = self.scan_yaml_directive_value(start_mark) 803 end_mark = self. reader.get_mark()798 end_mark = self.get_mark() 804 799 elif name == u'TAG': 805 800 value = self.scan_tag_directive_value(start_mark) 806 end_mark = self. reader.get_mark()801 end_mark = self.get_mark() 807 802 else: 808 end_mark = self. reader.get_mark()809 while self. reader.peek() not in u'\0\r\n\x85\u2028\u2029':810 self. reader.forward()803 end_mark = self.get_mark() 804 while self.peek() not in u'\0\r\n\x85\u2028\u2029': 805 self.forward() 811 806 self.scan_directive_ignored_line(start_mark) 812 807 return DirectiveToken(name, value, start_mark, end_mark) … … 815 810 # See the specification for details. 816 811 length = 0 817 ch = self. reader.peek(length)812 ch = self.peek(length) 818 813 while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ 819 814 or ch in u'-_': 820 815 length += 1 821 ch = self. reader.peek(length)816 ch = self.peek(length) 822 817 if not length: 823 818 raise ScannerError("while scanning a directive", start_mark, 824 819 "expected alphabetic or numeric character, but found %r" 825 % ch.encode('utf-8'), self. reader.get_mark())826 value = self. reader.prefix(length)827 self. reader.forward(length)828 ch = self. reader.peek()820 % ch.encode('utf-8'), self.get_mark()) 821 value = self.prefix(length) 822 self.forward(length) 823 ch = self.peek() 829 824 if ch not in u'\0 \r\n\x85\u2028\u2029': 830 825 raise ScannerError("while scanning a directive", start_mark, 831 826 "expected alphabetic or numeric character, but found %r" 832 % ch.encode('utf-8'), self. reader.get_mark())827 % ch.encode('utf-8'), self.get_mark()) 833 828 return value 834 829 835 830 def scan_yaml_directive_value(self, start_mark): 836 831 # See the specification for details. 837 while self. reader.peek() == u' ':838 self. reader.forward()832 while self.peek() == u' ': 833 self.forward() 839 834 major = self.scan_yaml_directive_number(start_mark) 840 if self. reader.peek() != '.':835 if self.peek() != '.': 841 836 raise ScannerError("while scanning a directive", start_mark, 842 837 "expected a digit or '.', but found %r" 843 % self. reader.peek().encode('utf-8'),844 self. reader.get_mark())845 self. reader.forward()838 % self.peek().encode('utf-8'), 839 self.get_mark()) 840 self.forward() 846 841 minor = self.scan_yaml_directive_number(start_mark) 847 if self. reader.peek() not in u'\0 \r\n\x85\u2028\u2029':842 if self.peek() not in u'\0 \r\n\x85\u2028\u2029': 848 843 raise ScannerError("while scanning a directive", start_mark, 849 844 "expected a digit or ' ', but found %r" 850 % self. reader.peek().encode('utf-8'),851 self. reader.get_mark())845 % self.peek().encode('utf-8'), 846 self.get_mark()) 852 847 return (major, minor) 853 848 854 849 def scan_yaml_directive_number(self, start_mark): 855 850 # See the specification for details. 856 ch = self. reader.peek()851 ch = self.peek() 857 852 if not (u'0' <= ch <= '9'): 858 853 raise ScannerError("while scanning a directive", start_mark, 859 854 "expected a digit, but found %r" % ch.encode('utf-8'), 860 self. reader.get_mark())855 self.get_mark()) 861 856 length = 0 862 while u'0' <= self. reader.peek(length) <= u'9':857 while u'0' <= self.peek(length) <= u'9': 863 858 length += 1 864 value = int(self. reader.prefix(length))865 self. reader.forward(length)859 value = int(self.prefix(length)) 860 self.forward(length) 866 861 return value 867 862 868 863 def scan_tag_directive_value(self, start_mark): 869 864 # See the specification for details. 870 while self. reader.peek() == u' ':871 self. reader.forward()865 while self.peek() == u' ': 866 self.forward() 872 867 handle = self.scan_tag_directive_handle(start_mark) 873 while self. reader.peek() == u' ':874 self. reader.forward()868 while self.peek() == u' ': 869 self.forward() 875 870 prefix = self.scan_tag_directive_prefix(start_mark) 876 871 return (handle, prefix) … … 879 874 # See the specification for details. 880 875 value = self.scan_tag_handle('directive', start_mark) 881 ch = self. reader.peek()876 ch = self.peek() 882 877 if ch != u' ': 883 878 raise ScannerError("while scanning a directive", start_mark, 884 879 "expected ' ', but found %r" % ch.encode('utf-8'), 885 self. reader.get_mark())880 self.get_mark()) 886 881 return value 887 882 … … 889 884 # See the specification for details. 890 885 value = self.scan_tag_uri('directive', start_mark) 891 ch = self. reader.peek()886 ch = self.peek() 892 887 if ch not in u'\0 \r\n\x85\u2028\u2029': 893 888 raise ScannerError("while scanning a directive", start_mark, 894 889 "expected ' ', but found %r" % ch.encode('utf-8'), 895 self. reader.get_mark())890 self.get_mark()) 896 891 return value 897 892 898 893 def scan_directive_ignored_line(self, start_mark): 899 894 # See the specification for details. 900 while self. reader.peek() == u' ':901 self. reader.forward()902 if self. reader.peek() == u'#':903 while self. reader.peek() not in u'\0\r\n\x85\u2028\u2029':904 self. reader.forward()905 ch = self. reader.peek()895 while self.peek() == u' ': 896 self.forward() 897 if self.peek() == u'#': 898 while self.peek() not in u'\0\r\n\x85\u2028\u2029': 899 self.forward() 900 ch = self.peek() 906 901 if ch not in u'\0\r\n\x85\u2028\u2029': 907 902 raise ScannerError("while scanning a directive", start_mark, 908 903 "expected a comment or a line break, but found %r" 909 % ch.encode('utf-8'), self. reader.get_mark())904 % ch.encode('utf-8'), self.get_mark()) 910 905 self.scan_line_break() 911 906 … … 919 914 # [ *alias , "value" ] 920 915 # Therefore we restrict aliases to numbers and ASCII letters. 921 start_mark = self. reader.get_mark()922 indicator = self. reader.peek()916 start_mark = self.get_mark() 917 indicator = self.peek() 923 918 if indicator == '*': 924 919 name = 'alias' 925 920 else: 926 921 name = 'anchor' 927 self. reader.forward()922 self.forward() 928 923 length = 0 929 ch = self. reader.peek(length)924 ch = self.peek(length) 930 925 while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ 931 926 or ch in u'-_': 932 927 length += 1 933 ch = self. reader.peek(length)928 ch = self.peek(length) 934 929 if not length: 935 930 raise ScannerError("while scanning an %s" % name, start_mark, 936 931 "expected alphabetic or numeric character, but found %r" 937 % ch.encode('utf-8'), self. reader.get_mark())938 value = self. reader.prefix(length)939 self. reader.forward(length)940 ch = self. reader.peek()932 % ch.encode('utf-8'), self.get_mark()) 933 value = self.prefix(length) 934 self.forward(length) 935 ch = self.peek() 941 936 if ch not in u'\0 \t\r\n\x85\u2028\u2029?:,]}%@`': 942 937 raise ScannerError("while scanning an %s" % name, start_mark, 943 938 "expected alphabetic or numeric character, but found %r" 944 % ch.encode('utf-8'), self. reader.get_mark())945 end_mark = self. reader.get_mark()939 % ch.encode('utf-8'), self.get_mark()) 940 end_mark = self.get_mark() 946 941 return TokenClass(value, start_mark, end_mark) 947 942 948 943 def scan_tag(self): 949 944 # See the specification for details. 950 start_mark = self. reader.get_mark()951 ch = self. reader.peek(1)945 start_mark = self.get_mark() 946 ch = self.peek(1) 952 947 if ch == u'<': 953 948 handle = None 954 self. reader.forward(2)949 self.forward(2) 955 950 suffix = self.scan_tag_uri('tag', start_mark) 956 if self. reader.peek() != u'>':951 if self.peek() != u'>': 957 952 raise ScannerError("while parsing a tag", start_mark, 958 "expected '>', but found %r" % self. reader.peek().encode('utf-8'),959 self. reader.get_mark())960 self. reader.forward()953 "expected '>', but found %r" % self.peek().encode('utf-8'), 954 self.get_mark()) 955 self.forward() 961 956 elif ch in u'\0 \t\r\n\x85\u2028\u2029': 962 957 handle = None 963 958 suffix = u'!' 964 self. reader.forward()959 self.forward() 965 960 else: 966 961 length = 1 … … 971 966 break 972 967 length += 1 973 ch = self. reader.peek(length)968 ch = self.peek(length) 974 969 handle = u'!' 975 970 if use_handle: … … 977 972 else: 978 973 handle = u'!' 979 self. reader.forward()974 self.forward() 980 975 suffix = self.scan_tag_uri('tag', start_mark) 981 ch = self. reader.peek()976 ch = self.peek() 982 977 if ch not in u'\0 \r\n\x85\u2028\u2029': 983 978 raise ScannerError("while scanning a tag", start_mark, 984 979 "expected ' ', but found %r" % ch.encode('utf-8'), 985 self. reader.get_mark())980 self.get_mark()) 986 981 value = (handle, suffix) 987 end_mark = self. reader.get_mark()982 end_mark = self.get_mark() 988 983 return TagToken(value, start_mark, end_mark) 989 984 … … 997 992 998 993 chunks = [] 999 start_mark = self. reader.get_mark()994 start_mark = self.get_mark() 1000 995 1001 996 # Scan the header. 1002 self. reader.forward()997 self.forward() 1003 998 chomping, increment = self.scan_block_scalar_indicators(start_mark) 1004 999 self.scan_block_scalar_ignored_line(start_mark) … … 1017 1012 1018 1013 # Scan the inner part of the block scalar. 1019 while self. reader.column == indent and self.reader.peek() != u'\0':1014 while self.column == indent and self.peek() != u'\0': 1020 1015 chunks.extend(breaks) 1021 leading_non_space = self. reader.peek() not in u' \t'1016 leading_non_space = self.peek() not in u' \t' 1022 1017 length = 0 1023 while self. reader.peek(length) not in u'\0\r\n\x85\u2028\u2029':1018 while self.peek(length) not in u'\0\r\n\x85\u2028\u2029': 1024 1019 length += 1 1025 chunks.append(self. reader.prefix(length))1026 self. reader.forward(length)1020 chunks.append(self.prefix(length)) 1021 self.forward(length) 1027 1022 line_break = self.scan_line_break() 1028 1023 breaks, end_mark = self.scan_block_scalar_breaks(indent) 1029 if self. reader.column == indent and self.reader.peek() != u'\0':1024 if self.column == indent and self.peek() != u'\0': 1030 1025 1031 1026 # Unfortunately, folding rules are ambiguous. … … 1034 1029 1035 1030 if folded and line_break == u'\n' \ 1036 and leading_non_space and self. reader.peek() not in u' \t':1031 and leading_non_space and self.peek() not in u' \t': 1037 1032 if not breaks: 1038 1033 chunks.append(u' ') … … 1045 1040 #if folded and line_break == u'\n': 1046 1041 # if not breaks: 1047 # if self. reader.peek() not in ' \t':1042 # if self.peek() not in ' \t': 1048 1043 # chunks.append(u' ') 1049 1044 # else: … … 1068 1063 chomping = None 1069 1064 increment = None 1070 ch = self. reader.peek()1065 ch = self.peek() 1071 1066 if ch in u'+-': 1072 1067 if ch == '+': … … 1074 1069 else: 1075 1070 chomping = False 1076 self. reader.forward()1077 ch = self. reader.peek()1071 self.forward() 1072 ch = self.peek() 1078 1073 if ch in u'0123456789': 1079 1074 increment = int(ch) … … 1081 1076 raise ScannerError("while scanning a block scalar", start_mark, 1082 1077 "expected indentation indicator in the range 1-9, but found 0", 1083 self. reader.get_mark())1084 self. reader.forward()1078 self.get_mark()) 1079 self.forward() 1085 1080 elif ch in u'0123456789': 1086 1081 increment = int(ch) … … 1088 1083 raise ScannerError("while scanning a block scalar", start_mark, 1089 1084 "expected indentation indicator in the range 1-9, but found 0", 1090 self. reader.get_mark())1091 self. reader.forward()1092 ch = self. reader.peek()1085 self.get_mark()) 1086 self.forward() 1087 ch = self.peek() 1093 1088 if ch in u'+-': 1094 1089 if ch == '+': … … 1096 1091 else: 1097 1092 chomping = False 1098 self. reader.forward()1099 ch = self. reader.peek()1093 self.forward() 1094 ch = self.peek() 1100 1095 if ch not in u'\0 \r\n\x85\u2028\u2029': 1101 1096 raise ScannerError("while scanning a block scalar", start_mark, 1102 1097 "expected chomping or indentation indicators, but found %r" 1103 % ch.encode('utf-8'), self. reader.get_mark())1098 % ch.encode('utf-8'), self.get_mark()) 1104 1099 return chomping, increment 1105 1100 1106 1101 def scan_block_scalar_ignored_line(self, start_mark): 1107 1102 # See the specification for details. 1108 while self. reader.peek() == u' ':1109 self. reader.forward()1110 if self. reader.peek() == u'#':1111 while self. reader.peek() not in u'\0\r\n\x85\u2028\u2029':1112 self. reader.forward()1113 ch = self. reader.peek()1103 while self.peek() == u' ': 1104 self.forward() 1105 if self.peek() == u'#': 1106 while self.peek() not in u'\0\r\n\x85\u2028\u2029': 1107 self.forward() 1108 ch = self.peek() 1114 1109 if ch not in u'\0\r\n\x85\u2028\u2029': 1115 1110 raise ScannerError("while scanning a block scalar", start_mark, 1116 1111 "expected a comment or a line break, but found %r" 1117 % ch.encode('utf-8'), self. reader.get_mark())1112 % ch.encode('utf-8'), self.get_mark()) 1118 1113 self.scan_line_break() 1119 1114 … … 1122 1117 chunks = [] 1123 1118 max_indent = 0 1124 end_mark = self. reader.get_mark()1125 while self. reader.peek() in u' \r\n\x85\u2028\u2029':1126 if self. reader.peek() != u' ':1119 end_mark = self.get_mark() 1120 while self.peek() in u' \r\n\x85\u2028\u2029': 1121 if self.peek() != u' ': 1127 1122 chunks.append(self.scan_line_break()) 1128 end_mark = self. reader.get_mark()1123 end_mark = self.get_mark() 1129 1124 else: 1130 self. reader.forward()1131 if self. reader.column > max_indent:1132 max_indent = self. reader.column1125 self.forward() 1126 if self.column > max_indent: 1127 max_indent = self.column 1133 1128 return chunks, max_indent, end_mark 1134 1129 … … 1136 1131 # See the specification for details. 1137 1132 chunks = [] 1138 end_mark = self. reader.get_mark()1139 while self. reader.column < indent and self.reader.peek() == u' ':1140 self. reader.forward()1141 while self. reader.peek() in u'\r\n\x85\u2028\u2029':1133 end_mark = self.get_mark() 1134 while self.column < indent and self.peek() == u' ': 1135 self.forward() 1136 while self.peek() in u'\r\n\x85\u2028\u2029': 1142 1137 chunks.append(self.scan_line_break()) 1143 end_mark = self. reader.get_mark()1144 while self. reader.column < indent and self.reader.peek() == u' ':1145 self. reader.forward()1138 end_mark = self.get_mark() 1139 while self.column < indent and self.peek() == u' ': 1140 self.forward() 1146 1141 return chunks, end_mark 1147 1142 … … 1158 1153 double = False 1159 1154 chunks = [] 1160 start_mark = self. reader.get_mark()1161 quote = self. reader.peek()1162 self. reader.forward()1155 start_mark = self.get_mark() 1156 quote = self.peek() 1157 self.forward() 1163 1158 chunks.extend(self.scan_flow_scalar_non_spaces(double, start_mark)) 1164 while self. reader.peek() != quote:1159 while self.peek() != quote: 1165 1160 chunks.extend(self.scan_flow_scalar_spaces(double, start_mark)) 1166 1161 chunks.extend(self.scan_flow_scalar_non_spaces(double, start_mark)) 1167 self. reader.forward()1168 end_mark = self. reader.get_mark()1162 self.forward() 1163 end_mark = self.get_mark() 1169 1164 return ScalarToken(u''.join(chunks), False, start_mark, end_mark, 1170 1165 style) … … 1201 1196 while True: 1202 1197 length = 0 1203 while self. reader.peek(length) not in u'\'\"\\\0 \t\r\n\x85\u2028\u2029':1198 while self.peek(length) not in u'\'\"\\\0 \t\r\n\x85\u2028\u2029': 1204 1199 length += 1 1205 1200 if length: 1206 chunks.append(self. reader.prefix(length))1207 self. reader.forward(length)1208 ch = self. reader.peek()1209 if not double and ch == u'\'' and self. reader.peek(1) == u'\'':1201 chunks.append(self.prefix(length)) 1202 self.forward(length) 1203 ch = self.peek() 1204 if not double and ch == u'\'' and self.peek(1) == u'\'': 1210 1205 chunks.append(u'\'') 1211 self. reader.forward(2)1206 self.forward(2) 1212 1207 elif (double and ch == u'\'') or (not double and ch in u'\"\\'): 1213 1208 chunks.append(ch) 1214 self. reader.forward()1209 self.forward() 1215 1210 elif double and ch == u'\\': 1216 self. reader.forward()1217 ch = self. reader.peek()1211 self.forward() 1212 ch = self.peek() 1218 1213 if ch in self.ESCAPE_REPLACEMENTS: 1219 1214 chunks.append(self.ESCAPE_REPLACEMENTS[ch]) 1220 self. reader.forward()1215 self.forward() 1221 1216 elif ch in self.ESCAPE_CODES: 1222 1217 length = self.ESCAPE_CODES[ch] 1223 self. reader.forward()1218 self.forward() 1224 1219 for k in range(length): 1225 if self. reader.peek(k) not in u'0123456789ABCDEFabcdef':1220 if self.peek(k) not in u'0123456789ABCDEFabcdef': 1226 1221 raise ScannerError("while scanning a double-quoted scalar", start_mark, 1227 1222 "expected escape sequence of %d hexdecimal numbers, but found %r" % 1228 (length, self. reader.peek(k).encode('utf-8')), self.reader.get_mark())1229 code = int(self. reader.prefix(length), 16)1223 (length, self.peek(k).encode('utf-8')), self.get_mark()) 1224 code = int(self.prefix(length), 16) 1230 1225 chunks.append(unichr(code)) 1231 self. reader.forward(length)1226 self.forward(length) 1232 1227 elif ch in u'\r\n\x85\u2028\u2029': 1233 1228 self.scan_line_break() … … 1235 1230 else: 1236 1231 raise ScannerError("while scanning a double-quoted scalar", start_mark, 1237 "found unknown escape character %r" % ch.encode('utf-8'), self. reader.get_mark())1232 "found unknown escape character %r" % ch.encode('utf-8'), self.get_mark()) 1238 1233 else: 1239 1234 return chunks … … 1243 1238 chunks = [] 1244 1239 length = 0 1245 while self. reader.peek(length) in u' \t':1240 while self.peek(length) in u' \t': 1246 1241 length += 1 1247 whitespaces = self. reader.prefix(length)1248 self. reader.forward(length)1249 ch = self. reader.peek()1242 whitespaces = self.prefix(length) 1243 self.forward(length) 1244 ch = self.peek() 1250 1245 if ch == u'\0': 1251 1246 raise ScannerError("while scanning a quoted scalar", start_mark, 1252 "found unexpected end of stream", self. reader.get_mark())1247 "found unexpected end of stream", self.get_mark()) 1253 1248 elif ch in u'\r\n\x85\u2028\u2029': 1254 1249 line_break = self.scan_line_break() … … 1269 1264 # Instead of checking indentation, we check for document 1270 1265 # separators. 1271 prefix = self. reader.prefix(3)1266 prefix = self.prefix(3) 1272 1267 if (prefix == u'---' or prefix == u'...') \ 1273 and self. reader.peek(3) in u'\0 \t\r\n\x85\u2028\u2029':1268 and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 1274 1269 raise ScannerError("while scanning a quoted scalar", start_mark, 1275 "found unexpected document separator", self. reader.get_mark())1276 while self. reader.peek() in u' \t':1277 self. reader.forward()1278 if self. reader.peek() in u'\r\n\x85\u2028\u2029':1270 "found unexpected document separator", self.get_mark()) 1271 while self.peek() in u' \t': 1272 self.forward() 1273 if self.peek() in u'\r\n\x85\u2028\u2029': 1279 1274 chunks.append(self.scan_line_break()) 1280 1275 else: … … 1288 1283 # Indentation rules are loosed for the flow context. 1289 1284 chunks = [] 1290 start_mark = self. reader.get_mark()1285 start_mark = self.get_mark() 1291 1286 end_mark = start_mark 1292 1287 indent = self.indent+1 … … 1298 1293 while True: 1299 1294 length = 0 1300 if self. reader.peek() == u'#':1295 if self.peek() == u'#': 1301 1296 break 1302 1297 while True: 1303 ch = self. reader.peek(length)1298 ch = self.peek(length) 1304 1299 if ch in u'\0 \t\r\n\x85\u2028\u2029' \ 1305 1300 or (not self.flow_level and ch == u':' and 1306 self. reader.peek(length+1) in u'\0 \t\r\n\x28\u2028\u2029') \1301 self.peek(length+1) in u'\0 \t\r\n\x28\u2028\u2029') \ 1307 1302 or (self.flow_level and ch in u',:?[]{}'): 1308 1303 break … … 1312 1307 self.allow_simple_key = False 1313 1308 chunks.extend(spaces) 1314 chunks.append(self. reader.prefix(length))1315 self. reader.forward(length)1316 end_mark = self. reader.get_mark()1309 chunks.append(self.prefix(length)) 1310 self.forward(length) 1311 end_mark = self.get_mark() 1317 1312 spaces = self.scan_plain_spaces(indent, start_mark) 1318 if not spaces or self. reader.peek() == u'#' \1319 or (not self.flow_level and self. reader.column < indent):1313 if not spaces or self.peek() == u'#' \ 1314 or (not self.flow_level and self.column < indent): 1320 1315 break 1321 1316 return ScalarToken(u''.join(chunks), True, start_mark, end_mark) … … 1327 1322 chunks = [] 1328 1323 length = 0 1329 while self. reader.peek(length) in u' ':1324 while self.peek(length) in u' ': 1330 1325 length += 1 1331 whitespaces = self. reader.prefix(length)1332 self. reader.forward(length)1333 ch = self. reader.peek()1326 whitespaces = self.prefix(length) 1327 self.forward(length) 1328 ch = self.peek() 1334 1329 if ch in u'\r\n\x85\u2028\u2029': 1335 1330 line_break = self.scan_line_break() 1336 1331 self.allow_simple_key = True 1337 prefix = self. reader.prefix(3)1332 prefix = self.prefix(3) 1338 1333 if (prefix == u'---' or prefix == u'...') \ 1339 and self. reader.peek(3) in u'\0 \t\r\n\x85\u2028\u2029':1334 and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 1340 1335 return 1341 1336 breaks = [] 1342 while self. reader.peek() in u' \r\n\x85\u2028\u2029':1343 if self. reader.peek() == ' ':1344 self. reader.forward()1337 while self.peek() in u' \r\n\x85\u2028\u2029': 1338 if self.peek() == ' ': 1339 self.forward() 1345 1340 else: 1346 1341 breaks.append(self.scan_line_break()) 1347 prefix = self. reader.prefix(3)1342 prefix = self.prefix(3) 1348 1343 if (prefix == u'---' or prefix == u'...') \ 1349 and self. reader.peek(3) in u'\0 \t\r\n\x85\u2028\u2029':1344 and self.peek(3) in u'\0 \t\r\n\x85\u2028\u2029': 1350 1345 return 1351 1346 if line_break != u'\n': … … 1362 1357 # For some strange reasons, the specification does not allow '_' in 1363 1358 # tag handles. I have allowed it anyway. 1364 ch = self. reader.peek()1359 ch = self.peek() 1365 1360 if ch != u'!': 1366 1361 raise ScannerError("while scanning a %s" % name, start_mark, 1367 1362 "expected '!', but found %r" % ch.encode('utf-8'), 1368 self. reader.get_mark())1363 self.get_mark()) 1369 1364 length = 1 1370 ch = self. reader.peek(length)1365 ch = self.peek(length) 1371 1366 if ch != u' ': 1372 1367 while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ 1373 1368 or ch in u'-_': 1374 1369 length += 1 1375 ch = self. reader.peek(length)1370 ch = self.peek(length) 1376 1371 if ch != u'!': 1377 self. reader.forward(length)1372 self.forward(length) 1378 1373 raise ScannerError("while scanning a %s" % name, start_mark, 1379 1374 "expected '!', but found %r" % ch.encode('utf-8'), 1380 self. reader.get_mark())1375 self.get_mark()) 1381 1376 length += 1 1382 value = self. reader.prefix(length)1383 self. reader.forward(length)1377 value = self.prefix(length) 1378 self.forward(length) 1384 1379 return value 1385 1380 … … 1389 1384 chunks = [] 1390 1385 length = 0 1391 ch = self. reader.peek(length)1386 ch = self.peek(length) 1392 1387 while u'0' <= ch <= u'9' or u'A' <= ch <= 'Z' or u'a' <= ch <= 'z' \ 1393 1388 or ch in u'-;/?:@&=+$,_.!~*\'()[]%': 1394 1389 if ch == u'%': 1395 chunks.append(self. reader.prefix(length))1396 self. reader.forward(length)1390 chunks.append(self.prefix(length)) 1391 self.forward(length) 1397 1392 length = 0 1398 1393 chunks.append(self.scan_uri_escapes(name, start_mark)) 1399 1394 else: 1400 1395 length += 1 1401 ch = self. reader.peek(length)1396 ch = self.peek(length) 1402 1397 if length: 1403 chunks.append(self. reader.prefix(length))1404 self. reader.forward(length)1398 chunks.append(self.prefix(length)) 1399 self.forward(length) 1405 1400 length = 0 1406 1401 if not chunks: 1407 1402 raise ScannerError("while parsing a %s" % name, start_mark, 1408 1403 "expected URI, but found %r" % ch.encode('utf-8'), 1409 self. reader.get_mark())1404 self.get_mark()) 1410 1405 return u''.join(chunks) 1411 1406 … … 1413 1408 # See the specification for details. 1414 1409 bytes = [] 1415 mark = self. reader.get_mark()1416 while self. reader.peek() == u'%':1417 self. reader.forward()1410 mark = self.get_mark() 1411 while self.peek() == u'%': 1412 self.forward() 1418 1413 for k in range(2): 1419 if self. reader.peek(k) not in u'0123456789ABCDEFabcdef':1414 if self.peek(k) not in u'0123456789ABCDEFabcdef': 1420 1415 raise ScannerError("while scanning a %s" % name, start_mark, 1421 1416 "expected URI escape sequence of 2 hexdecimal numbers, but found %r" % 1422 (self. reader.peek(k).encode('utf-8')), self.reader.get_mark())1423 bytes.append(chr(int(self. reader.prefix(2), 16)))1424 self. reader.forward(2)1417 (self.peek(k).encode('utf-8')), self.get_mark()) 1418 bytes.append(chr(int(self.prefix(2), 16))) 1419 self.forward(2) 1425 1420 try: 1426 1421 value = unicode(''.join(bytes), 'utf-8') … … 1438 1433 # '\u2029 : '\u2029' 1439 1434 # default : '' 1440 ch = self. reader.peek()1435 ch = self.peek() 1441 1436 if ch in u'\r\n\x85': 1442 if self. reader.prefix(2) == u'\r\n':1443 self. reader.forward(2)1437 if self.prefix(2) == u'\r\n': 1438 self.forward(2) 1444 1439 else: 1445 self. reader.forward()1440 self.forward() 1446 1441 return u'\n' 1447 1442 elif ch in u'\u2028\u2029': 1448 self. reader.forward()1443 self.forward() 1449 1444 return ch 1450 1445 return u'' -
pyyaml/trunk/lib/yaml/serializer.py
r135 r136 13 13 ANCHOR_TEMPLATE = u'id%03d' 14 14 15 def __init__(self, emitter, encoding=None, line_break=None, canonical=None, 16 indent=None, width=None, allow_unicode=None): 17 self.emitter = emitter 15 def __init__(self, encoding=None, 16 explicit_start=None, explicit_end=None, version=None, tags=None): 17 self.use_encoding = encoding 18 self.use_explicit_start = explicit_start 19 self.use_explicit_end = explicit_end 20 self.use_version = version 21 self.use_tags = tags 18 22 self.serialized_nodes = {} 19 23 self.anchors = {} 20 24 self.last_anchor_id = 0 21 25 self.closed = None 22 self.open(encoding, line_break, canonical, indent, width, allow_unicode)23 26 24 def open(self, encoding=None, line_break=None, canonical=None, 25 indent=None, width=None, allow_unicode=None): 27 def open(self): 26 28 if self.closed is None: 27 self.emitter.emit(StreamStartEvent(encoding=encoding, 28 line_break=line_break, canonical=canonical, 29 indent=indent, width=width, allow_unicode=allow_unicode)) 29 self.emit(StreamStartEvent(encoding=self.use_encoding)) 30 30 self.closed = False 31 31 elif self.closed: … … 38 38 raise SerializerError("serializer is not opened") 39 39 elif not self.closed: 40 self.emit ter.emit(StreamEndEvent())40 self.emit(StreamEndEvent()) 41 41 self.closed = True 42 42 43 def __del__(self):44 self.close()43 #def __del__(self): 44 # self.close() 45 45 46 def serialize(self, node, explicit_start=None, explicit_end=None, 47 version=None, tags=None): 46 def serialize(self, node): 48 47 if self.closed is None: 49 48 raise SerializerError("serializer is not opened") 50 49 elif self.closed: 51 50 raise SerializerError("serializer is closed") 52 self.emit ter.emit(DocumentStartEvent(explicit=explicit_start,53 version= version, tags=tags))51 self.emit(DocumentStartEvent(explicit=self.use_explicit_start, 52 version=self.use_version, tags=self.use_tags)) 54 53 self.anchor_node(node) 55 54 self.serialize_node(node) 56 self.emit ter.emit(DocumentEndEvent(explicit=explicit_end))55 self.emit(DocumentEndEvent(explicit=self.use_explicit_end)) 57 56 self.serialized_nodes = {} 58 57 self.anchors = {} … … 80 79 alias = self.anchors[node] 81 80 if node in self.serialized_nodes: 82 self.emit ter.emit(AliasEvent(alias))81 self.emit(AliasEvent(alias)) 83 82 else: 84 83 self.serialized_nodes[node] = True 85 84 if isinstance(node, ScalarNode): 86 self.emitter.emit(ScalarEvent(alias, node.tag, node.value, 87 implicit=node.implicit, style=node.style)) 85 detected_tag = self.detect(node.value) 86 implicit = (node.tag == self.detect(node.value) 87 or (node.tag == self.DEFAULT_SCALAR_TAG 88 and detected_tag is None)) 89 self.emit(ScalarEvent(alias, node.tag, implicit, node.value, 90 style=node.style)) 88 91 elif isinstance(node, SequenceNode): 89 self.emitter.emit(SequenceStartEvent(alias, node.tag, 92 # TODO: 93 # 1) Check the current path in the Resolver. 94 # 2) Add the implicit flag to the SequenceStartEvent and 95 # MappingStartEvent. 96 tag = node.tag 97 if tag == self.DEFAULT_SEQUENCE_TAG and not self.canonical: 98 tag = None 99 self.emit(SequenceStartEvent(alias, tag, 90 100 flow_style=node.flow_style)) 91 101 for item in node.value: 92 102 self.serialize_node(item) 93 self.emit ter.emit(SequenceEndEvent())103 self.emit(SequenceEndEvent()) 94 104 elif isinstance(node, MappingNode): 95 self.emitter.emit(MappingStartEvent(alias, node.tag, 105 tag = node.tag 106 if tag == self.DEFAULT_MAPPING_TAG and not self.canonical: 107 tag = None 108 self.emit(MappingStartEvent(alias, tag, 96 109 flow_style=node.flow_style)) 97 for key in node.value: 98 self.serialize_node(key) 99 self.serialize_node(node.value[key]) 100 self.emitter.emit(MappingEndEvent()) 110 if hasattr(node.value, 'keys'): 111 for key in node.value.keys(): 112 self.serialize_node(key) 113 self.serialize_node(node.value[key]) 114 else: 115 for key, value in node.value: 116 self.serialize_node(key) 117 self.serialize_node(value) 118 self.emit(MappingEndEvent()) 101 119
