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

Revision 205, 17.5 KB checked in by xi, 8 years ago (diff)

Update PyRex? based bindings to libyaml to include Parser functions.

RevLine 
[195]1
2import yaml
3
4def get_version_string():
5    return yaml_get_version_string()
6
7def get_version():
8    cdef int major, minor, patch
9    yaml_get_version(&major, &minor, &patch)
10    return (major, minor, patch)
11
[196]12def 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)
31
[205]32def 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)
[195]51
[205]52cdef class ScannerAndParser:
53
[195]54    cdef yaml_parser_t *parser
55    cdef int eof
56    cdef object stream
[196]57    cdef yaml_token_t *cached_token
[205]58    cdef yaml_event_t *cached_event
[196]59    cdef object cached_obj
[195]60
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
[196]74        self.cached_token = NULL
75        self.cached_obj = None
[195]76
77    def __dealloc__(self):
78        if self.parser != NULL:
79            yaml_parser_delete(self.parser)
80            self.parser = NULL
81
[205]82    cdef object _convert_token(self, yaml_token_t *token):
[195]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:
[205]167            return yaml.AliasToken(token.data.alias.value,
[195]168                    start_mark, end_mark)
169        elif token.type == YAML_ANCHOR_TOKEN:
[205]170            return yaml.AnchorToken(token.data.anchor.value,
[195]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")
185
[205]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")
315
[195]316    def get_token(self):
317        cdef yaml_token_t *token
[196]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
[195]324        if self.eof != 0:
325            return None
326        token = yaml_parser_get_token(self.parser)
[205]327        obj = self._convert_token(token)
[195]328        if token.type == YAML_STREAM_END_TOKEN:
329            self.eof = 1
330        yaml_token_delete(token)
331        return obj
332
333    def peek_token(self):
334        cdef yaml_token_t *token
[196]335        if self.cached_token != NULL:
336            return self.cached_obj
[195]337        if self.eof != 0:
338            return None
339        token = yaml_parser_peek_token(self.parser)
[205]340        obj = self._convert_token(token)
[196]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
[195]346
347    def check_token(self, *choices):
348        cdef yaml_token_t *token
[196]349        if self.cached_token != NULL:
350            obj = self.cached_obj
351        elif self.eof != 0:
[195]352            return False
[196]353        else:
354            token = yaml_parser_peek_token(self.parser)
[205]355            obj = self._convert_token(token)
[196]356            if token.type == YAML_STREAM_END_TOKEN:
357                self.eof = 1
358            self.cached_token = token
359            self.cached_obj = obj
[195]360        if not choices:
361            return True
362        for choice in choices:
363            if isinstance(obj, choice):
364                return True
365        return False
366
[205]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
383
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
397
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
417
418class Loader(ScannerAndParser,
[195]419        yaml.composer.Composer,
420        yaml.constructor.Constructor,
421        yaml.resolver.Resolver):
422
423    def __init__(self, stream):
[205]424        ScannerAndParser.__init__(self, stream)
[195]425        yaml.composer.Composer.__init__(self)
426        yaml.constructor.Constructor.__init__(self)
427        yaml.resolver.Resolver.__init__(self)
428
429yaml.ExtLoader = Loader
430
Note: See TracBrowser for help on using the repository browser.