source: pyyaml/trunk/ext/_yaml.pyx @ 348

Revision 348, 62.7 KB checked in by xi, 6 years ago (diff)

Fixed the Pyrex implementation of Mark class.

Line 
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    cdef object _parser_error(self):
315        if self.parser.error == YAML_MEMORY_ERROR:
316            return MemoryError
317        elif self.parser.error == YAML_READER_ERROR:
318            if PY_MAJOR_VERSION < 3:
319                return ReaderError(self.stream_name, self.parser.problem_offset,
320                        self.parser.problem_value, '?', self.parser.problem)
321            else:
322                return ReaderError(self.stream_name, self.parser.problem_offset,
323                        self.parser.problem_value, u'?', PyUnicode_FromString(self.parser.problem))
324        elif self.parser.error == YAML_SCANNER_ERROR    \
325                or self.parser.error == YAML_PARSER_ERROR:
326            context_mark = None
327            problem_mark = None
328            if self.parser.context != NULL:
329                context_mark = Mark(self.stream_name,
330                        self.parser.context_mark.index,
331                        self.parser.context_mark.line,
332                        self.parser.context_mark.column, None, None)
333            if self.parser.problem != NULL:
334                problem_mark = Mark(self.stream_name,
335                        self.parser.problem_mark.index,
336                        self.parser.problem_mark.line,
337                        self.parser.problem_mark.column, None, None)
338            context = None
339            if self.parser.context != NULL:
340                if PY_MAJOR_VERSION < 3:
341                    context = self.parser.context
342                else:
343                    context = PyUnicode_FromString(self.parser.context)
344            if PY_MAJOR_VERSION < 3:
345                problem = self.parser.problem
346            else:
347                problem = PyUnicode_FromString(self.parser.problem)
348            if self.parser.error == YAML_SCANNER_ERROR:
349                return ScannerError(context, context_mark, problem, problem_mark)
350            else:
351                return ParserError(context, context_mark, problem, problem_mark)
352        if PY_MAJOR_VERSION < 3:
353            raise ValueError("no parser error")
354        else:
355            raise ValueError(u"no parser error")
356
357    def raw_scan(self):
358        cdef yaml_token_t token
359        cdef int done
360        cdef int count
361        count = 0
362        done = 0
363        while done == 0:
364            if yaml_parser_scan(&self.parser, &token) == 0:
365                error = self._parser_error()
366                raise error
367            if token.type == YAML_NO_TOKEN:
368                done = 1
369            else:
370                count = count+1
371            yaml_token_delete(&token)
372        return count
373
374    cdef object _scan(self):
375        cdef yaml_token_t token
376        if yaml_parser_scan(&self.parser, &token) == 0:
377            error = self._parser_error()
378            raise error
379        token_object = self._token_to_object(&token)
380        yaml_token_delete(&token)
381        return token_object
382
383    cdef object _token_to_object(self, yaml_token_t *token):
384        start_mark = Mark(self.stream_name,
385                token.start_mark.index,
386                token.start_mark.line,
387                token.start_mark.column,
388                None, None)
389        end_mark = Mark(self.stream_name,
390                token.end_mark.index,
391                token.end_mark.line,
392                token.end_mark.column,
393                None, None)
394        if token.type == YAML_NO_TOKEN:
395            return None
396        elif token.type == YAML_STREAM_START_TOKEN:
397            encoding = None
398            if token.data.stream_start.encoding == YAML_UTF8_ENCODING:
399                if self.unicode_source == 0:
400                    encoding = u"utf-8"
401            elif token.data.stream_start.encoding == YAML_UTF16LE_ENCODING:
402                encoding = u"utf-16-le"
403            elif token.data.stream_start.encoding == YAML_UTF16BE_ENCODING:
404                encoding = u"utf-16-be"
405            return StreamStartToken(start_mark, end_mark, encoding)
406        elif token.type == YAML_STREAM_END_TOKEN:
407            return StreamEndToken(start_mark, end_mark)
408        elif token.type == YAML_VERSION_DIRECTIVE_TOKEN:
409            return DirectiveToken(u"YAML",
410                    (token.data.version_directive.major,
411                        token.data.version_directive.minor),
412                    start_mark, end_mark)
413        elif token.type == YAML_TAG_DIRECTIVE_TOKEN:
414            handle = PyUnicode_FromString(token.data.tag_directive.handle)
415            prefix = PyUnicode_FromString(token.data.tag_directive.prefix)
416            return DirectiveToken(u"TAG", (handle, prefix),
417                    start_mark, end_mark)
418        elif token.type == YAML_DOCUMENT_START_TOKEN:
419            return DocumentStartToken(start_mark, end_mark)
420        elif token.type == YAML_DOCUMENT_END_TOKEN:
421            return DocumentEndToken(start_mark, end_mark)
422        elif token.type == YAML_BLOCK_SEQUENCE_START_TOKEN:
423            return BlockSequenceStartToken(start_mark, end_mark)
424        elif token.type == YAML_BLOCK_MAPPING_START_TOKEN:
425            return BlockMappingStartToken(start_mark, end_mark)
426        elif token.type == YAML_BLOCK_END_TOKEN:
427            return BlockEndToken(start_mark, end_mark)
428        elif token.type == YAML_FLOW_SEQUENCE_START_TOKEN:
429            return FlowSequenceStartToken(start_mark, end_mark)
430        elif token.type == YAML_FLOW_SEQUENCE_END_TOKEN:
431            return FlowSequenceEndToken(start_mark, end_mark)
432        elif token.type == YAML_FLOW_MAPPING_START_TOKEN:
433            return FlowMappingStartToken(start_mark, end_mark)
434        elif token.type == YAML_FLOW_MAPPING_END_TOKEN:
435            return FlowMappingEndToken(start_mark, end_mark)
436        elif token.type == YAML_BLOCK_ENTRY_TOKEN:
437            return BlockEntryToken(start_mark, end_mark)
438        elif token.type == YAML_FLOW_ENTRY_TOKEN:
439            return FlowEntryToken(start_mark, end_mark)
440        elif token.type == YAML_KEY_TOKEN:
441            return KeyToken(start_mark, end_mark)
442        elif token.type == YAML_VALUE_TOKEN:
443            return ValueToken(start_mark, end_mark)
444        elif token.type == YAML_ALIAS_TOKEN:
445            value = PyUnicode_FromString(token.data.alias.value)
446            return AliasToken(value, start_mark, end_mark)
447        elif token.type == YAML_ANCHOR_TOKEN:
448            value = PyUnicode_FromString(token.data.anchor.value)
449            return AnchorToken(value, start_mark, end_mark)
450        elif token.type == YAML_TAG_TOKEN:
451            handle = PyUnicode_FromString(token.data.tag.handle)
452            suffix = PyUnicode_FromString(token.data.tag.suffix)
453            if not handle:
454                handle = None
455            return TagToken((handle, suffix), start_mark, end_mark)
456        elif token.type == YAML_SCALAR_TOKEN:
457            value = PyUnicode_DecodeUTF8(token.data.scalar.value,
458                    token.data.scalar.length, 'strict')
459            plain = False
460            style = None
461            if token.data.scalar.style == YAML_PLAIN_SCALAR_STYLE:
462                plain = True
463                style = u''
464            elif token.data.scalar.style == YAML_SINGLE_QUOTED_SCALAR_STYLE:
465                style = u'\''
466            elif token.data.scalar.style == YAML_DOUBLE_QUOTED_SCALAR_STYLE:
467                style = u'"'
468            elif token.data.scalar.style == YAML_LITERAL_SCALAR_STYLE:
469                style = u'|'
470            elif token.data.scalar.style == YAML_FOLDED_SCALAR_STYLE:
471                style = u'>'
472            return ScalarToken(value, plain,
473                    start_mark, end_mark, style)
474        else:
475            if PY_MAJOR_VERSION < 3:
476                raise ValueError("unknown token type")
477            else:
478                raise ValueError(u"unknown token type")
479
480    def get_token(self):
481        if self.current_token is not None:
482            value = self.current_token
483            self.current_token = None
484        else:
485            value = self._scan()
486        return value
487
488    def peek_token(self):
489        if self.current_token is None:
490            self.current_token = self._scan()
491        return self.current_token
492
493    def check_token(self, *choices):
494        if self.current_token is None:
495            self.current_token = self._scan()
496        if self.current_token is None:
497            return False
498        if not choices:
499            return True
500        token_class = self.current_token.__class__
501        for choice in choices:
502            if token_class is choice:
503                return True
504        return False
505
506    def raw_parse(self):
507        cdef yaml_event_t event
508        cdef int done
509        cdef int count
510        count = 0
511        done = 0
512        while done == 0:
513            if yaml_parser_parse(&self.parser, &event) == 0:
514                error = self._parser_error()
515                raise error
516            if event.type == YAML_NO_EVENT:
517                done = 1
518            else:
519                count = count+1
520            yaml_event_delete(&event)
521        return count
522
523    cdef object _parse(self):
524        cdef yaml_event_t event
525        if yaml_parser_parse(&self.parser, &event) == 0:
526            error = self._parser_error()
527            raise error
528        event_object = self._event_to_object(&event)
529        yaml_event_delete(&event)
530        return event_object
531
532    cdef object _event_to_object(self, yaml_event_t *event):
533        cdef yaml_tag_directive_t *tag_directive
534        start_mark = Mark(self.stream_name,
535                event.start_mark.index,
536                event.start_mark.line,
537                event.start_mark.column,
538                None, None)
539        end_mark = Mark(self.stream_name,
540                event.end_mark.index,
541                event.end_mark.line,
542                event.end_mark.column,
543                None, None)
544        if event.type == YAML_NO_EVENT:
545            return None
546        elif event.type == YAML_STREAM_START_EVENT:
547            encoding = None
548            if event.data.stream_start.encoding == YAML_UTF8_ENCODING:
549                if self.unicode_source == 0:
550                    encoding = u"utf-8"
551            elif event.data.stream_start.encoding == YAML_UTF16LE_ENCODING:
552                encoding = u"utf-16-le"
553            elif event.data.stream_start.encoding == YAML_UTF16BE_ENCODING:
554                encoding = u"utf-16-be"
555            return StreamStartEvent(start_mark, end_mark, encoding)
556        elif event.type == YAML_STREAM_END_EVENT:
557            return StreamEndEvent(start_mark, end_mark)
558        elif event.type == YAML_DOCUMENT_START_EVENT:
559            explicit = False
560            if event.data.document_start.implicit == 0:
561                explicit = True
562            version = None
563            if event.data.document_start.version_directive != NULL:
564                version = (event.data.document_start.version_directive.major,
565                        event.data.document_start.version_directive.minor)
566            tags = None
567            if event.data.document_start.tag_directives.start != NULL:
568                tags = {}
569                tag_directive = event.data.document_start.tag_directives.start
570                while tag_directive != event.data.document_start.tag_directives.end:
571                    handle = PyUnicode_FromString(tag_directive.handle)
572                    prefix = PyUnicode_FromString(tag_directive.prefix)
573                    tags[handle] = prefix
574                    tag_directive = tag_directive+1
575            return DocumentStartEvent(start_mark, end_mark,
576                    explicit, version, tags)
577        elif event.type == YAML_DOCUMENT_END_EVENT:
578            explicit = False
579            if event.data.document_end.implicit == 0:
580                explicit = True
581            return DocumentEndEvent(start_mark, end_mark, explicit)
582        elif event.type == YAML_ALIAS_EVENT:
583            anchor = PyUnicode_FromString(event.data.alias.anchor)
584            return AliasEvent(anchor, start_mark, end_mark)
585        elif event.type == YAML_SCALAR_EVENT:
586            anchor = None
587            if event.data.scalar.anchor != NULL:
588                anchor = PyUnicode_FromString(event.data.scalar.anchor)
589            tag = None
590            if event.data.scalar.tag != NULL:
591                tag = PyUnicode_FromString(event.data.scalar.tag)
592            value = PyUnicode_DecodeUTF8(event.data.scalar.value,
593                    event.data.scalar.length, 'strict')
594            plain_implicit = False
595            if event.data.scalar.plain_implicit == 1:
596                plain_implicit = True
597            quoted_implicit = False
598            if event.data.scalar.quoted_implicit == 1:
599                quoted_implicit = True
600            style = None
601            if event.data.scalar.style == YAML_PLAIN_SCALAR_STYLE:
602                style = u''
603            elif event.data.scalar.style == YAML_SINGLE_QUOTED_SCALAR_STYLE:
604                style = u'\''
605            elif event.data.scalar.style == YAML_DOUBLE_QUOTED_SCALAR_STYLE:
606                style = u'"'
607            elif event.data.scalar.style == YAML_LITERAL_SCALAR_STYLE:
608                style = u'|'
609            elif event.data.scalar.style == YAML_FOLDED_SCALAR_STYLE:
610                style = u'>'
611            return ScalarEvent(anchor, tag,
612                    (plain_implicit, quoted_implicit),
613                    value, start_mark, end_mark, style)
614        elif event.type == YAML_SEQUENCE_START_EVENT:
615            anchor = None
616            if event.data.sequence_start.anchor != NULL:
617                anchor = PyUnicode_FromString(event.data.sequence_start.anchor)
618            tag = None
619            if event.data.sequence_start.tag != NULL:
620                tag = PyUnicode_FromString(event.data.sequence_start.tag)
621            implicit = False
622            if event.data.sequence_start.implicit == 1:
623                implicit = True
624            flow_style = None
625            if event.data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE:
626                flow_style = True
627            elif event.data.sequence_start.style == YAML_BLOCK_SEQUENCE_STYLE:
628                flow_style = False
629            return SequenceStartEvent(anchor, tag, implicit,
630                    start_mark, end_mark, flow_style)
631        elif event.type == YAML_MAPPING_START_EVENT:
632            anchor = None
633            if event.data.mapping_start.anchor != NULL:
634                anchor = PyUnicode_FromString(event.data.mapping_start.anchor)
635            tag = None
636            if event.data.mapping_start.tag != NULL:
637                tag = PyUnicode_FromString(event.data.mapping_start.tag)
638            implicit = False
639            if event.data.mapping_start.implicit == 1:
640                implicit = True
641            flow_style = None
642            if event.data.mapping_start.style == YAML_FLOW_MAPPING_STYLE:
643                flow_style = True
644            elif event.data.mapping_start.style == YAML_BLOCK_MAPPING_STYLE:
645                flow_style = False
646            return MappingStartEvent(anchor, tag, implicit,
647                    start_mark, end_mark, flow_style)
648        elif event.type == YAML_SEQUENCE_END_EVENT:
649            return SequenceEndEvent(start_mark, end_mark)
650        elif event.type == YAML_MAPPING_END_EVENT:
651            return MappingEndEvent(start_mark, end_mark)
652        else:
653            if PY_MAJOR_VERSION < 3:
654                raise ValueError("unknown event type")
655            else:
656                raise ValueError(u"unknown event type")
657
658    def get_event(self):
659        if self.current_event is not None:
660            value = self.current_event
661            self.current_event = None
662        else:
663            value = self._parse()
664        return value
665
666    def peek_event(self):
667        if self.current_event is None:
668            self.current_event = self._parse()
669        return self.current_event
670
671    def check_event(self, *choices):
672        if self.current_event is None:
673            self.current_event = self._parse()
674        if self.current_event is None:
675            return False
676        if not choices:
677            return True
678        event_class = self.current_event.__class__
679        for choice in choices:
680            if event_class is choice:
681                return True
682        return False
683
684    def check_node(self):
685        self._parse_next_event()
686        if self.parsed_event.type == YAML_STREAM_START_EVENT:
687            yaml_event_delete(&self.parsed_event)
688            self._parse_next_event()
689        if self.parsed_event.type != YAML_STREAM_END_EVENT:
690            return True
691        return False
692
693    def get_node(self):
694        self._parse_next_event()
695        if self.parsed_event.type != YAML_STREAM_END_EVENT:
696            return self._compose_document()
697
698    def get_single_node(self):
699        self._parse_next_event()
700        yaml_event_delete(&self.parsed_event)
701        self._parse_next_event()
702        document = None
703        if self.parsed_event.type != YAML_STREAM_END_EVENT:
704            document = self._compose_document()
705        self._parse_next_event()
706        if self.parsed_event.type != YAML_STREAM_END_EVENT:
707            mark = Mark(self.stream_name,
708                    self.parsed_event.start_mark.index,
709                    self.parsed_event.start_mark.line,
710                    self.parsed_event.start_mark.column,
711                    None, None)
712            if PY_MAJOR_VERSION < 3:
713                raise ComposerError("expected a single document in the stream",
714                        document.start_mark, "but found another document", mark)
715            else:
716                raise ComposerError(u"expected a single document in the stream",
717                        document.start_mark, u"but found another document", mark)
718        return document
719
720    cdef object _compose_document(self):
721        yaml_event_delete(&self.parsed_event)
722        node = self._compose_node(None, None)
723        self._parse_next_event()
724        yaml_event_delete(&self.parsed_event)
725        self.anchors = {}
726        return node
727
728    cdef object _compose_node(self, object parent, object index):
729        self._parse_next_event()
730        if self.parsed_event.type == YAML_ALIAS_EVENT:
731            anchor = PyUnicode_FromString(self.parsed_event.data.alias.anchor)
732            if anchor not in self.anchors:
733                mark = Mark(self.stream_name,
734                        self.parsed_event.start_mark.index,
735                        self.parsed_event.start_mark.line,
736                        self.parsed_event.start_mark.column,
737                        None, None)
738                if PY_MAJOR_VERSION < 3:
739                    raise ComposerError(None, None, "found undefined alias", mark)
740                else:
741                    raise ComposerError(None, None, u"found undefined alias", mark)
742            yaml_event_delete(&self.parsed_event)
743            return self.anchors[anchor]
744        anchor = None
745        if self.parsed_event.type == YAML_SCALAR_EVENT  \
746                and self.parsed_event.data.scalar.anchor != NULL:
747            anchor = PyUnicode_FromString(self.parsed_event.data.scalar.anchor)
748        elif self.parsed_event.type == YAML_SEQUENCE_START_EVENT    \
749                and self.parsed_event.data.sequence_start.anchor != NULL:
750            anchor = PyUnicode_FromString(self.parsed_event.data.sequence_start.anchor)
751        elif self.parsed_event.type == YAML_MAPPING_START_EVENT    \
752                and self.parsed_event.data.mapping_start.anchor != NULL:
753            anchor = PyUnicode_FromString(self.parsed_event.data.mapping_start.anchor)
754        if anchor is not None:
755            if anchor in self.anchors:
756                mark = Mark(self.stream_name,
757                        self.parsed_event.start_mark.index,
758                        self.parsed_event.start_mark.line,
759                        self.parsed_event.start_mark.column,
760                        None, None)
761                if PY_MAJOR_VERSION < 3:
762                    raise ComposerError("found duplicate anchor; first occurence",
763                            self.anchors[anchor].start_mark, "second occurence", mark)
764                else:
765                    raise ComposerError(u"found duplicate anchor; first occurence",
766                            self.anchors[anchor].start_mark, u"second occurence", mark)
767        self.descend_resolver(parent, index)
768        if self.parsed_event.type == YAML_SCALAR_EVENT:
769            node = self._compose_scalar_node(anchor)
770        elif self.parsed_event.type == YAML_SEQUENCE_START_EVENT:
771            node = self._compose_sequence_node(anchor)
772        elif self.parsed_event.type == YAML_MAPPING_START_EVENT:
773            node = self._compose_mapping_node(anchor)
774        self.ascend_resolver()
775        return node
776
777    cdef _compose_scalar_node(self, object anchor):
778        start_mark = Mark(self.stream_name,
779                self.parsed_event.start_mark.index,
780                self.parsed_event.start_mark.line,
781                self.parsed_event.start_mark.column,
782                None, None)
783        end_mark = Mark(self.stream_name,
784                self.parsed_event.end_mark.index,
785                self.parsed_event.end_mark.line,
786                self.parsed_event.end_mark.column,
787                None, None)
788        value = PyUnicode_DecodeUTF8(self.parsed_event.data.scalar.value,
789                self.parsed_event.data.scalar.length, 'strict')
790        plain_implicit = False
791        if self.parsed_event.data.scalar.plain_implicit == 1:
792            plain_implicit = True
793        quoted_implicit = False
794        if self.parsed_event.data.scalar.quoted_implicit == 1:
795            quoted_implicit = True
796        if self.parsed_event.data.scalar.tag == NULL    \
797                or (self.parsed_event.data.scalar.tag[0] == c'!'
798                        and self.parsed_event.data.scalar.tag[1] == c'\0'):
799            tag = self.resolve(ScalarNode, value, (plain_implicit, quoted_implicit))
800        else:
801            tag = PyUnicode_FromString(self.parsed_event.data.scalar.tag)
802        style = None
803        if self.parsed_event.data.scalar.style == YAML_PLAIN_SCALAR_STYLE:
804            style = u''
805        elif self.parsed_event.data.scalar.style == YAML_SINGLE_QUOTED_SCALAR_STYLE:
806            style = u'\''
807        elif self.parsed_event.data.scalar.style == YAML_DOUBLE_QUOTED_SCALAR_STYLE:
808            style = u'"'
809        elif self.parsed_event.data.scalar.style == YAML_LITERAL_SCALAR_STYLE:
810            style = u'|'
811        elif self.parsed_event.data.scalar.style == YAML_FOLDED_SCALAR_STYLE:
812            style = u'>'
813        node = ScalarNode(tag, value, start_mark, end_mark, style)
814        if anchor is not None:
815            self.anchors[anchor] = node
816        yaml_event_delete(&self.parsed_event)
817        return node
818
819    cdef _compose_sequence_node(self, object anchor):
820        cdef int index
821        start_mark = Mark(self.stream_name,
822                self.parsed_event.start_mark.index,
823                self.parsed_event.start_mark.line,
824                self.parsed_event.start_mark.column,
825                None, None)
826        implicit = False
827        if self.parsed_event.data.sequence_start.implicit == 1:
828            implicit = True
829        if self.parsed_event.data.sequence_start.tag == NULL    \
830                or (self.parsed_event.data.sequence_start.tag[0] == c'!'
831                        and self.parsed_event.data.sequence_start.tag[1] == c'\0'):
832            tag = self.resolve(SequenceNode, None, implicit)
833        else:
834            tag = PyUnicode_FromString(self.parsed_event.data.sequence_start.tag)
835        flow_style = None
836        if self.parsed_event.data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE:
837            flow_style = True
838        elif self.parsed_event.data.sequence_start.style == YAML_BLOCK_SEQUENCE_STYLE:
839            flow_style = False
840        value = []
841        node = SequenceNode(tag, value, start_mark, None, flow_style)
842        if anchor is not None:
843            self.anchors[anchor] = node
844        yaml_event_delete(&self.parsed_event)
845        index = 0
846        self._parse_next_event()
847        while self.parsed_event.type != YAML_SEQUENCE_END_EVENT:
848            value.append(self._compose_node(node, index))
849            index = index+1
850            self._parse_next_event()
851        node.end_mark = Mark(self.stream_name,
852                self.parsed_event.end_mark.index,
853                self.parsed_event.end_mark.line,
854                self.parsed_event.end_mark.column,
855                None, None)
856        yaml_event_delete(&self.parsed_event)
857        return node
858
859    cdef _compose_mapping_node(self, object anchor):
860        start_mark = Mark(self.stream_name,
861                self.parsed_event.start_mark.index,
862                self.parsed_event.start_mark.line,
863                self.parsed_event.start_mark.column,
864                None, None)
865        implicit = False
866        if self.parsed_event.data.mapping_start.implicit == 1:
867            implicit = True
868        if self.parsed_event.data.mapping_start.tag == NULL    \
869                or (self.parsed_event.data.mapping_start.tag[0] == c'!'
870                        and self.parsed_event.data.mapping_start.tag[1] == c'\0'):
871            tag = self.resolve(MappingNode, None, implicit)
872        else:
873            tag = PyUnicode_FromString(self.parsed_event.data.mapping_start.tag)
874        flow_style = None
875        if self.parsed_event.data.mapping_start.style == YAML_FLOW_MAPPING_STYLE:
876            flow_style = True
877        elif self.parsed_event.data.mapping_start.style == YAML_BLOCK_MAPPING_STYLE:
878            flow_style = False
879        value = []
880        node = MappingNode(tag, value, start_mark, None, flow_style)
881        if anchor is not None:
882            self.anchors[anchor] = node
883        yaml_event_delete(&self.parsed_event)
884        self._parse_next_event()
885        while self.parsed_event.type != YAML_MAPPING_END_EVENT:
886            item_key = self._compose_node(node, None)
887            item_value = self._compose_node(node, item_key)
888            value.append((item_key, item_value))
889            self._parse_next_event()
890        node.end_mark = Mark(self.stream_name,
891                self.parsed_event.end_mark.index,
892                self.parsed_event.end_mark.line,
893                self.parsed_event.end_mark.column,
894                None, None)
895        yaml_event_delete(&self.parsed_event)
896        return node
897
898    cdef int _parse_next_event(self) except 0:
899        if self.parsed_event.type == YAML_NO_EVENT:
900            if yaml_parser_parse(&self.parser, &self.parsed_event) == 0:
901                error = self._parser_error()
902                raise error
903        return 1
904
905cdef int input_handler(void *data, char *buffer, int size, int *read) except 0:
906    cdef CParser parser
907    parser = <CParser>data
908    if parser.stream_cache is None:
909        value = parser.stream.read(size)
910        if PyUnicode_CheckExact(value) != 0:
911            value = PyUnicode_AsUTF8String(value)
912            parser.unicode_source = 1
913        if PyString_CheckExact(value) == 0:
914            if PY_MAJOR_VERSION < 3:
915                raise TypeError("a string value is expected")
916            else:
917                raise TypeError(u"a string value is expected")
918        parser.stream_cache = value
919        parser.stream_cache_pos = 0
920        parser.stream_cache_len = PyString_GET_SIZE(value)
921    if (parser.stream_cache_len - parser.stream_cache_pos) < size:
922        size = parser.stream_cache_len - parser.stream_cache_pos
923    if size > 0:
924        memcpy(buffer, PyString_AS_STRING(parser.stream_cache)
925                            + parser.stream_cache_pos, size)
926    read[0] = size
927    parser.stream_cache_pos += size
928    if parser.stream_cache_pos == parser.stream_cache_len:
929        parser.stream_cache = None
930    return 1
931
932cdef class CEmitter:
933
934    cdef yaml_emitter_t emitter
935
936    cdef object stream
937
938    cdef int document_start_implicit
939    cdef int document_end_implicit
940    cdef object use_version
941    cdef object use_tags
942
943    cdef object serialized_nodes
944    cdef object anchors
945    cdef int last_alias_id
946    cdef int closed
947    cdef int dump_unicode
948    cdef object use_encoding
949
950    def __init__(self, stream, canonical=None, indent=None, width=None,
951            allow_unicode=None, line_break=None, encoding=None,
952            explicit_start=None, explicit_end=None, version=None, tags=None):
953        if yaml_emitter_initialize(&self.emitter) == 0:
954            raise MemoryError
955        self.stream = stream
956        self.dump_unicode = 0
957        try:
958            if stream.encoding:
959                self.dump_unicode = 1
960        except AttributeError:
961            pass
962        self.use_encoding = encoding
963        yaml_emitter_set_output(&self.emitter, output_handler, <void *>self)   
964        if canonical:
965            yaml_emitter_set_canonical(&self.emitter, 1)
966        if indent is not None:
967            yaml_emitter_set_indent(&self.emitter, indent)
968        if width is not None:
969            yaml_emitter_set_width(&self.emitter, width)
970        if allow_unicode:
971            yaml_emitter_set_unicode(&self.emitter, 1)
972        if line_break is not None:
973            if line_break == '\r':
974                yaml_emitter_set_break(&self.emitter, YAML_CR_BREAK)
975            elif line_break == '\n':
976                yaml_emitter_set_break(&self.emitter, YAML_LN_BREAK)
977            elif line_break == '\r\n':
978                yaml_emitter_set_break(&self.emitter, YAML_CRLN_BREAK)
979        self.document_start_implicit = 1
980        if explicit_start:
981            self.document_start_implicit = 0
982        self.document_end_implicit = 1
983        if explicit_end:
984            self.document_end_implicit = 0
985        self.use_version = version
986        self.use_tags = tags
987        self.serialized_nodes = {}
988        self.anchors = {}
989        self.last_alias_id = 0
990        self.closed = -1
991
992    def __dealloc__(self):
993        yaml_emitter_delete(&self.emitter)
994
995    cdef object _emitter_error(self):
996        if self.emitter.error == YAML_MEMORY_ERROR:
997            return MemoryError
998        elif self.emitter.error == YAML_EMITTER_ERROR:
999            if PY_MAJOR_VERSION < 3:
1000                problem = self.emitter.problem
1001            else:
1002                problem = PyUnicode_FromString(self.emitter.problem)
1003            return EmitterError(problem)
1004        if PY_MAJOR_VERSION < 3:
1005            raise ValueError("no emitter error")
1006        else:
1007            raise ValueError(u"no emitter error")
1008
1009    cdef int _object_to_event(self, object event_object, yaml_event_t *event) except 0:
1010        cdef yaml_encoding_t encoding
1011        cdef yaml_version_directive_t version_directive_value
1012        cdef yaml_version_directive_t *version_directive
1013        cdef yaml_tag_directive_t tag_directives_value[128]
1014        cdef yaml_tag_directive_t *tag_directives_start
1015        cdef yaml_tag_directive_t *tag_directives_end
1016        cdef int implicit
1017        cdef int plain_implicit
1018        cdef int quoted_implicit
1019        cdef char *anchor
1020        cdef char *tag
1021        cdef char *value
1022        cdef int length
1023        cdef yaml_scalar_style_t scalar_style
1024        cdef yaml_sequence_style_t sequence_style
1025        cdef yaml_mapping_style_t mapping_style
1026        event_class = event_object.__class__
1027        if event_class is StreamStartEvent:
1028            encoding = YAML_UTF8_ENCODING
1029            if event_object.encoding == u'utf-16-le' or event_object.encoding == 'utf-16-le':
1030                encoding = YAML_UTF16LE_ENCODING
1031            elif event_object.encoding == u'utf-16-be' or event_object.encoding == 'utf-16-be':
1032                encoding = YAML_UTF16BE_ENCODING
1033            if event_object.encoding is None:
1034                self.dump_unicode = 1
1035            if self.dump_unicode == 1:
1036                encoding = YAML_UTF8_ENCODING
1037            yaml_stream_start_event_initialize(event, encoding)
1038        elif event_class is StreamEndEvent:
1039            yaml_stream_end_event_initialize(event)
1040        elif event_class is DocumentStartEvent:
1041            version_directive = NULL
1042            if event_object.version:
1043                version_directive_value.major = event_object.version[0]
1044                version_directive_value.minor = event_object.version[1]
1045                version_directive = &version_directive_value
1046            tag_directives_start = NULL
1047            tag_directives_end = NULL
1048            if event_object.tags:
1049                if len(event_object.tags) > 128:
1050                    if PY_MAJOR_VERSION < 3:
1051                        raise ValueError("too many tags")
1052                    else:
1053                        raise ValueError(u"too many tags")
1054                tag_directives_start = tag_directives_value
1055                tag_directives_end = tag_directives_value
1056                cache = []
1057                for handle in event_object.tags:
1058                    prefix = event_object.tags[handle]
1059                    if PyUnicode_CheckExact(handle):
1060                        handle = PyUnicode_AsUTF8String(handle)
1061                        cache.append(handle)
1062                    if not PyString_CheckExact(handle):
1063                        if PY_MAJOR_VERSION < 3:
1064                            raise TypeError("tag handle must be a string")
1065                        else:
1066                            raise TypeError(u"tag handle must be a string")
1067                    tag_directives_end.handle = PyString_AS_STRING(handle)
1068                    if PyUnicode_CheckExact(prefix):
1069                        prefix = PyUnicode_AsUTF8String(prefix)
1070                        cache.append(prefix)
1071                    if not PyString_CheckExact(prefix):
1072                        if PY_MAJOR_VERSION < 3:
1073                            raise TypeError("tag prefix must be a string")
1074                        else:
1075                            raise TypeError(u"tag prefix must be a string")
1076                    tag_directives_end.prefix = PyString_AS_STRING(prefix)
1077                    tag_directives_end = tag_directives_end+1
1078            implicit = 1
1079            if event_object.explicit:
1080                implicit = 0
1081            if yaml_document_start_event_initialize(event, version_directive,
1082                    tag_directives_start, tag_directives_end, implicit) == 0:
1083                raise MemoryError
1084        elif event_class is DocumentEndEvent:
1085            implicit = 1
1086            if event_object.explicit:
1087                implicit = 0
1088            yaml_document_end_event_initialize(event, implicit)
1089        elif event_class is AliasEvent:
1090            anchor = NULL
1091            anchor_object = event_object.anchor
1092            if PyUnicode_CheckExact(anchor_object):
1093                anchor_object = PyUnicode_AsUTF8String(anchor_object)
1094            if not PyString_CheckExact(anchor_object):
1095                if PY_MAJOR_VERSION < 3:
1096                    raise TypeError("anchor must be a string")
1097                else:
1098                    raise TypeError(u"anchor must be a string")
1099            anchor = PyString_AS_STRING(anchor_object)
1100            if yaml_alias_event_initialize(event, anchor) == 0:
1101                raise MemoryError
1102        elif event_class is ScalarEvent:
1103            anchor = NULL
1104            anchor_object = event_object.anchor
1105            if anchor_object is not None:
1106                if PyUnicode_CheckExact(anchor_object):
1107                    anchor_object = PyUnicode_AsUTF8String(anchor_object)
1108                if not PyString_CheckExact(anchor_object):
1109                    if PY_MAJOR_VERSION < 3:
1110                        raise TypeError("anchor must be a string")
1111                    else:
1112                        raise TypeError(u"anchor must be a string")
1113                anchor = PyString_AS_STRING(anchor_object)
1114            tag = NULL
1115            tag_object = event_object.tag
1116            if tag_object is not None:
1117                if PyUnicode_CheckExact(tag_object):
1118                    tag_object = PyUnicode_AsUTF8String(tag_object)
1119                if not PyString_CheckExact(tag_object):
1120                    if PY_MAJOR_VERSION < 3:
1121                        raise TypeError("tag must be a string")
1122                    else:
1123                        raise TypeError(u"tag must be a string")
1124                tag = PyString_AS_STRING(tag_object)
1125            value_object = event_object.value
1126            if PyUnicode_CheckExact(value_object):
1127                value_object = PyUnicode_AsUTF8String(value_object)
1128            if not PyString_CheckExact(value_object):
1129                if PY_MAJOR_VERSION < 3:
1130                    raise TypeError("value must be a string")
1131                else:
1132                    raise TypeError(u"value must be a string")
1133            value = PyString_AS_STRING(value_object)
1134            length = PyString_GET_SIZE(value_object)
1135            plain_implicit = 0
1136            quoted_implicit = 0
1137            if event_object.implicit is not None:
1138                plain_implicit = event_object.implicit[0]
1139                quoted_implicit = event_object.implicit[1]
1140            style_object = event_object.style
1141            scalar_style = YAML_PLAIN_SCALAR_STYLE
1142            if style_object == "'" or style_object == u"'":
1143                scalar_style = YAML_SINGLE_QUOTED_SCALAR_STYLE
1144            elif style_object == "\"" or style_object == u"\"":
1145                scalar_style = YAML_DOUBLE_QUOTED_SCALAR_STYLE
1146            elif style_object == "|" or style_object == u"|":
1147                scalar_style = YAML_LITERAL_SCALAR_STYLE
1148            elif style_object == ">" or style_object == u">":
1149                scalar_style = YAML_FOLDED_SCALAR_STYLE
1150            if yaml_scalar_event_initialize(event, anchor, tag, value, length,
1151                    plain_implicit, quoted_implicit, scalar_style) == 0:
1152                raise MemoryError
1153        elif event_class is SequenceStartEvent:
1154            anchor = NULL
1155            anchor_object = event_object.anchor
1156            if anchor_object is not None:
1157                if PyUnicode_CheckExact(anchor_object):
1158                    anchor_object = PyUnicode_AsUTF8String(anchor_object)
1159                if not PyString_CheckExact(anchor_object):
1160                    if PY_MAJOR_VERSION < 3:
1161                        raise TypeError("anchor must be a string")
1162                    else:
1163                        raise TypeError(u"anchor must be a string")
1164                anchor = PyString_AS_STRING(anchor_object)
1165            tag = NULL
1166            tag_object = event_object.tag
1167            if tag_object is not None:
1168                if PyUnicode_CheckExact(tag_object):
1169                    tag_object = PyUnicode_AsUTF8String(tag_object)
1170                if not PyString_CheckExact(tag_object):
1171                    if PY_MAJOR_VERSION < 3:
1172                        raise TypeError("tag must be a string")
1173                    else:
1174                        raise TypeError(u"tag must be a string")
1175                tag = PyString_AS_STRING(tag_object)
1176            implicit = 0
1177            if event_object.implicit:
1178                implicit = 1
1179            sequence_style = YAML_BLOCK_SEQUENCE_STYLE
1180            if event_object.flow_style:
1181                sequence_style = YAML_FLOW_SEQUENCE_STYLE
1182            if yaml_sequence_start_event_initialize(event, anchor, tag,
1183                    implicit, sequence_style) == 0:
1184                raise MemoryError
1185        elif event_class is MappingStartEvent:
1186            anchor = NULL
1187            anchor_object = event_object.anchor
1188            if anchor_object is not None:
1189                if PyUnicode_CheckExact(anchor_object):
1190                    anchor_object = PyUnicode_AsUTF8String(anchor_object)
1191                if not PyString_CheckExact(anchor_object):
1192                    if PY_MAJOR_VERSION < 3:
1193                        raise TypeError("anchor must be a string")
1194                    else:
1195                        raise TypeError(u"anchor must be a string")
1196                anchor = PyString_AS_STRING(anchor_object)
1197            tag = NULL
1198            tag_object = event_object.tag
1199            if tag_object is not None:
1200                if PyUnicode_CheckExact(tag_object):
1201                    tag_object = PyUnicode_AsUTF8String(tag_object)
1202                if not PyString_CheckExact(tag_object):
1203                    if PY_MAJOR_VERSION < 3:
1204                        raise TypeError("tag must be a string")
1205                    else:
1206                        raise TypeError(u"tag must be a string")
1207                tag = PyString_AS_STRING(tag_object)
1208            implicit = 0
1209            if event_object.implicit:
1210                implicit = 1
1211            mapping_style = YAML_BLOCK_MAPPING_STYLE
1212            if event_object.flow_style:
1213                mapping_style = YAML_FLOW_MAPPING_STYLE
1214            if yaml_mapping_start_event_initialize(event, anchor, tag,
1215                    implicit, mapping_style) == 0:
1216                raise MemoryError
1217        elif event_class is SequenceEndEvent:
1218            yaml_sequence_end_event_initialize(event)
1219        elif event_class is MappingEndEvent:
1220            yaml_mapping_end_event_initialize(event)
1221        else:
1222            if PY_MAJOR_VERSION < 3:
1223                raise TypeError("invalid event %s" % event_object)
1224            else:
1225                raise TypeError(u"invalid event %s" % event_object)
1226        return 1
1227
1228    def emit(self, event_object):
1229        cdef yaml_event_t event
1230        self._object_to_event(event_object, &event)
1231        if yaml_emitter_emit(&self.emitter, &event) == 0:
1232            error = self._emitter_error()
1233            raise error
1234
1235    def open(self):
1236        cdef yaml_event_t event
1237        cdef yaml_encoding_t encoding
1238        if self.closed == -1:
1239            if self.use_encoding == u'utf-16-le' or self.use_encoding == 'utf-16-le':
1240                encoding = YAML_UTF16LE_ENCODING
1241            elif self.use_encoding == u'utf-16-be' or self.use_encoding == 'utf-16-be':
1242                encoding = YAML_UTF16BE_ENCODING
1243            else:
1244                encoding = YAML_UTF8_ENCODING
1245            if self.use_encoding is None:
1246                self.dump_unicode = 1
1247            if self.dump_unicode == 1:
1248                encoding = YAML_UTF8_ENCODING
1249            yaml_stream_start_event_initialize(&event, encoding)
1250            if yaml_emitter_emit(&self.emitter, &event) == 0:
1251                error = self._emitter_error()
1252                raise error
1253            self.closed = 0
1254        elif self.closed == 1:
1255            if PY_MAJOR_VERSION < 3:
1256                raise SerializerError("serializer is closed")
1257            else:
1258                raise SerializerError(u"serializer is closed")
1259        else:
1260            if PY_MAJOR_VERSION < 3:
1261                raise SerializerError("serializer is already opened")
1262            else:
1263                raise SerializerError(u"serializer is already opened")
1264
1265    def close(self):
1266        cdef yaml_event_t event
1267        if self.closed == -1:
1268            if PY_MAJOR_VERSION < 3:
1269                raise SerializerError("serializer is not opened")
1270            else:
1271                raise SerializerError(u"serializer is not opened")
1272        elif self.closed == 0:
1273            yaml_stream_end_event_initialize(&event)
1274            if yaml_emitter_emit(&self.emitter, &event) == 0:
1275                error = self._emitter_error()
1276                raise error
1277            self.closed = 1
1278
1279    def serialize(self, node):
1280        cdef yaml_event_t event
1281        cdef yaml_version_directive_t version_directive_value
1282        cdef yaml_version_directive_t *version_directive
1283        cdef yaml_tag_directive_t tag_directives_value[128]
1284        cdef yaml_tag_directive_t *tag_directives_start
1285        cdef yaml_tag_directive_t *tag_directives_end
1286        if self.closed == -1:
1287            if PY_MAJOR_VERSION < 3:
1288                raise SerializerError("serializer is not opened")
1289            else:
1290                raise SerializerError(u"serializer is not opened")
1291        elif self.closed == 1:
1292            if PY_MAJOR_VERSION < 3:
1293                raise SerializerError("serializer is closed")
1294            else:
1295                raise SerializerError(u"serializer is closed")
1296        cache = []
1297        version_directive = NULL
1298        if self.use_version:
1299            version_directive_value.major = self.use_version[0]
1300            version_directive_value.minor = self.use_version[1]
1301            version_directive = &version_directive_value
1302        tag_directives_start = NULL
1303        tag_directives_end = NULL
1304        if self.use_tags:
1305            if len(self.use_tags) > 128:
1306                if PY_MAJOR_VERSION < 3:
1307                    raise ValueError("too many tags")
1308                else:
1309                    raise ValueError(u"too many tags")
1310            tag_directives_start = tag_directives_value
1311            tag_directives_end = tag_directives_value
1312            for handle in self.use_tags:
1313                prefix = self.use_tags[handle]
1314                if PyUnicode_CheckExact(handle):
1315                    handle = PyUnicode_AsUTF8String(handle)
1316                    cache.append(handle)
1317                if not PyString_CheckExact(handle):
1318                    if PY_MAJOR_VERSION < 3:
1319                        raise TypeError("tag handle must be a string")
1320                    else:
1321                        raise TypeError(u"tag handle must be a string")
1322                tag_directives_end.handle = PyString_AS_STRING(handle)
1323                if PyUnicode_CheckExact(prefix):
1324                    prefix = PyUnicode_AsUTF8String(prefix)
1325                    cache.append(prefix)
1326                if not PyString_CheckExact(prefix):
1327                    if PY_MAJOR_VERSION < 3:
1328                        raise TypeError("tag prefix must be a string")
1329                    else:
1330                        raise TypeError(u"tag prefix must be a string")
1331                tag_directives_end.prefix = PyString_AS_STRING(prefix)
1332                tag_directives_end = tag_directives_end+1
1333        if yaml_document_start_event_initialize(&event, version_directive,
1334                tag_directives_start, tag_directives_end,
1335                self.document_start_implicit) == 0:
1336            raise MemoryError
1337        if yaml_emitter_emit(&self.emitter, &event) == 0:
1338            error = self._emitter_error()
1339            raise error
1340        self._anchor_node(node)
1341        self._serialize_node(node, None, None)
1342        yaml_document_end_event_initialize(&event, self.document_end_implicit)
1343        if yaml_emitter_emit(&self.emitter, &event) == 0:
1344            error = self._emitter_error()
1345            raise error
1346        self.serialized_nodes = {}
1347        self.anchors = {}
1348        self.last_alias_id = 0
1349
1350    cdef int _anchor_node(self, object node) except 0:
1351        if node in self.anchors:
1352            if self.anchors[node] is None:
1353                self.last_alias_id = self.last_alias_id+1
1354                self.anchors[node] = u"id%03d" % self.last_alias_id
1355        else:
1356            self.anchors[node] = None
1357            node_class = node.__class__
1358            if node_class is SequenceNode:
1359                for item in node.value:
1360                    self._anchor_node(item)
1361            elif node_class is MappingNode:
1362                for key, value in node.value:
1363                    self._anchor_node(key)
1364                    self._anchor_node(value)
1365        return 1
1366
1367    cdef int _serialize_node(self, object node, object parent, object index) except 0:
1368        cdef yaml_event_t event
1369        cdef int implicit
1370        cdef int plain_implicit
1371        cdef int quoted_implicit
1372        cdef char *anchor
1373        cdef char *tag
1374        cdef char *value
1375        cdef int length
1376        cdef int item_index
1377        cdef yaml_scalar_style_t scalar_style
1378        cdef yaml_sequence_style_t sequence_style
1379        cdef yaml_mapping_style_t mapping_style
1380        anchor_object = self.anchors[node]
1381        anchor = NULL
1382        if anchor_object is not None:
1383            anchor = PyString_AS_STRING(PyUnicode_AsUTF8String(anchor_object))
1384        if node in self.serialized_nodes:
1385            if yaml_alias_event_initialize(&event, anchor) == 0:
1386                raise MemoryError
1387            if yaml_emitter_emit(&self.emitter, &event) == 0:
1388                error = self._emitter_error()
1389                raise error
1390        else:
1391            node_class = node.__class__
1392            self.serialized_nodes[node] = True
1393            self.descend_resolver(parent, index)
1394            if node_class is ScalarNode:
1395                plain_implicit = 0
1396                quoted_implicit = 0
1397                tag_object = node.tag
1398                if self.resolve(ScalarNode, node.value, (True, False)) == tag_object:
1399                    plain_implicit = 1
1400                if self.resolve(ScalarNode, node.value, (False, True)) == tag_object:
1401                    quoted_implicit = 1
1402                tag = NULL
1403                if tag_object is not None:
1404                    if PyUnicode_CheckExact(tag_object):
1405                        tag_object = PyUnicode_AsUTF8String(tag_object)
1406                    if not PyString_CheckExact(tag_object):
1407                        if PY_MAJOR_VERSION < 3:
1408                            raise TypeError("tag must be a string")
1409                        else:
1410                            raise TypeError(u"tag must be a string")
1411                    tag = PyString_AS_STRING(tag_object)
1412                value_object = node.value
1413                if PyUnicode_CheckExact(value_object):
1414                    value_object = PyUnicode_AsUTF8String(value_object)
1415                if not PyString_CheckExact(value_object):
1416                    if PY_MAJOR_VERSION < 3:
1417                        raise TypeError("value must be a string")
1418                    else:
1419                        raise TypeError(u"value must be a string")
1420                value = PyString_AS_STRING(value_object)
1421                length = PyString_GET_SIZE(value_object)
1422                style_object = node.style
1423                scalar_style = YAML_PLAIN_SCALAR_STYLE
1424                if style_object == "'" or style_object == u"'":
1425                    scalar_style = YAML_SINGLE_QUOTED_SCALAR_STYLE
1426                elif style_object == "\"" or style_object == u"\"":
1427                    scalar_style = YAML_DOUBLE_QUOTED_SCALAR_STYLE
1428                elif style_object == "|" or style_object == u"|":
1429                    scalar_style = YAML_LITERAL_SCALAR_STYLE
1430                elif style_object == ">" or style_object == u">":
1431                    scalar_style = YAML_FOLDED_SCALAR_STYLE
1432                if yaml_scalar_event_initialize(&event, anchor, tag, value, length,
1433                        plain_implicit, quoted_implicit, scalar_style) == 0:
1434                    raise MemoryError
1435                if yaml_emitter_emit(&self.emitter, &event) == 0:
1436                    error = self._emitter_error()
1437                    raise error
1438            elif node_class is SequenceNode:
1439                implicit = 0
1440                tag_object = node.tag
1441                if self.resolve(SequenceNode, node.value, True) == tag_object:
1442                    implicit = 1
1443                tag = NULL
1444                if tag_object is not None:
1445                    if PyUnicode_CheckExact(tag_object):
1446                        tag_object = PyUnicode_AsUTF8String(tag_object)
1447                    if not PyString_CheckExact(tag_object):
1448                        if PY_MAJOR_VERSION < 3:
1449                            raise TypeError("tag must be a string")
1450                        else:
1451                            raise TypeError(u"tag must be a string")
1452                    tag = PyString_AS_STRING(tag_object)
1453                sequence_style = YAML_BLOCK_SEQUENCE_STYLE
1454                if node.flow_style:
1455                    sequence_style = YAML_FLOW_SEQUENCE_STYLE
1456                if yaml_sequence_start_event_initialize(&event, anchor, tag,
1457                        implicit, sequence_style) == 0:
1458                    raise MemoryError
1459                if yaml_emitter_emit(&self.emitter, &event) == 0:
1460                    error = self._emitter_error()
1461                    raise error
1462                item_index = 0
1463                for item in node.value:
1464                    self._serialize_node(item, node, item_index)
1465                    item_index = item_index+1
1466                yaml_sequence_end_event_initialize(&event)
1467                if yaml_emitter_emit(&self.emitter, &event) == 0:
1468                    error = self._emitter_error()
1469                    raise error
1470            elif node_class is MappingNode:
1471                implicit = 0
1472                tag_object = node.tag
1473                if self.resolve(MappingNode, node.value, True) == tag_object:
1474                    implicit = 1
1475                tag = NULL
1476                if tag_object is not None:
1477                    if PyUnicode_CheckExact(tag_object):
1478                        tag_object = PyUnicode_AsUTF8String(tag_object)
1479                    if not PyString_CheckExact(tag_object):
1480                        if PY_MAJOR_VERSION < 3:
1481                            raise TypeError("tag must be a string")
1482                        else:
1483                            raise TypeError(u"tag must be a string")
1484                    tag = PyString_AS_STRING(tag_object)
1485                mapping_style = YAML_BLOCK_MAPPING_STYLE
1486                if node.flow_style:
1487                    mapping_style = YAML_FLOW_MAPPING_STYLE
1488                if yaml_mapping_start_event_initialize(&event, anchor, tag,
1489                        implicit, mapping_style) == 0:
1490                    raise MemoryError
1491                if yaml_emitter_emit(&self.emitter, &event) == 0:
1492                    error = self._emitter_error()
1493                    raise error
1494                for item_key, item_value in node.value:
1495                    self._serialize_node(item_key, node, None)
1496                    self._serialize_node(item_value, node, item_key)
1497                yaml_mapping_end_event_initialize(&event)
1498                if yaml_emitter_emit(&self.emitter, &event) == 0:
1499                    error = self._emitter_error()
1500                    raise error
1501            self.ascend_resolver()
1502        return 1
1503
1504cdef int output_handler(void *data, char *buffer, int size) except 0:
1505    cdef CEmitter emitter
1506    emitter = <CEmitter>data
1507    if emitter.dump_unicode == 0:
1508        value = PyString_FromStringAndSize(buffer, size)
1509    else:
1510        value = PyUnicode_DecodeUTF8(buffer, size, 'strict')
1511    emitter.stream.write(value)
1512    return 1
1513
Note: See TracBrowser for help on using the repository browser.