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