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