Update PyRex based bindings to libyaml to include Parser functions.
[pyyaml/python3.git] / ext / _yaml.pyx
blob65fecaaf26525a85d3112a11a6deb03e1a31735e
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 def test_scanner(data):
13 cdef yaml_parser_t *parser
14 cdef yaml_token_t *token
15 cdef int done
16 if PyString_CheckExact(data) == 0:
17 raise TypeError("string input required")
18 parser = yaml_parser_new()
19 if parser == NULL:
20 raise MemoryError
21 yaml_parser_set_input_string(parser, PyString_AS_STRING(data), PyString_GET_SIZE(data))
22 done = 0
23 while done == 0:
24 token = yaml_parser_get_token(parser)
25 if token == NULL:
26 raise MemoryError
27 if token.type == YAML_STREAM_END_TOKEN:
28 done = 1
29 yaml_token_delete(token)
30 yaml_parser_delete(parser)
32 def test_parser(data):
33 cdef yaml_parser_t *parser
34 cdef yaml_event_t *event
35 cdef int done
36 if PyString_CheckExact(data) == 0:
37 raise TypeError("string input required")
38 parser = yaml_parser_new()
39 if parser == NULL:
40 raise MemoryError
41 yaml_parser_set_input_string(parser, PyString_AS_STRING(data), PyString_GET_SIZE(data))
42 done = 0
43 while done == 0:
44 event = yaml_parser_get_event(parser)
45 if event == NULL:
46 raise MemoryError
47 if event.type == YAML_STREAM_END_EVENT:
48 done = 1
49 yaml_event_delete(event)
50 yaml_parser_delete(parser)
52 cdef class ScannerAndParser:
54 cdef yaml_parser_t *parser
55 cdef int eof
56 cdef object stream
57 cdef yaml_token_t *cached_token
58 cdef yaml_event_t *cached_event
59 cdef object cached_obj
61 def __init__(self, stream):
62 if hasattr(stream, 'read'):
63 stream = stream.read()
64 if PyUnicode_CheckExact(stream) != 0:
65 stream = stream.encode('utf-8')
66 if PyString_CheckExact(stream) == 0:
67 raise TypeError("a string or stream input is required")
68 self.parser = yaml_parser_new()
69 if self.parser == NULL:
70 raise MemoryError
71 yaml_parser_set_input_string(self.parser, PyString_AS_STRING(stream), PyString_GET_SIZE(stream))
72 self.eof = 0
73 self.stream = stream
74 self.cached_token = NULL
75 self.cached_obj = None
77 def __dealloc__(self):
78 if self.parser != NULL:
79 yaml_parser_delete(self.parser)
80 self.parser = NULL
82 cdef object _convert_token(self, yaml_token_t *token):
83 if token == NULL:
84 if self.parser.error == YAML_MEMORY_ERROR:
85 raise MemoryError
86 elif self.parser.error == YAML_READER_ERROR:
87 raise yaml.reader.ReaderError("<input>",
88 self.parser.problem_offset,
89 self.parser.problem_value,
90 '?', self.parser.problem)
91 elif self.parser.error == YAML_SCANNER_ERROR:
92 if self.parser.context != NULL:
93 raise yaml.scanner.ScannerError(
94 self.parser.context,
95 yaml.Mark("<input>",
96 self.parser.context_mark.index,
97 self.parser.context_mark.line,
98 self.parser.context_mark.column,
99 None, None),
100 self.parser.problem,
101 yaml.Mark("<input>",
102 self.parser.problem_mark.index,
103 self.parser.problem_mark.line,
104 self.parser.problem_mark.column,
105 None, None))
106 else:
107 raise yaml.scanner.ScannerError(None, None,
108 self.parser.problem,
109 yaml.Mark("<input>",
110 self.parser.problem_mark.index,
111 self.parser.problem_mark.line,
112 self.parser.problem_mark.column,
113 None, None))
114 else:
115 raise RuntimeError("neither error nor token produced")
116 start_mark = yaml.Mark("<input>",
117 token.start_mark.index,
118 token.start_mark.line,
119 token.start_mark.column,
120 None, None)
121 end_mark = yaml.Mark("<input>",
122 token.end_mark.index,
123 token.end_mark.line,
124 token.end_mark.column,
125 None, None)
126 if token.type == YAML_STREAM_START_TOKEN:
127 return yaml.StreamStartToken(start_mark, end_mark)
128 elif token.type == YAML_STREAM_END_TOKEN:
129 return yaml.StreamEndToken(start_mark, end_mark)
130 elif token.type == YAML_VERSION_DIRECTIVE_TOKEN:
131 return yaml.DirectiveToken('YAML',
132 (token.data.version_directive.major,
133 token.data.version_directive.minor),
134 start_mark, end_mark)
135 elif token.type == YAML_TAG_DIRECTIVE_TOKEN:
136 return yaml.DirectiveToken('TAG',
137 (token.data.tag_directive.handle,
138 token.data.tag_directive.prefix),
139 start_mark, end_mark)
140 elif token.type == YAML_DOCUMENT_START_TOKEN:
141 return yaml.DocumentStartToken(start_mark, end_mark)
142 elif token.type == YAML_DOCUMENT_END_TOKEN:
143 return yaml.DocumentEndToken(start_mark, end_mark)
144 elif token.type == YAML_BLOCK_SEQUENCE_START_TOKEN:
145 return yaml.BlockSequenceStartToken(start_mark, end_mark)
146 elif token.type == YAML_BLOCK_MAPPING_START_TOKEN:
147 return yaml.BlockMappingStartToken(start_mark, end_mark)
148 elif token.type == YAML_BLOCK_END_TOKEN:
149 return yaml.BlockEndToken(start_mark, end_mark)
150 elif token.type == YAML_FLOW_SEQUENCE_START_TOKEN:
151 return yaml.FlowSequenceStartToken(start_mark, end_mark)
152 elif token.type == YAML_FLOW_SEQUENCE_END_TOKEN:
153 return yaml.FlowSequenceEndToken(start_mark, end_mark)
154 elif token.type == YAML_FLOW_MAPPING_START_TOKEN:
155 return yaml.FlowMappingStartToken(start_mark, end_mark)
156 elif token.type == YAML_FLOW_MAPPING_END_TOKEN:
157 return yaml.FlowMappingEndToken(start_mark, end_mark)
158 elif token.type == YAML_BLOCK_ENTRY_TOKEN:
159 return yaml.BlockEntryToken(start_mark, end_mark)
160 elif token.type == YAML_FLOW_ENTRY_TOKEN:
161 return yaml.FlowEntryToken(start_mark, end_mark)
162 elif token.type == YAML_KEY_TOKEN:
163 return yaml.KeyToken(start_mark, end_mark)
164 elif token.type == YAML_VALUE_TOKEN:
165 return yaml.ValueToken(start_mark, end_mark)
166 elif token.type == YAML_ALIAS_TOKEN:
167 return yaml.AliasToken(token.data.alias.value,
168 start_mark, end_mark)
169 elif token.type == YAML_ANCHOR_TOKEN:
170 return yaml.AnchorToken(token.data.anchor.value,
171 start_mark, end_mark)
172 elif token.type == YAML_TAG_TOKEN:
173 handle = token.data.tag.handle
174 if handle == '':
175 handle = None
176 return yaml.TagToken((handle, token.data.tag.suffix),
177 start_mark, end_mark)
178 elif token.type == YAML_SCALAR_TOKEN:
179 value = PyString_FromStringAndSize(token.data.scalar.value, token.data.scalar.length)
180 return yaml.ScalarToken(unicode(value, 'utf-8'),
181 bool(token.data.scalar.style == YAML_PLAIN_SCALAR_STYLE),
182 start_mark, end_mark)
183 else:
184 raise RuntimeError("unknown token type")
186 cdef object _convert_event(self, yaml_event_t *event):
187 if event == NULL:
188 if self.parser.error == YAML_MEMORY_ERROR:
189 raise MemoryError
190 elif self.parser.error == YAML_READER_ERROR:
191 raise yaml.reader.ReaderError("<input>",
192 self.parser.problem_offset,
193 self.parser.problem_value,
194 '?', self.parser.problem)
195 elif self.parser.error == YAML_SCANNER_ERROR:
196 if self.parser.context != NULL:
197 raise yaml.scanner.ScannerError(
198 self.parser.context,
199 yaml.Mark("<input>",
200 self.parser.context_mark.index,
201 self.parser.context_mark.line,
202 self.parser.context_mark.column,
203 None, None),
204 self.parser.problem,
205 yaml.Mark("<input>",
206 self.parser.problem_mark.index,
207 self.parser.problem_mark.line,
208 self.parser.problem_mark.column,
209 None, None))
210 else:
211 raise yaml.scanner.ScannerError(None, None,
212 self.parser.problem,
213 yaml.Mark("<input>",
214 self.parser.problem_mark.index,
215 self.parser.problem_mark.line,
216 self.parser.problem_mark.column,
217 None, None))
218 elif self.parser.error == YAML_PARSER_ERROR:
219 if self.parser.context != NULL:
220 raise yaml.parser.ParserError(
221 self.parser.context,
222 yaml.Mark("<input>",
223 self.parser.context_mark.index,
224 self.parser.context_mark.line,
225 self.parser.context_mark.column,
226 None, None),
227 self.parser.problem,
228 yaml.Mark("<input>",
229 self.parser.problem_mark.index,
230 self.parser.problem_mark.line,
231 self.parser.problem_mark.column,
232 None, None))
233 else:
234 raise yaml.parser.ParserError(None, None,
235 self.parser.problem,
236 yaml.Mark("<input>",
237 self.parser.problem_mark.index,
238 self.parser.problem_mark.line,
239 self.parser.problem_mark.column,
240 None, None))
241 else:
242 raise RuntimeError("neither error nor event produced")
243 start_mark = yaml.Mark("<input>",
244 event.start_mark.index,
245 event.start_mark.line,
246 event.start_mark.column,
247 None, None)
248 end_mark = yaml.Mark("<input>",
249 event.end_mark.index,
250 event.end_mark.line,
251 event.end_mark.column,
252 None, None)
253 if event.type == YAML_STREAM_START_EVENT:
254 return yaml.StreamStartEvent(start_mark, end_mark)
255 elif event.type == YAML_STREAM_END_EVENT:
256 return yaml.StreamEndEvent(start_mark, end_mark)
257 elif event.type == YAML_DOCUMENT_START_EVENT:
258 return yaml.DocumentStartEvent(start_mark, end_mark,
259 (event.data.document_start.implicit == 0))
260 elif event.type == YAML_DOCUMENT_END_EVENT:
261 return yaml.DocumentEndEvent(start_mark, end_mark,
262 (event.data.document_end.implicit == 0))
263 elif event.type == YAML_SCALAR_EVENT:
264 if event.data.scalar.anchor == NULL:
265 anchor = None
266 else:
267 anchor = event.data.scalar.anchor
268 if event.data.scalar.tag == NULL:
269 tag = None
270 else:
271 tag = event.data.scalar.tag
272 implicit = (event.data.scalar.plain_implicit == 1, event.data.scalar.quoted_implicit == 1)
273 flow_style = (event.data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE)
274 value = PyString_FromStringAndSize(event.data.scalar.value, event.data.scalar.length)
275 return yaml.ScalarEvent(anchor, tag, implicit, unicode(value, 'utf-8'),
276 start_mark, end_mark)
277 elif event.type == YAML_ALIAS_EVENT:
278 if event.data.alias.anchor == NULL:
279 anchor = None
280 else:
281 anchor = event.data.alias.anchor
282 return yaml.AliasEvent(anchor, start_mark, end_mark)
283 elif event.type == YAML_SEQUENCE_START_EVENT:
284 if event.data.sequence_start.anchor == NULL:
285 anchor = None
286 else:
287 anchor = event.data.sequence_start.anchor
288 if event.data.sequence_start.tag == NULL:
289 tag = None
290 else:
291 tag = event.data.sequence_start.tag
292 implicit = (event.data.sequence_start.implicit == 1)
293 flow_style = (event.data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE)
294 return yaml.SequenceStartEvent(anchor, tag, implicit,
295 start_mark, end_mark, flow_style)
296 elif event.type == YAML_MAPPING_START_EVENT:
297 if event.data.mapping_start.anchor == NULL:
298 anchor = None
299 else:
300 anchor = event.data.mapping_start.anchor
301 if event.data.mapping_start.tag == NULL:
302 tag = None
303 else:
304 tag = event.data.mapping_start.tag
305 implicit = (event.data.mapping_start.implicit == 1)
306 flow_style = (event.data.mapping_start.style == YAML_FLOW_MAPPING_STYLE)
307 return yaml.MappingStartEvent(anchor, tag, implicit,
308 start_mark, end_mark, flow_style)
309 elif event.type == YAML_SEQUENCE_END_EVENT:
310 return yaml.SequenceEndEvent(start_mark, end_mark)
311 elif event.type == YAML_MAPPING_END_EVENT:
312 return yaml.MappingEndEvent(start_mark, end_mark)
313 else:
314 raise RuntimeError("unknown event type")
316 def get_token(self):
317 cdef yaml_token_t *token
318 if self.cached_token != NULL:
319 yaml_token_delete(yaml_parser_get_token(self.parser))
320 obj = self.cached_obj
321 self.cached_token = NULL
322 self.cached_obj = None
323 return obj
324 if self.eof != 0:
325 return None
326 token = yaml_parser_get_token(self.parser)
327 obj = self._convert_token(token)
328 if token.type == YAML_STREAM_END_TOKEN:
329 self.eof = 1
330 yaml_token_delete(token)
331 return obj
333 def peek_token(self):
334 cdef yaml_token_t *token
335 if self.cached_token != NULL:
336 return self.cached_obj
337 if self.eof != 0:
338 return None
339 token = yaml_parser_peek_token(self.parser)
340 obj = self._convert_token(token)
341 if token.type == YAML_STREAM_END_TOKEN:
342 self.eof = 1
343 self.cached_token = token
344 self.cached_obj = obj
345 return obj
347 def check_token(self, *choices):
348 cdef yaml_token_t *token
349 if self.cached_token != NULL:
350 obj = self.cached_obj
351 elif self.eof != 0:
352 return False
353 else:
354 token = yaml_parser_peek_token(self.parser)
355 obj = self._convert_token(token)
356 if token.type == YAML_STREAM_END_TOKEN:
357 self.eof = 1
358 self.cached_token = token
359 self.cached_obj = obj
360 if not choices:
361 return True
362 for choice in choices:
363 if isinstance(obj, choice):
364 return True
365 return False
367 def get_event(self):
368 cdef yaml_event_t *event
369 if self.cached_event != NULL:
370 yaml_event_delete(yaml_parser_get_event(self.parser))
371 obj = self.cached_obj
372 self.cached_event = NULL
373 self.cached_obj = None
374 return obj
375 if self.eof != 0:
376 return None
377 event = yaml_parser_get_event(self.parser)
378 obj = self._convert_event(event)
379 if event.type == YAML_STREAM_END_EVENT:
380 self.eof = 1
381 yaml_event_delete(event)
382 return obj
384 def peek_event(self):
385 cdef yaml_event_t *event
386 if self.cached_event != NULL:
387 return self.cached_obj
388 if self.eof != 0:
389 return None
390 event = yaml_parser_peek_event(self.parser)
391 obj = self._convert_event(event)
392 if event.type == YAML_STREAM_END_EVENT:
393 self.eof = 1
394 self.cached_event = event
395 self.cached_obj = obj
396 return obj
398 def check_event(self, *choices):
399 cdef yaml_event_t *event
400 if self.cached_event != NULL:
401 obj = self.cached_obj
402 elif self.eof != 0:
403 return False
404 else:
405 event = yaml_parser_peek_event(self.parser)
406 obj = self._convert_event(event)
407 if event.type == YAML_STREAM_END_EVENT:
408 self.eof = 1
409 self.cached_event = event
410 self.cached_obj = obj
411 if not choices:
412 return True
413 for choice in choices:
414 if isinstance(obj, choice):
415 return True
416 return False
418 class Loader(ScannerAndParser,
419 yaml.composer.Composer,
420 yaml.constructor.Constructor,
421 yaml.resolver.Resolver):
423 def __init__(self, stream):
424 ScannerAndParser.__init__(self, stream)
425 yaml.composer.Composer.__init__(self)
426 yaml.constructor.Constructor.__init__(self)
427 yaml.resolver.Resolver.__init__(self)
429 yaml.ExtLoader = Loader