1
2import yaml
3
4def 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
12def 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
18YAMLError = yaml.error.YAMLError
19ReaderError = yaml.reader.ReaderError
20ScannerError = yaml.scanner.ScannerError
21ParserError = yaml.parser.ParserError
22ComposerError = yaml.composer.ComposerError
23ConstructorError = yaml.constructor.ConstructorError
24EmitterError = yaml.emitter.EmitterError
25SerializerError = yaml.serializer.SerializerError
26RepresenterError = yaml.representer.RepresenterError
27
28StreamStartToken = yaml.tokens.StreamStartToken
29StreamEndToken = yaml.tokens.StreamEndToken
30DirectiveToken = yaml.tokens.DirectiveToken
31DocumentStartToken = yaml.tokens.DocumentStartToken
32DocumentEndToken = yaml.tokens.DocumentEndToken
33BlockSequenceStartToken = yaml.tokens.BlockSequenceStartToken
34BlockMappingStartToken = yaml.tokens.BlockMappingStartToken
35BlockEndToken = yaml.tokens.BlockEndToken
36FlowSequenceStartToken = yaml.tokens.FlowSequenceStartToken
37FlowMappingStartToken = yaml.tokens.FlowMappingStartToken
38FlowSequenceEndToken = yaml.tokens.FlowSequenceEndToken
39FlowMappingEndToken = yaml.tokens.FlowMappingEndToken
40KeyToken = yaml.tokens.KeyToken
41ValueToken = yaml.tokens.ValueToken
42BlockEntryToken = yaml.tokens.BlockEntryToken
43FlowEntryToken = yaml.tokens.FlowEntryToken
44AliasToken = yaml.tokens.AliasToken
45AnchorToken = yaml.tokens.AnchorToken
46TagToken = yaml.tokens.TagToken
47ScalarToken = yaml.tokens.ScalarToken
48
49StreamStartEvent = yaml.events.StreamStartEvent
50StreamEndEvent = yaml.events.StreamEndEvent
51DocumentStartEvent = yaml.events.DocumentStartEvent
52DocumentEndEvent = yaml.events.DocumentEndEvent
53AliasEvent = yaml.events.AliasEvent
54ScalarEvent = yaml.events.ScalarEvent
55SequenceStartEvent = yaml.events.SequenceStartEvent
56SequenceEndEvent = yaml.events.SequenceEndEvent
57MappingStartEvent = yaml.events.MappingStartEvent
58MappingEndEvent = yaml.events.MappingEndEvent
59
60ScalarNode = yaml.nodes.ScalarNode
61SequenceNode = yaml.nodes.SequenceNode
62MappingNode = yaml.nodes.MappingNode
63
64cdef 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
247cdef 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
908cdef 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
935cdef 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
1518cdef 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
1528