Imported Upstream version 3.10
[platform/upstream/python-PyYAML.git] / ext / _yaml.pyx
1
2 import yaml
3
4 def get_version_string():
5     cdef char *value
6     value = yaml_get_version_string()
7     if PY_MAJOR_VERSION < 3:
8         return value
9     else:
10         return PyUnicode_FromString(value)
11
12 def get_version():
13     cdef int major, minor, patch
14     yaml_get_version(&major, &minor, &patch)
15     return (major, minor, patch)
16
17 #Mark = yaml.error.Mark
18 YAMLError = yaml.error.YAMLError
19 ReaderError = yaml.reader.ReaderError
20 ScannerError = yaml.scanner.ScannerError
21 ParserError = yaml.parser.ParserError
22 ComposerError = yaml.composer.ComposerError
23 ConstructorError = yaml.constructor.ConstructorError
24 EmitterError = yaml.emitter.EmitterError
25 SerializerError = yaml.serializer.SerializerError
26 RepresenterError = yaml.representer.RepresenterError
27
28 StreamStartToken = yaml.tokens.StreamStartToken
29 StreamEndToken = yaml.tokens.StreamEndToken
30 DirectiveToken = yaml.tokens.DirectiveToken
31 DocumentStartToken = yaml.tokens.DocumentStartToken
32 DocumentEndToken = yaml.tokens.DocumentEndToken
33 BlockSequenceStartToken = yaml.tokens.BlockSequenceStartToken
34 BlockMappingStartToken = yaml.tokens.BlockMappingStartToken
35 BlockEndToken = yaml.tokens.BlockEndToken
36 FlowSequenceStartToken = yaml.tokens.FlowSequenceStartToken
37 FlowMappingStartToken = yaml.tokens.FlowMappingStartToken
38 FlowSequenceEndToken = yaml.tokens.FlowSequenceEndToken
39 FlowMappingEndToken = yaml.tokens.FlowMappingEndToken
40 KeyToken = yaml.tokens.KeyToken
41 ValueToken = yaml.tokens.ValueToken
42 BlockEntryToken = yaml.tokens.BlockEntryToken
43 FlowEntryToken = yaml.tokens.FlowEntryToken
44 AliasToken = yaml.tokens.AliasToken
45 AnchorToken = yaml.tokens.AnchorToken
46 TagToken = yaml.tokens.TagToken
47 ScalarToken = yaml.tokens.ScalarToken
48
49 StreamStartEvent = yaml.events.StreamStartEvent
50 StreamEndEvent = yaml.events.StreamEndEvent
51 DocumentStartEvent = yaml.events.DocumentStartEvent
52 DocumentEndEvent = yaml.events.DocumentEndEvent
53 AliasEvent = yaml.events.AliasEvent
54 ScalarEvent = yaml.events.ScalarEvent
55 SequenceStartEvent = yaml.events.SequenceStartEvent
56 SequenceEndEvent = yaml.events.SequenceEndEvent
57 MappingStartEvent = yaml.events.MappingStartEvent
58 MappingEndEvent = yaml.events.MappingEndEvent
59
60 ScalarNode = yaml.nodes.ScalarNode
61 SequenceNode = yaml.nodes.SequenceNode
62 MappingNode = yaml.nodes.MappingNode
63
64 cdef class Mark:
65     cdef readonly object name
66     cdef readonly int index
67     cdef readonly int line
68     cdef readonly int column
69     cdef readonly buffer
70     cdef readonly pointer
71
72     def __init__(self, object name, int index, int line, int column,
73             object buffer, object pointer):
74         self.name = name
75         self.index = index
76         self.line = line
77         self.column = column
78         self.buffer = buffer
79         self.pointer = pointer
80
81     def get_snippet(self):
82         return None
83
84     def __str__(self):
85         where = "  in \"%s\", line %d, column %d"   \
86                 % (self.name, self.line+1, self.column+1)
87         return where
88
89 #class YAMLError(Exception):
90 #    pass
91 #
92 #class MarkedYAMLError(YAMLError):
93 #
94 #    def __init__(self, context=None, context_mark=None,
95 #            problem=None, problem_mark=None, note=None):
96 #        self.context = context
97 #        self.context_mark = context_mark
98 #        self.problem = problem
99 #        self.problem_mark = problem_mark
100 #        self.note = note
101 #
102 #    def __str__(self):
103 #        lines = []
104 #        if self.context is not None:
105 #            lines.append(self.context)
106 #        if self.context_mark is not None  \
107 #            and (self.problem is None or self.problem_mark is None
108 #                    or self.context_mark.name != self.problem_mark.name
109 #                    or self.context_mark.line != self.problem_mark.line
110 #                    or self.context_mark.column != self.problem_mark.column):
111 #            lines.append(str(self.context_mark))
112 #        if self.problem is not None:
113 #            lines.append(self.problem)
114 #        if self.problem_mark is not None:
115 #            lines.append(str(self.problem_mark))
116 #        if self.note is not None:
117 #            lines.append(self.note)
118 #        return '\n'.join(lines)
119 #
120 #class ReaderError(YAMLError):
121 #
122 #    def __init__(self, name, position, character, encoding, reason):
123 #        self.name = name
124 #        self.character = character
125 #        self.position = position
126 #        self.encoding = encoding
127 #        self.reason = reason
128 #
129 #    def __str__(self):
130 #        if isinstance(self.character, str):
131 #            return "'%s' codec can't decode byte #x%02x: %s\n"  \
132 #                    "  in \"%s\", position %d"    \
133 #                    % (self.encoding, ord(self.character), self.reason,
134 #                            self.name, self.position)
135 #        else:
136 #            return "unacceptable character #x%04x: %s\n"    \
137 #                    "  in \"%s\", position %d"    \
138 #                    % (ord(self.character), self.reason,
139 #                            self.name, self.position)
140 #
141 #class ScannerError(MarkedYAMLError):
142 #    pass
143 #
144 #class ParserError(MarkedYAMLError):
145 #    pass
146 #
147 #class EmitterError(YAMLError):
148 #    pass
149 #
150 #cdef class Token:
151 #    cdef readonly Mark start_mark
152 #    cdef readonly Mark end_mark
153 #    def __init__(self, Mark start_mark, Mark end_mark):
154 #        self.start_mark = start_mark
155 #        self.end_mark = end_mark
156 #
157 #cdef class StreamStartToken(Token):
158 #    cdef readonly object encoding
159 #    def __init__(self, Mark start_mark, Mark end_mark, encoding):
160 #        self.start_mark = start_mark
161 #        self.end_mark = end_mark
162 #        self.encoding = encoding
163 #
164 #cdef class StreamEndToken(Token):
165 #    pass
166 #
167 #cdef class DirectiveToken(Token):
168 #    cdef readonly object name
169 #    cdef readonly object value
170 #    def __init__(self, name, value, Mark start_mark, Mark end_mark):
171 #        self.name = name
172 #        self.value = value
173 #        self.start_mark = start_mark
174 #        self.end_mark = end_mark
175 #
176 #cdef class DocumentStartToken(Token):
177 #    pass
178 #
179 #cdef class DocumentEndToken(Token):
180 #    pass
181 #
182 #cdef class BlockSequenceStartToken(Token):
183 #    pass
184 #
185 #cdef class BlockMappingStartToken(Token):
186 #    pass
187 #
188 #cdef class BlockEndToken(Token):
189 #    pass
190 #
191 #cdef class FlowSequenceStartToken(Token):
192 #    pass
193 #
194 #cdef class FlowMappingStartToken(Token):
195 #    pass
196 #
197 #cdef class FlowSequenceEndToken(Token):
198 #    pass
199 #
200 #cdef class FlowMappingEndToken(Token):
201 #    pass
202 #
203 #cdef class KeyToken(Token):
204 #    pass
205 #
206 #cdef class ValueToken(Token):
207 #    pass
208 #
209 #cdef class BlockEntryToken(Token):
210 #    pass
211 #
212 #cdef class FlowEntryToken(Token):
213 #    pass
214 #
215 #cdef class AliasToken(Token):
216 #    cdef readonly object value
217 #    def __init__(self, value, Mark start_mark, Mark end_mark):
218 #        self.value = value
219 #        self.start_mark = start_mark
220 #        self.end_mark = end_mark
221 #
222 #cdef class AnchorToken(Token):
223 #    cdef readonly object value
224 #    def __init__(self, value, Mark start_mark, Mark end_mark):
225 #        self.value = value
226 #        self.start_mark = start_mark
227 #        self.end_mark = end_mark
228 #
229 #cdef class TagToken(Token):
230 #    cdef readonly object value
231 #    def __init__(self, value, Mark start_mark, Mark end_mark):
232 #        self.value = value
233 #        self.start_mark = start_mark
234 #        self.end_mark = end_mark
235 #
236 #cdef class ScalarToken(Token):
237 #    cdef readonly object value
238 #    cdef readonly object plain
239 #    cdef readonly object style
240 #    def __init__(self, value, plain, Mark start_mark, Mark end_mark, style=None):
241 #        self.value = value
242 #        self.plain = plain
243 #        self.start_mark = start_mark
244 #        self.end_mark = end_mark
245 #        self.style = style
246
247 cdef class CParser:
248
249     cdef yaml_parser_t parser
250     cdef yaml_event_t parsed_event
251
252     cdef object stream
253     cdef object stream_name
254     cdef object current_token
255     cdef object current_event
256     cdef object anchors
257     cdef object stream_cache
258     cdef int stream_cache_len
259     cdef int stream_cache_pos
260     cdef int unicode_source
261
262     def __init__(self, stream):
263         cdef is_readable
264         if yaml_parser_initialize(&self.parser) == 0:
265             raise MemoryError
266         self.parsed_event.type = YAML_NO_EVENT
267         is_readable = 1
268         try:
269             stream.read
270         except AttributeError:
271             is_readable = 0
272         self.unicode_source = 0
273         if is_readable:
274             self.stream = stream
275             try:
276                 self.stream_name = stream.name
277             except AttributeError:
278                 if PY_MAJOR_VERSION < 3:
279                     self.stream_name = '<file>'
280                 else:
281                     self.stream_name = u'<file>'
282             self.stream_cache = None
283             self.stream_cache_len = 0
284             self.stream_cache_pos = 0
285             yaml_parser_set_input(&self.parser, input_handler, <void *>self)
286         else:
287             if PyUnicode_CheckExact(stream) != 0:
288                 stream = PyUnicode_AsUTF8String(stream)
289                 if PY_MAJOR_VERSION < 3:
290                     self.stream_name = '<unicode string>'
291                 else:
292                     self.stream_name = u'<unicode string>'
293                 self.unicode_source = 1
294             else:
295                 if PY_MAJOR_VERSION < 3:
296                     self.stream_name = '<byte string>'
297                 else:
298                     self.stream_name = u'<byte string>'
299             if PyString_CheckExact(stream) == 0:
300                 if PY_MAJOR_VERSION < 3:
301                     raise TypeError("a string or stream input is required")
302                 else:
303                     raise TypeError(u"a string or stream input is required")
304             self.stream = stream
305             yaml_parser_set_input_string(&self.parser, PyString_AS_STRING(stream), PyString_GET_SIZE(stream))
306         self.current_token = None
307         self.current_event = None
308         self.anchors = {}
309
310     def __dealloc__(self):
311         yaml_parser_delete(&self.parser)
312         yaml_event_delete(&self.parsed_event)
313
314     def dispose(self):
315         pass
316
317     cdef object _parser_error(self):
318         if self.parser.error == YAML_MEMORY_ERROR:
319             return MemoryError
320         elif self.parser.error == YAML_READER_ERROR:
321             if PY_MAJOR_VERSION < 3:
322                 return ReaderError(self.stream_name, self.parser.problem_offset,
323                         self.parser.problem_value, '?', self.parser.problem)
324             else:
325                 return ReaderError(self.stream_name, self.parser.problem_offset,
326                         self.parser.problem_value, u'?', PyUnicode_FromString(self.parser.problem))
327         elif self.parser.error == YAML_SCANNER_ERROR    \
328                 or self.parser.error == YAML_PARSER_ERROR:
329             context_mark = None
330             problem_mark = None
331             if self.parser.context != NULL:
332                 context_mark = Mark(self.stream_name,
333                         self.parser.context_mark.index,
334                         self.parser.context_mark.line,
335                         self.parser.context_mark.column, None, None)
336             if self.parser.problem != NULL:
337                 problem_mark = Mark(self.stream_name,
338                         self.parser.problem_mark.index,
339                         self.parser.problem_mark.line,
340                         self.parser.problem_mark.column, None, None)
341             context = None
342             if self.parser.context != NULL:
343                 if PY_MAJOR_VERSION < 3:
344                     context = self.parser.context
345                 else:
346                     context = PyUnicode_FromString(self.parser.context)
347             if PY_MAJOR_VERSION < 3:
348                 problem = self.parser.problem
349             else:
350                 problem = PyUnicode_FromString(self.parser.problem)
351             if self.parser.error == YAML_SCANNER_ERROR:
352                 return ScannerError(context, context_mark, problem, problem_mark)
353             else:
354                 return ParserError(context, context_mark, problem, problem_mark)
355         if PY_MAJOR_VERSION < 3:
356             raise ValueError("no parser error")
357         else:
358             raise ValueError(u"no parser error")
359
360     def raw_scan(self):
361         cdef yaml_token_t token
362         cdef int done
363         cdef int count
364         count = 0
365         done = 0
366         while done == 0:
367             if yaml_parser_scan(&self.parser, &token) == 0:
368                 error = self._parser_error()
369                 raise error
370             if token.type == YAML_NO_TOKEN:
371                 done = 1
372             else:
373                 count = count+1
374             yaml_token_delete(&token)
375         return count
376
377     cdef object _scan(self):
378         cdef yaml_token_t token
379         if yaml_parser_scan(&self.parser, &token) == 0:
380             error = self._parser_error()
381             raise error
382         token_object = self._token_to_object(&token)
383         yaml_token_delete(&token)
384         return token_object
385
386     cdef object _token_to_object(self, yaml_token_t *token):
387         start_mark = Mark(self.stream_name,
388                 token.start_mark.index,
389                 token.start_mark.line,
390                 token.start_mark.column,
391                 None, None)
392         end_mark = Mark(self.stream_name,
393                 token.end_mark.index,
394                 token.end_mark.line,
395                 token.end_mark.column,
396                 None, None)
397         if token.type == YAML_NO_TOKEN:
398             return None
399         elif token.type == YAML_STREAM_START_TOKEN:
400             encoding = None
401             if token.data.stream_start.encoding == YAML_UTF8_ENCODING:
402                 if self.unicode_source == 0:
403                     encoding = u"utf-8"
404             elif token.data.stream_start.encoding == YAML_UTF16LE_ENCODING:
405                 encoding = u"utf-16-le"
406             elif token.data.stream_start.encoding == YAML_UTF16BE_ENCODING:
407                 encoding = u"utf-16-be"
408             return StreamStartToken(start_mark, end_mark, encoding)
409         elif token.type == YAML_STREAM_END_TOKEN:
410             return StreamEndToken(start_mark, end_mark)
411         elif token.type == YAML_VERSION_DIRECTIVE_TOKEN:
412             return DirectiveToken(u"YAML",
413                     (token.data.version_directive.major,
414                         token.data.version_directive.minor),
415                     start_mark, end_mark)
416         elif token.type == YAML_TAG_DIRECTIVE_TOKEN:
417             handle = PyUnicode_FromString(token.data.tag_directive.handle)
418             prefix = PyUnicode_FromString(token.data.tag_directive.prefix)
419             return DirectiveToken(u"TAG", (handle, prefix),
420                     start_mark, end_mark)
421         elif token.type == YAML_DOCUMENT_START_TOKEN:
422             return DocumentStartToken(start_mark, end_mark)
423         elif token.type == YAML_DOCUMENT_END_TOKEN:
424             return DocumentEndToken(start_mark, end_mark)
425         elif token.type == YAML_BLOCK_SEQUENCE_START_TOKEN:
426             return BlockSequenceStartToken(start_mark, end_mark)
427         elif token.type == YAML_BLOCK_MAPPING_START_TOKEN:
428             return BlockMappingStartToken(start_mark, end_mark)
429         elif token.type == YAML_BLOCK_END_TOKEN:
430             return BlockEndToken(start_mark, end_mark)
431         elif token.type == YAML_FLOW_SEQUENCE_START_TOKEN:
432             return FlowSequenceStartToken(start_mark, end_mark)
433         elif token.type == YAML_FLOW_SEQUENCE_END_TOKEN:
434             return FlowSequenceEndToken(start_mark, end_mark)
435         elif token.type == YAML_FLOW_MAPPING_START_TOKEN:
436             return FlowMappingStartToken(start_mark, end_mark)
437         elif token.type == YAML_FLOW_MAPPING_END_TOKEN:
438             return FlowMappingEndToken(start_mark, end_mark)
439         elif token.type == YAML_BLOCK_ENTRY_TOKEN:
440             return BlockEntryToken(start_mark, end_mark)
441         elif token.type == YAML_FLOW_ENTRY_TOKEN:
442             return FlowEntryToken(start_mark, end_mark)
443         elif token.type == YAML_KEY_TOKEN:
444             return KeyToken(start_mark, end_mark)
445         elif token.type == YAML_VALUE_TOKEN:
446             return ValueToken(start_mark, end_mark)
447         elif token.type == YAML_ALIAS_TOKEN:
448             value = PyUnicode_FromString(token.data.alias.value)
449             return AliasToken(value, start_mark, end_mark)
450         elif token.type == YAML_ANCHOR_TOKEN:
451             value = PyUnicode_FromString(token.data.anchor.value)
452             return AnchorToken(value, start_mark, end_mark)
453         elif token.type == YAML_TAG_TOKEN:
454             handle = PyUnicode_FromString(token.data.tag.handle)
455             suffix = PyUnicode_FromString(token.data.tag.suffix)
456             if not handle:
457                 handle = None
458             return TagToken((handle, suffix), start_mark, end_mark)
459         elif token.type == YAML_SCALAR_TOKEN:
460             value = PyUnicode_DecodeUTF8(token.data.scalar.value,
461                     token.data.scalar.length, 'strict')
462             plain = False
463             style = None
464             if token.data.scalar.style == YAML_PLAIN_SCALAR_STYLE:
465                 plain = True
466                 style = u''
467             elif token.data.scalar.style == YAML_SINGLE_QUOTED_SCALAR_STYLE:
468                 style = u'\''
469             elif token.data.scalar.style == YAML_DOUBLE_QUOTED_SCALAR_STYLE:
470                 style = u'"'
471             elif token.data.scalar.style == YAML_LITERAL_SCALAR_STYLE:
472                 style = u'|'
473             elif token.data.scalar.style == YAML_FOLDED_SCALAR_STYLE:
474                 style = u'>'
475             return ScalarToken(value, plain,
476                     start_mark, end_mark, style)
477         else:
478             if PY_MAJOR_VERSION < 3:
479                 raise ValueError("unknown token type")
480             else:
481                 raise ValueError(u"unknown token type")
482
483     def get_token(self):
484         if self.current_token is not None:
485             value = self.current_token
486             self.current_token = None
487         else:
488             value = self._scan()
489         return value
490
491     def peek_token(self):
492         if self.current_token is None:
493             self.current_token = self._scan()
494         return self.current_token
495
496     def check_token(self, *choices):
497         if self.current_token is None:
498             self.current_token = self._scan()
499         if self.current_token is None:
500             return False
501         if not choices:
502             return True
503         token_class = self.current_token.__class__
504         for choice in choices:
505             if token_class is choice:
506                 return True
507         return False
508
509     def raw_parse(self):
510         cdef yaml_event_t event
511         cdef int done
512         cdef int count
513         count = 0
514         done = 0
515         while done == 0:
516             if yaml_parser_parse(&self.parser, &event) == 0:
517                 error = self._parser_error()
518                 raise error
519             if event.type == YAML_NO_EVENT:
520                 done = 1
521             else:
522                 count = count+1
523             yaml_event_delete(&event)
524         return count
525
526     cdef object _parse(self):
527         cdef yaml_event_t event
528         if yaml_parser_parse(&self.parser, &event) == 0:
529             error = self._parser_error()
530             raise error
531         event_object = self._event_to_object(&event)
532         yaml_event_delete(&event)
533         return event_object
534
535     cdef object _event_to_object(self, yaml_event_t *event):
536         cdef yaml_tag_directive_t *tag_directive
537         start_mark = Mark(self.stream_name,
538                 event.start_mark.index,
539                 event.start_mark.line,
540                 event.start_mark.column,
541                 None, None)
542         end_mark = Mark(self.stream_name,
543                 event.end_mark.index,
544                 event.end_mark.line,
545                 event.end_mark.column,
546                 None, None)
547         if event.type == YAML_NO_EVENT:
548             return None
549         elif event.type == YAML_STREAM_START_EVENT:
550             encoding = None
551             if event.data.stream_start.encoding == YAML_UTF8_ENCODING:
552                 if self.unicode_source == 0:
553                     encoding = u"utf-8"
554             elif event.data.stream_start.encoding == YAML_UTF16LE_ENCODING:
555                 encoding = u"utf-16-le"
556             elif event.data.stream_start.encoding == YAML_UTF16BE_ENCODING:
557                 encoding = u"utf-16-be"
558             return StreamStartEvent(start_mark, end_mark, encoding)
559         elif event.type == YAML_STREAM_END_EVENT:
560             return StreamEndEvent(start_mark, end_mark)
561         elif event.type == YAML_DOCUMENT_START_EVENT:
562             explicit = False
563             if event.data.document_start.implicit == 0:
564                 explicit = True
565             version = None
566             if event.data.document_start.version_directive != NULL:
567                 version = (event.data.document_start.version_directive.major,
568                         event.data.document_start.version_directive.minor)
569             tags = None
570             if event.data.document_start.tag_directives.start != NULL:
571                 tags = {}
572                 tag_directive = event.data.document_start.tag_directives.start
573                 while tag_directive != event.data.document_start.tag_directives.end:
574                     handle = PyUnicode_FromString(tag_directive.handle)
575                     prefix = PyUnicode_FromString(tag_directive.prefix)
576                     tags[handle] = prefix
577                     tag_directive = tag_directive+1
578             return DocumentStartEvent(start_mark, end_mark,
579                     explicit, version, tags)
580         elif event.type == YAML_DOCUMENT_END_EVENT:
581             explicit = False
582             if event.data.document_end.implicit == 0:
583                 explicit = True
584             return DocumentEndEvent(start_mark, end_mark, explicit)
585         elif event.type == YAML_ALIAS_EVENT:
586             anchor = PyUnicode_FromString(event.data.alias.anchor)
587             return AliasEvent(anchor, start_mark, end_mark)
588         elif event.type == YAML_SCALAR_EVENT:
589             anchor = None
590             if event.data.scalar.anchor != NULL:
591                 anchor = PyUnicode_FromString(event.data.scalar.anchor)
592             tag = None
593             if event.data.scalar.tag != NULL:
594                 tag = PyUnicode_FromString(event.data.scalar.tag)
595             value = PyUnicode_DecodeUTF8(event.data.scalar.value,
596                     event.data.scalar.length, 'strict')
597             plain_implicit = False
598             if event.data.scalar.plain_implicit == 1:
599                 plain_implicit = True
600             quoted_implicit = False
601             if event.data.scalar.quoted_implicit == 1:
602                 quoted_implicit = True
603             style = None
604             if event.data.scalar.style == YAML_PLAIN_SCALAR_STYLE:
605                 style = u''
606             elif event.data.scalar.style == YAML_SINGLE_QUOTED_SCALAR_STYLE:
607                 style = u'\''
608             elif event.data.scalar.style == YAML_DOUBLE_QUOTED_SCALAR_STYLE:
609                 style = u'"'
610             elif event.data.scalar.style == YAML_LITERAL_SCALAR_STYLE:
611                 style = u'|'
612             elif event.data.scalar.style == YAML_FOLDED_SCALAR_STYLE:
613                 style = u'>'
614             return ScalarEvent(anchor, tag,
615                     (plain_implicit, quoted_implicit),
616                     value, start_mark, end_mark, style)
617         elif event.type == YAML_SEQUENCE_START_EVENT:
618             anchor = None
619             if event.data.sequence_start.anchor != NULL:
620                 anchor = PyUnicode_FromString(event.data.sequence_start.anchor)
621             tag = None
622             if event.data.sequence_start.tag != NULL:
623                 tag = PyUnicode_FromString(event.data.sequence_start.tag)
624             implicit = False
625             if event.data.sequence_start.implicit == 1:
626                 implicit = True
627             flow_style = None
628             if event.data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE:
629                 flow_style = True
630             elif event.data.sequence_start.style == YAML_BLOCK_SEQUENCE_STYLE:
631                 flow_style = False
632             return SequenceStartEvent(anchor, tag, implicit,
633                     start_mark, end_mark, flow_style)
634         elif event.type == YAML_MAPPING_START_EVENT:
635             anchor = None
636             if event.data.mapping_start.anchor != NULL:
637                 anchor = PyUnicode_FromString(event.data.mapping_start.anchor)
638             tag = None
639             if event.data.mapping_start.tag != NULL:
640                 tag = PyUnicode_FromString(event.data.mapping_start.tag)
641             implicit = False
642             if event.data.mapping_start.implicit == 1:
643                 implicit = True
644             flow_style = None
645             if event.data.mapping_start.style == YAML_FLOW_MAPPING_STYLE:
646                 flow_style = True
647             elif event.data.mapping_start.style == YAML_BLOCK_MAPPING_STYLE:
648                 flow_style = False
649             return MappingStartEvent(anchor, tag, implicit,
650                     start_mark, end_mark, flow_style)
651         elif event.type == YAML_SEQUENCE_END_EVENT:
652             return SequenceEndEvent(start_mark, end_mark)
653         elif event.type == YAML_MAPPING_END_EVENT:
654             return MappingEndEvent(start_mark, end_mark)
655         else:
656             if PY_MAJOR_VERSION < 3:
657                 raise ValueError("unknown event type")
658             else:
659                 raise ValueError(u"unknown event type")
660
661     def get_event(self):
662         if self.current_event is not None:
663             value = self.current_event
664             self.current_event = None
665         else:
666             value = self._parse()
667         return value
668
669     def peek_event(self):
670         if self.current_event is None:
671             self.current_event = self._parse()
672         return self.current_event
673
674     def check_event(self, *choices):
675         if self.current_event is None:
676             self.current_event = self._parse()
677         if self.current_event is None:
678             return False
679         if not choices:
680             return True
681         event_class = self.current_event.__class__
682         for choice in choices:
683             if event_class is choice:
684                 return True
685         return False
686
687     def check_node(self):
688         self._parse_next_event()
689         if self.parsed_event.type == YAML_STREAM_START_EVENT:
690             yaml_event_delete(&self.parsed_event)
691             self._parse_next_event()
692         if self.parsed_event.type != YAML_STREAM_END_EVENT:
693             return True
694         return False
695
696     def get_node(self):
697         self._parse_next_event()
698         if self.parsed_event.type != YAML_STREAM_END_EVENT:
699             return self._compose_document()
700
701     def get_single_node(self):
702         self._parse_next_event()
703         yaml_event_delete(&self.parsed_event)
704         self._parse_next_event()
705         document = None
706         if self.parsed_event.type != YAML_STREAM_END_EVENT:
707             document = self._compose_document()
708         self._parse_next_event()
709         if self.parsed_event.type != YAML_STREAM_END_EVENT:
710             mark = Mark(self.stream_name,
711                     self.parsed_event.start_mark.index,
712                     self.parsed_event.start_mark.line,
713                     self.parsed_event.start_mark.column,
714                     None, None)
715             if PY_MAJOR_VERSION < 3:
716                 raise ComposerError("expected a single document in the stream",
717                         document.start_mark, "but found another document", mark)
718             else:
719                 raise ComposerError(u"expected a single document in the stream",
720                         document.start_mark, u"but found another document", mark)
721         return document
722
723     cdef object _compose_document(self):
724         yaml_event_delete(&self.parsed_event)
725         node = self._compose_node(None, None)
726         self._parse_next_event()
727         yaml_event_delete(&self.parsed_event)
728         self.anchors = {}
729         return node
730
731     cdef object _compose_node(self, object parent, object index):
732         self._parse_next_event()
733         if self.parsed_event.type == YAML_ALIAS_EVENT:
734             anchor = PyUnicode_FromString(self.parsed_event.data.alias.anchor)
735             if anchor not in self.anchors:
736                 mark = Mark(self.stream_name,
737                         self.parsed_event.start_mark.index,
738                         self.parsed_event.start_mark.line,
739                         self.parsed_event.start_mark.column,
740                         None, None)
741                 if PY_MAJOR_VERSION < 3:
742                     raise ComposerError(None, None, "found undefined alias", mark)
743                 else:
744                     raise ComposerError(None, None, u"found undefined alias", mark)
745             yaml_event_delete(&self.parsed_event)
746             return self.anchors[anchor]
747         anchor = None
748         if self.parsed_event.type == YAML_SCALAR_EVENT  \
749                 and self.parsed_event.data.scalar.anchor != NULL:
750             anchor = PyUnicode_FromString(self.parsed_event.data.scalar.anchor)
751         elif self.parsed_event.type == YAML_SEQUENCE_START_EVENT    \
752                 and self.parsed_event.data.sequence_start.anchor != NULL:
753             anchor = PyUnicode_FromString(self.parsed_event.data.sequence_start.anchor)
754         elif self.parsed_event.type == YAML_MAPPING_START_EVENT    \
755                 and self.parsed_event.data.mapping_start.anchor != NULL:
756             anchor = PyUnicode_FromString(self.parsed_event.data.mapping_start.anchor)
757         if anchor is not None:
758             if anchor in self.anchors:
759                 mark = Mark(self.stream_name,
760                         self.parsed_event.start_mark.index,
761                         self.parsed_event.start_mark.line,
762                         self.parsed_event.start_mark.column,
763                         None, None)
764                 if PY_MAJOR_VERSION < 3:
765                     raise ComposerError("found duplicate anchor; first occurence",
766                             self.anchors[anchor].start_mark, "second occurence", mark)
767                 else:
768                     raise ComposerError(u"found duplicate anchor; first occurence",
769                             self.anchors[anchor].start_mark, u"second occurence", mark)
770         self.descend_resolver(parent, index)
771         if self.parsed_event.type == YAML_SCALAR_EVENT:
772             node = self._compose_scalar_node(anchor)
773         elif self.parsed_event.type == YAML_SEQUENCE_START_EVENT:
774             node = self._compose_sequence_node(anchor)
775         elif self.parsed_event.type == YAML_MAPPING_START_EVENT:
776             node = self._compose_mapping_node(anchor)
777         self.ascend_resolver()
778         return node
779
780     cdef _compose_scalar_node(self, object anchor):
781         start_mark = Mark(self.stream_name,
782                 self.parsed_event.start_mark.index,
783                 self.parsed_event.start_mark.line,
784                 self.parsed_event.start_mark.column,
785                 None, None)
786         end_mark = Mark(self.stream_name,
787                 self.parsed_event.end_mark.index,
788                 self.parsed_event.end_mark.line,
789                 self.parsed_event.end_mark.column,
790                 None, None)
791         value = PyUnicode_DecodeUTF8(self.parsed_event.data.scalar.value,
792                 self.parsed_event.data.scalar.length, 'strict')
793         plain_implicit = False
794         if self.parsed_event.data.scalar.plain_implicit == 1:
795             plain_implicit = True
796         quoted_implicit = False
797         if self.parsed_event.data.scalar.quoted_implicit == 1:
798             quoted_implicit = True
799         if self.parsed_event.data.scalar.tag == NULL    \
800                 or (self.parsed_event.data.scalar.tag[0] == c'!'
801                         and self.parsed_event.data.scalar.tag[1] == c'\0'):
802             tag = self.resolve(ScalarNode, value, (plain_implicit, quoted_implicit))
803         else:
804             tag = PyUnicode_FromString(self.parsed_event.data.scalar.tag)
805         style = None
806         if self.parsed_event.data.scalar.style == YAML_PLAIN_SCALAR_STYLE:
807             style = u''
808         elif self.parsed_event.data.scalar.style == YAML_SINGLE_QUOTED_SCALAR_STYLE:
809             style = u'\''
810         elif self.parsed_event.data.scalar.style == YAML_DOUBLE_QUOTED_SCALAR_STYLE:
811             style = u'"'
812         elif self.parsed_event.data.scalar.style == YAML_LITERAL_SCALAR_STYLE:
813             style = u'|'
814         elif self.parsed_event.data.scalar.style == YAML_FOLDED_SCALAR_STYLE:
815             style = u'>'
816         node = ScalarNode(tag, value, start_mark, end_mark, style)
817         if anchor is not None:
818             self.anchors[anchor] = node
819         yaml_event_delete(&self.parsed_event)
820         return node
821
822     cdef _compose_sequence_node(self, object anchor):
823         cdef int index
824         start_mark = Mark(self.stream_name,
825                 self.parsed_event.start_mark.index,
826                 self.parsed_event.start_mark.line,
827                 self.parsed_event.start_mark.column,
828                 None, None)
829         implicit = False
830         if self.parsed_event.data.sequence_start.implicit == 1:
831             implicit = True
832         if self.parsed_event.data.sequence_start.tag == NULL    \
833                 or (self.parsed_event.data.sequence_start.tag[0] == c'!'
834                         and self.parsed_event.data.sequence_start.tag[1] == c'\0'):
835             tag = self.resolve(SequenceNode, None, implicit)
836         else:
837             tag = PyUnicode_FromString(self.parsed_event.data.sequence_start.tag)
838         flow_style = None
839         if self.parsed_event.data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE:
840             flow_style = True
841         elif self.parsed_event.data.sequence_start.style == YAML_BLOCK_SEQUENCE_STYLE:
842             flow_style = False
843         value = []
844         node = SequenceNode(tag, value, start_mark, None, flow_style)
845         if anchor is not None:
846             self.anchors[anchor] = node
847         yaml_event_delete(&self.parsed_event)
848         index = 0
849         self._parse_next_event()
850         while self.parsed_event.type != YAML_SEQUENCE_END_EVENT:
851             value.append(self._compose_node(node, index))
852             index = index+1
853             self._parse_next_event()
854         node.end_mark = Mark(self.stream_name,
855                 self.parsed_event.end_mark.index,
856                 self.parsed_event.end_mark.line,
857                 self.parsed_event.end_mark.column,
858                 None, None)
859         yaml_event_delete(&self.parsed_event)
860         return node
861
862     cdef _compose_mapping_node(self, object anchor):
863         start_mark = Mark(self.stream_name,
864                 self.parsed_event.start_mark.index,
865                 self.parsed_event.start_mark.line,
866                 self.parsed_event.start_mark.column,
867                 None, None)
868         implicit = False
869         if self.parsed_event.data.mapping_start.implicit == 1:
870             implicit = True
871         if self.parsed_event.data.mapping_start.tag == NULL    \
872                 or (self.parsed_event.data.mapping_start.tag[0] == c'!'
873                         and self.parsed_event.data.mapping_start.tag[1] == c'\0'):
874             tag = self.resolve(MappingNode, None, implicit)
875         else:
876             tag = PyUnicode_FromString(self.parsed_event.data.mapping_start.tag)
877         flow_style = None
878         if self.parsed_event.data.mapping_start.style == YAML_FLOW_MAPPING_STYLE:
879             flow_style = True
880         elif self.parsed_event.data.mapping_start.style == YAML_BLOCK_MAPPING_STYLE:
881             flow_style = False
882         value = []
883         node = MappingNode(tag, value, start_mark, None, flow_style)
884         if anchor is not None:
885             self.anchors[anchor] = node
886         yaml_event_delete(&self.parsed_event)
887         self._parse_next_event()
888         while self.parsed_event.type != YAML_MAPPING_END_EVENT:
889             item_key = self._compose_node(node, None)
890             item_value = self._compose_node(node, item_key)
891             value.append((item_key, item_value))
892             self._parse_next_event()
893         node.end_mark = Mark(self.stream_name,
894                 self.parsed_event.end_mark.index,
895                 self.parsed_event.end_mark.line,
896                 self.parsed_event.end_mark.column,
897                 None, None)
898         yaml_event_delete(&self.parsed_event)
899         return node
900
901     cdef int _parse_next_event(self) except 0:
902         if self.parsed_event.type == YAML_NO_EVENT:
903             if yaml_parser_parse(&self.parser, &self.parsed_event) == 0:
904                 error = self._parser_error()
905                 raise error
906         return 1
907
908 cdef int input_handler(void *data, char *buffer, int size, int *read) except 0:
909     cdef CParser parser
910     parser = <CParser>data
911     if parser.stream_cache is None:
912         value = parser.stream.read(size)
913         if PyUnicode_CheckExact(value) != 0:
914             value = PyUnicode_AsUTF8String(value)
915             parser.unicode_source = 1
916         if PyString_CheckExact(value) == 0:
917             if PY_MAJOR_VERSION < 3:
918                 raise TypeError("a string value is expected")
919             else:
920                 raise TypeError(u"a string value is expected")
921         parser.stream_cache = value
922         parser.stream_cache_pos = 0
923         parser.stream_cache_len = PyString_GET_SIZE(value)
924     if (parser.stream_cache_len - parser.stream_cache_pos) < size:
925         size = parser.stream_cache_len - parser.stream_cache_pos
926     if size > 0:
927         memcpy(buffer, PyString_AS_STRING(parser.stream_cache)
928                             + parser.stream_cache_pos, size)
929     read[0] = size
930     parser.stream_cache_pos += size
931     if parser.stream_cache_pos == parser.stream_cache_len:
932         parser.stream_cache = None
933     return 1
934
935 cdef class CEmitter:
936
937     cdef yaml_emitter_t emitter
938
939     cdef object stream
940
941     cdef int document_start_implicit
942     cdef int document_end_implicit
943     cdef object use_version
944     cdef object use_tags
945
946     cdef object serialized_nodes
947     cdef object anchors
948     cdef int last_alias_id
949     cdef int closed
950     cdef int dump_unicode
951     cdef object use_encoding
952
953     def __init__(self, stream, canonical=None, indent=None, width=None,
954             allow_unicode=None, line_break=None, encoding=None,
955             explicit_start=None, explicit_end=None, version=None, tags=None):
956         if yaml_emitter_initialize(&self.emitter) == 0:
957             raise MemoryError
958         self.stream = stream
959         self.dump_unicode = 0
960         if PY_MAJOR_VERSION < 3:
961             if getattr3(stream, 'encoding', None):
962                 self.dump_unicode = 1
963         else:
964             if hasattr(stream, u'encoding'):
965                 self.dump_unicode = 1
966         self.use_encoding = encoding
967         yaml_emitter_set_output(&self.emitter, output_handler, <void *>self)    
968         if canonical:
969             yaml_emitter_set_canonical(&self.emitter, 1)
970         if indent is not None:
971             yaml_emitter_set_indent(&self.emitter, indent)
972         if width is not None:
973             yaml_emitter_set_width(&self.emitter, width)
974         if allow_unicode:
975             yaml_emitter_set_unicode(&self.emitter, 1)
976         if line_break is not None:
977             if line_break == '\r':
978                 yaml_emitter_set_break(&self.emitter, YAML_CR_BREAK)
979             elif line_break == '\n':
980                 yaml_emitter_set_break(&self.emitter, YAML_LN_BREAK)
981             elif line_break == '\r\n':
982                 yaml_emitter_set_break(&self.emitter, YAML_CRLN_BREAK)
983         self.document_start_implicit = 1
984         if explicit_start:
985             self.document_start_implicit = 0
986         self.document_end_implicit = 1
987         if explicit_end:
988             self.document_end_implicit = 0
989         self.use_version = version
990         self.use_tags = tags
991         self.serialized_nodes = {}
992         self.anchors = {}
993         self.last_alias_id = 0
994         self.closed = -1
995
996     def __dealloc__(self):
997         yaml_emitter_delete(&self.emitter)
998
999     def dispose(self):
1000         pass
1001
1002     cdef object _emitter_error(self):
1003         if self.emitter.error == YAML_MEMORY_ERROR:
1004             return MemoryError
1005         elif self.emitter.error == YAML_EMITTER_ERROR:
1006             if PY_MAJOR_VERSION < 3:
1007                 problem = self.emitter.problem
1008             else:
1009                 problem = PyUnicode_FromString(self.emitter.problem)
1010             return EmitterError(problem)
1011         if PY_MAJOR_VERSION < 3:
1012             raise ValueError("no emitter error")
1013         else:
1014             raise ValueError(u"no emitter error")
1015
1016     cdef int _object_to_event(self, object event_object, yaml_event_t *event) except 0:
1017         cdef yaml_encoding_t encoding
1018         cdef yaml_version_directive_t version_directive_value
1019         cdef yaml_version_directive_t *version_directive
1020         cdef yaml_tag_directive_t tag_directives_value[128]
1021         cdef yaml_tag_directive_t *tag_directives_start
1022         cdef yaml_tag_directive_t *tag_directives_end
1023         cdef int implicit
1024         cdef int plain_implicit
1025         cdef int quoted_implicit
1026         cdef char *anchor
1027         cdef char *tag
1028         cdef char *value
1029         cdef int length
1030         cdef yaml_scalar_style_t scalar_style
1031         cdef yaml_sequence_style_t sequence_style
1032         cdef yaml_mapping_style_t mapping_style
1033         event_class = event_object.__class__
1034         if event_class is StreamStartEvent:
1035             encoding = YAML_UTF8_ENCODING
1036             if event_object.encoding == u'utf-16-le' or event_object.encoding == 'utf-16-le':
1037                 encoding = YAML_UTF16LE_ENCODING
1038             elif event_object.encoding == u'utf-16-be' or event_object.encoding == 'utf-16-be':
1039                 encoding = YAML_UTF16BE_ENCODING
1040             if event_object.encoding is None:
1041                 self.dump_unicode = 1
1042             if self.dump_unicode == 1:
1043                 encoding = YAML_UTF8_ENCODING
1044             yaml_stream_start_event_initialize(event, encoding)
1045         elif event_class is StreamEndEvent:
1046             yaml_stream_end_event_initialize(event)
1047         elif event_class is DocumentStartEvent:
1048             version_directive = NULL
1049             if event_object.version:
1050                 version_directive_value.major = event_object.version[0]
1051                 version_directive_value.minor = event_object.version[1]
1052                 version_directive = &version_directive_value
1053             tag_directives_start = NULL
1054             tag_directives_end = NULL
1055             if event_object.tags:
1056                 if len(event_object.tags) > 128:
1057                     if PY_MAJOR_VERSION < 3:
1058                         raise ValueError("too many tags")
1059                     else:
1060                         raise ValueError(u"too many tags")
1061                 tag_directives_start = tag_directives_value
1062                 tag_directives_end = tag_directives_value
1063                 cache = []
1064                 for handle in event_object.tags:
1065                     prefix = event_object.tags[handle]
1066                     if PyUnicode_CheckExact(handle):
1067                         handle = PyUnicode_AsUTF8String(handle)
1068                         cache.append(handle)
1069                     if not PyString_CheckExact(handle):
1070                         if PY_MAJOR_VERSION < 3:
1071                             raise TypeError("tag handle must be a string")
1072                         else:
1073                             raise TypeError(u"tag handle must be a string")
1074                     tag_directives_end.handle = PyString_AS_STRING(handle)
1075                     if PyUnicode_CheckExact(prefix):
1076                         prefix = PyUnicode_AsUTF8String(prefix)
1077                         cache.append(prefix)
1078                     if not PyString_CheckExact(prefix):
1079                         if PY_MAJOR_VERSION < 3:
1080                             raise TypeError("tag prefix must be a string")
1081                         else:
1082                             raise TypeError(u"tag prefix must be a string")
1083                     tag_directives_end.prefix = PyString_AS_STRING(prefix)
1084                     tag_directives_end = tag_directives_end+1
1085             implicit = 1
1086             if event_object.explicit:
1087                 implicit = 0
1088             if yaml_document_start_event_initialize(event, version_directive,
1089                     tag_directives_start, tag_directives_end, implicit) == 0:
1090                 raise MemoryError
1091         elif event_class is DocumentEndEvent:
1092             implicit = 1
1093             if event_object.explicit:
1094                 implicit = 0
1095             yaml_document_end_event_initialize(event, implicit)
1096         elif event_class is AliasEvent:
1097             anchor = NULL
1098             anchor_object = event_object.anchor
1099             if PyUnicode_CheckExact(anchor_object):
1100                 anchor_object = PyUnicode_AsUTF8String(anchor_object)
1101             if not PyString_CheckExact(anchor_object):
1102                 if PY_MAJOR_VERSION < 3:
1103                     raise TypeError("anchor must be a string")
1104                 else:
1105                     raise TypeError(u"anchor must be a string")
1106             anchor = PyString_AS_STRING(anchor_object)
1107             if yaml_alias_event_initialize(event, anchor) == 0:
1108                 raise MemoryError
1109         elif event_class is ScalarEvent:
1110             anchor = NULL
1111             anchor_object = event_object.anchor
1112             if anchor_object is not None:
1113                 if PyUnicode_CheckExact(anchor_object):
1114                     anchor_object = PyUnicode_AsUTF8String(anchor_object)
1115                 if not PyString_CheckExact(anchor_object):
1116                     if PY_MAJOR_VERSION < 3:
1117                         raise TypeError("anchor must be a string")
1118                     else:
1119                         raise TypeError(u"anchor must be a string")
1120                 anchor = PyString_AS_STRING(anchor_object)
1121             tag = NULL
1122             tag_object = event_object.tag
1123             if tag_object is not None:
1124                 if PyUnicode_CheckExact(tag_object):
1125                     tag_object = PyUnicode_AsUTF8String(tag_object)
1126                 if not PyString_CheckExact(tag_object):
1127                     if PY_MAJOR_VERSION < 3:
1128                         raise TypeError("tag must be a string")
1129                     else:
1130                         raise TypeError(u"tag must be a string")
1131                 tag = PyString_AS_STRING(tag_object)
1132             value_object = event_object.value
1133             if PyUnicode_CheckExact(value_object):
1134                 value_object = PyUnicode_AsUTF8String(value_object)
1135             if not PyString_CheckExact(value_object):
1136                 if PY_MAJOR_VERSION < 3:
1137                     raise TypeError("value must be a string")
1138                 else:
1139                     raise TypeError(u"value must be a string")
1140             value = PyString_AS_STRING(value_object)
1141             length = PyString_GET_SIZE(value_object)
1142             plain_implicit = 0
1143             quoted_implicit = 0
1144             if event_object.implicit is not None:
1145                 plain_implicit = event_object.implicit[0]
1146                 quoted_implicit = event_object.implicit[1]
1147             style_object = event_object.style
1148             scalar_style = YAML_PLAIN_SCALAR_STYLE
1149             if style_object == "'" or style_object == u"'":
1150                 scalar_style = YAML_SINGLE_QUOTED_SCALAR_STYLE
1151             elif style_object == "\"" or style_object == u"\"":
1152                 scalar_style = YAML_DOUBLE_QUOTED_SCALAR_STYLE
1153             elif style_object == "|" or style_object == u"|":
1154                 scalar_style = YAML_LITERAL_SCALAR_STYLE
1155             elif style_object == ">" or style_object == u">":
1156                 scalar_style = YAML_FOLDED_SCALAR_STYLE
1157             if yaml_scalar_event_initialize(event, anchor, tag, value, length,
1158                     plain_implicit, quoted_implicit, scalar_style) == 0:
1159                 raise MemoryError
1160         elif event_class is SequenceStartEvent:
1161             anchor = NULL
1162             anchor_object = event_object.anchor
1163             if anchor_object is not None:
1164                 if PyUnicode_CheckExact(anchor_object):
1165                     anchor_object = PyUnicode_AsUTF8String(anchor_object)
1166                 if not PyString_CheckExact(anchor_object):
1167                     if PY_MAJOR_VERSION < 3:
1168                         raise TypeError("anchor must be a string")
1169                     else:
1170                         raise TypeError(u"anchor must be a string")
1171                 anchor = PyString_AS_STRING(anchor_object)
1172             tag = NULL
1173             tag_object = event_object.tag
1174             if tag_object is not None:
1175                 if PyUnicode_CheckExact(tag_object):
1176                     tag_object = PyUnicode_AsUTF8String(tag_object)
1177                 if not PyString_CheckExact(tag_object):
1178                     if PY_MAJOR_VERSION < 3:
1179                         raise TypeError("tag must be a string")
1180                     else:
1181                         raise TypeError(u"tag must be a string")
1182                 tag = PyString_AS_STRING(tag_object)
1183             implicit = 0
1184             if event_object.implicit:
1185                 implicit = 1
1186             sequence_style = YAML_BLOCK_SEQUENCE_STYLE
1187             if event_object.flow_style:
1188                 sequence_style = YAML_FLOW_SEQUENCE_STYLE
1189             if yaml_sequence_start_event_initialize(event, anchor, tag,
1190                     implicit, sequence_style) == 0:
1191                 raise MemoryError
1192         elif event_class is MappingStartEvent:
1193             anchor = NULL
1194             anchor_object = event_object.anchor
1195             if anchor_object is not None:
1196                 if PyUnicode_CheckExact(anchor_object):
1197                     anchor_object = PyUnicode_AsUTF8String(anchor_object)
1198                 if not PyString_CheckExact(anchor_object):
1199                     if PY_MAJOR_VERSION < 3:
1200                         raise TypeError("anchor must be a string")
1201                     else:
1202                         raise TypeError(u"anchor must be a string")
1203                 anchor = PyString_AS_STRING(anchor_object)
1204             tag = NULL
1205             tag_object = event_object.tag
1206             if tag_object is not None:
1207                 if PyUnicode_CheckExact(tag_object):
1208                     tag_object = PyUnicode_AsUTF8String(tag_object)
1209                 if not PyString_CheckExact(tag_object):
1210                     if PY_MAJOR_VERSION < 3:
1211                         raise TypeError("tag must be a string")
1212                     else:
1213                         raise TypeError(u"tag must be a string")
1214                 tag = PyString_AS_STRING(tag_object)
1215             implicit = 0
1216             if event_object.implicit:
1217                 implicit = 1
1218             mapping_style = YAML_BLOCK_MAPPING_STYLE
1219             if event_object.flow_style:
1220                 mapping_style = YAML_FLOW_MAPPING_STYLE
1221             if yaml_mapping_start_event_initialize(event, anchor, tag,
1222                     implicit, mapping_style) == 0:
1223                 raise MemoryError
1224         elif event_class is SequenceEndEvent:
1225             yaml_sequence_end_event_initialize(event)
1226         elif event_class is MappingEndEvent:
1227             yaml_mapping_end_event_initialize(event)
1228         else:
1229             if PY_MAJOR_VERSION < 3:
1230                 raise TypeError("invalid event %s" % event_object)
1231             else:
1232                 raise TypeError(u"invalid event %s" % event_object)
1233         return 1
1234
1235     def emit(self, event_object):
1236         cdef yaml_event_t event
1237         self._object_to_event(event_object, &event)
1238         if yaml_emitter_emit(&self.emitter, &event) == 0:
1239             error = self._emitter_error()
1240             raise error
1241
1242     def open(self):
1243         cdef yaml_event_t event
1244         cdef yaml_encoding_t encoding
1245         if self.closed == -1:
1246             if self.use_encoding == u'utf-16-le' or self.use_encoding == 'utf-16-le':
1247                 encoding = YAML_UTF16LE_ENCODING
1248             elif self.use_encoding == u'utf-16-be' or self.use_encoding == 'utf-16-be':
1249                 encoding = YAML_UTF16BE_ENCODING
1250             else:
1251                 encoding = YAML_UTF8_ENCODING
1252             if self.use_encoding is None:
1253                 self.dump_unicode = 1
1254             if self.dump_unicode == 1:
1255                 encoding = YAML_UTF8_ENCODING
1256             yaml_stream_start_event_initialize(&event, encoding)
1257             if yaml_emitter_emit(&self.emitter, &event) == 0:
1258                 error = self._emitter_error()
1259                 raise error
1260             self.closed = 0
1261         elif self.closed == 1:
1262             if PY_MAJOR_VERSION < 3:
1263                 raise SerializerError("serializer is closed")
1264             else:
1265                 raise SerializerError(u"serializer is closed")
1266         else:
1267             if PY_MAJOR_VERSION < 3:
1268                 raise SerializerError("serializer is already opened")
1269             else:
1270                 raise SerializerError(u"serializer is already opened")
1271
1272     def close(self):
1273         cdef yaml_event_t event
1274         if self.closed == -1:
1275             if PY_MAJOR_VERSION < 3:
1276                 raise SerializerError("serializer is not opened")
1277             else:
1278                 raise SerializerError(u"serializer is not opened")
1279         elif self.closed == 0:
1280             yaml_stream_end_event_initialize(&event)
1281             if yaml_emitter_emit(&self.emitter, &event) == 0:
1282                 error = self._emitter_error()
1283                 raise error
1284             self.closed = 1
1285
1286     def serialize(self, node):
1287         cdef yaml_event_t event
1288         cdef yaml_version_directive_t version_directive_value
1289         cdef yaml_version_directive_t *version_directive
1290         cdef yaml_tag_directive_t tag_directives_value[128]
1291         cdef yaml_tag_directive_t *tag_directives_start
1292         cdef yaml_tag_directive_t *tag_directives_end
1293         if self.closed == -1:
1294             if PY_MAJOR_VERSION < 3:
1295                 raise SerializerError("serializer is not opened")
1296             else:
1297                 raise SerializerError(u"serializer is not opened")
1298         elif self.closed == 1:
1299             if PY_MAJOR_VERSION < 3:
1300                 raise SerializerError("serializer is closed")
1301             else:
1302                 raise SerializerError(u"serializer is closed")
1303         cache = []
1304         version_directive = NULL
1305         if self.use_version:
1306             version_directive_value.major = self.use_version[0]
1307             version_directive_value.minor = self.use_version[1]
1308             version_directive = &version_directive_value
1309         tag_directives_start = NULL
1310         tag_directives_end = NULL
1311         if self.use_tags:
1312             if len(self.use_tags) > 128:
1313                 if PY_MAJOR_VERSION < 3:
1314                     raise ValueError("too many tags")
1315                 else:
1316                     raise ValueError(u"too many tags")
1317             tag_directives_start = tag_directives_value
1318             tag_directives_end = tag_directives_value
1319             for handle in self.use_tags:
1320                 prefix = self.use_tags[handle]
1321                 if PyUnicode_CheckExact(handle):
1322                     handle = PyUnicode_AsUTF8String(handle)
1323                     cache.append(handle)
1324                 if not PyString_CheckExact(handle):
1325                     if PY_MAJOR_VERSION < 3:
1326                         raise TypeError("tag handle must be a string")
1327                     else:
1328                         raise TypeError(u"tag handle must be a string")
1329                 tag_directives_end.handle = PyString_AS_STRING(handle)
1330                 if PyUnicode_CheckExact(prefix):
1331                     prefix = PyUnicode_AsUTF8String(prefix)
1332                     cache.append(prefix)
1333                 if not PyString_CheckExact(prefix):
1334                     if PY_MAJOR_VERSION < 3:
1335                         raise TypeError("tag prefix must be a string")
1336                     else:
1337                         raise TypeError(u"tag prefix must be a string")
1338                 tag_directives_end.prefix = PyString_AS_STRING(prefix)
1339                 tag_directives_end = tag_directives_end+1
1340         if yaml_document_start_event_initialize(&event, version_directive,
1341                 tag_directives_start, tag_directives_end,
1342                 self.document_start_implicit) == 0:
1343             raise MemoryError
1344         if yaml_emitter_emit(&self.emitter, &event) == 0:
1345             error = self._emitter_error()
1346             raise error
1347         self._anchor_node(node)
1348         self._serialize_node(node, None, None)
1349         yaml_document_end_event_initialize(&event, self.document_end_implicit)
1350         if yaml_emitter_emit(&self.emitter, &event) == 0:
1351             error = self._emitter_error()
1352             raise error
1353         self.serialized_nodes = {}
1354         self.anchors = {}
1355         self.last_alias_id = 0
1356
1357     cdef int _anchor_node(self, object node) except 0:
1358         if node in self.anchors:
1359             if self.anchors[node] is None:
1360                 self.last_alias_id = self.last_alias_id+1
1361                 self.anchors[node] = u"id%03d" % self.last_alias_id
1362         else:
1363             self.anchors[node] = None
1364             node_class = node.__class__
1365             if node_class is SequenceNode:
1366                 for item in node.value:
1367                     self._anchor_node(item)
1368             elif node_class is MappingNode:
1369                 for key, value in node.value:
1370                     self._anchor_node(key)
1371                     self._anchor_node(value)
1372         return 1
1373
1374     cdef int _serialize_node(self, object node, object parent, object index) except 0:
1375         cdef yaml_event_t event
1376         cdef int implicit
1377         cdef int plain_implicit
1378         cdef int quoted_implicit
1379         cdef char *anchor
1380         cdef char *tag
1381         cdef char *value
1382         cdef int length
1383         cdef int item_index
1384         cdef yaml_scalar_style_t scalar_style
1385         cdef yaml_sequence_style_t sequence_style
1386         cdef yaml_mapping_style_t mapping_style
1387         anchor_object = self.anchors[node]
1388         anchor = NULL
1389         if anchor_object is not None:
1390             if PyUnicode_CheckExact(anchor_object):
1391                 anchor_object = PyUnicode_AsUTF8String(anchor_object)
1392             if not PyString_CheckExact(anchor_object):
1393                 if PY_MAJOR_VERSION < 3:
1394                     raise TypeError("anchor must be a string")
1395                 else:
1396                     raise TypeError(u"anchor must be a string")
1397             anchor = PyString_AS_STRING(anchor_object)
1398         if node in self.serialized_nodes:
1399             if yaml_alias_event_initialize(&event, anchor) == 0:
1400                 raise MemoryError
1401             if yaml_emitter_emit(&self.emitter, &event) == 0:
1402                 error = self._emitter_error()
1403                 raise error
1404         else:
1405             node_class = node.__class__
1406             self.serialized_nodes[node] = True
1407             self.descend_resolver(parent, index)
1408             if node_class is ScalarNode:
1409                 plain_implicit = 0
1410                 quoted_implicit = 0
1411                 tag_object = node.tag
1412                 if self.resolve(ScalarNode, node.value, (True, False)) == tag_object:
1413                     plain_implicit = 1
1414                 if self.resolve(ScalarNode, node.value, (False, True)) == tag_object:
1415                     quoted_implicit = 1
1416                 tag = NULL
1417                 if tag_object is not None:
1418                     if PyUnicode_CheckExact(tag_object):
1419                         tag_object = PyUnicode_AsUTF8String(tag_object)
1420                     if not PyString_CheckExact(tag_object):
1421                         if PY_MAJOR_VERSION < 3:
1422                             raise TypeError("tag must be a string")
1423                         else:
1424                             raise TypeError(u"tag must be a string")
1425                     tag = PyString_AS_STRING(tag_object)
1426                 value_object = node.value
1427                 if PyUnicode_CheckExact(value_object):
1428                     value_object = PyUnicode_AsUTF8String(value_object)
1429                 if not PyString_CheckExact(value_object):
1430                     if PY_MAJOR_VERSION < 3:
1431                         raise TypeError("value must be a string")
1432                     else:
1433                         raise TypeError(u"value must be a string")
1434                 value = PyString_AS_STRING(value_object)
1435                 length = PyString_GET_SIZE(value_object)
1436                 style_object = node.style
1437                 scalar_style = YAML_PLAIN_SCALAR_STYLE
1438                 if style_object == "'" or style_object == u"'":
1439                     scalar_style = YAML_SINGLE_QUOTED_SCALAR_STYLE
1440                 elif style_object == "\"" or style_object == u"\"":
1441                     scalar_style = YAML_DOUBLE_QUOTED_SCALAR_STYLE
1442                 elif style_object == "|" or style_object == u"|":
1443                     scalar_style = YAML_LITERAL_SCALAR_STYLE
1444                 elif style_object == ">" or style_object == u">":
1445                     scalar_style = YAML_FOLDED_SCALAR_STYLE
1446                 if yaml_scalar_event_initialize(&event, anchor, tag, value, length,
1447                         plain_implicit, quoted_implicit, scalar_style) == 0:
1448                     raise MemoryError
1449                 if yaml_emitter_emit(&self.emitter, &event) == 0:
1450                     error = self._emitter_error()
1451                     raise error
1452             elif node_class is SequenceNode:
1453                 implicit = 0
1454                 tag_object = node.tag
1455                 if self.resolve(SequenceNode, node.value, True) == tag_object:
1456                     implicit = 1
1457                 tag = NULL
1458                 if tag_object is not None:
1459                     if PyUnicode_CheckExact(tag_object):
1460                         tag_object = PyUnicode_AsUTF8String(tag_object)
1461                     if not PyString_CheckExact(tag_object):
1462                         if PY_MAJOR_VERSION < 3:
1463                             raise TypeError("tag must be a string")
1464                         else:
1465                             raise TypeError(u"tag must be a string")
1466                     tag = PyString_AS_STRING(tag_object)
1467                 sequence_style = YAML_BLOCK_SEQUENCE_STYLE
1468                 if node.flow_style:
1469                     sequence_style = YAML_FLOW_SEQUENCE_STYLE
1470                 if yaml_sequence_start_event_initialize(&event, anchor, tag,
1471                         implicit, sequence_style) == 0:
1472                     raise MemoryError
1473                 if yaml_emitter_emit(&self.emitter, &event) == 0:
1474                     error = self._emitter_error()
1475                     raise error
1476                 item_index = 0
1477                 for item in node.value:
1478                     self._serialize_node(item, node, item_index)
1479                     item_index = item_index+1
1480                 yaml_sequence_end_event_initialize(&event)
1481                 if yaml_emitter_emit(&self.emitter, &event) == 0:
1482                     error = self._emitter_error()
1483                     raise error
1484             elif node_class is MappingNode:
1485                 implicit = 0
1486                 tag_object = node.tag
1487                 if self.resolve(MappingNode, node.value, True) == tag_object:
1488                     implicit = 1
1489                 tag = NULL
1490                 if tag_object is not None:
1491                     if PyUnicode_CheckExact(tag_object):
1492                         tag_object = PyUnicode_AsUTF8String(tag_object)
1493                     if not PyString_CheckExact(tag_object):
1494                         if PY_MAJOR_VERSION < 3:
1495                             raise TypeError("tag must be a string")
1496                         else:
1497                             raise TypeError(u"tag must be a string")
1498                     tag = PyString_AS_STRING(tag_object)
1499                 mapping_style = YAML_BLOCK_MAPPING_STYLE
1500                 if node.flow_style:
1501                     mapping_style = YAML_FLOW_MAPPING_STYLE
1502                 if yaml_mapping_start_event_initialize(&event, anchor, tag,
1503                         implicit, mapping_style) == 0:
1504                     raise MemoryError
1505                 if yaml_emitter_emit(&self.emitter, &event) == 0:
1506                     error = self._emitter_error()
1507                     raise error
1508                 for item_key, item_value in node.value:
1509                     self._serialize_node(item_key, node, None)
1510                     self._serialize_node(item_value, node, item_key)
1511                 yaml_mapping_end_event_initialize(&event)
1512                 if yaml_emitter_emit(&self.emitter, &event) == 0:
1513                     error = self._emitter_error()
1514                     raise error
1515             self.ascend_resolver()
1516         return 1
1517
1518 cdef int output_handler(void *data, char *buffer, int size) except 0:
1519     cdef CEmitter emitter
1520     emitter = <CEmitter>data
1521     if emitter.dump_unicode == 0:
1522         value = PyString_FromStringAndSize(buffer, size)
1523     else:
1524         value = PyUnicode_DecodeUTF8(buffer, size, 'strict')
1525     emitter.stream.write(value)
1526     return 1
1527