source: trunk/tests/test_parser.py @ 17

Revision 17, 8.4 KB checked in by xi, 9 years ago (diff)

Add _syck.Emitter (finally closes #19).

Line 
1
2import unittest
3
4import _syck
5
6import StringIO, gc
7
8EXAMPLE = """
9-
10  avg: 0.278
11  hr: 65
12  name: Mark McGwire
13-
14  avg: 0.288
15  hr: 63
16  name: Sammy Sosa
17"""
18
19INVALID = """
20 - invalid
21- document
22""", 2, 0
23
24COMPARE1 = """
25one: foo
26two: bar
27three: baz
28""", {
29    'one': 'foo',
30    'two': 'bar',
31    'three': 'baz',
32}
33
34COMPARE2 = """
35- Mark McGwire
36- Sammy Sosa
37- Ken Griffey
38""", [
39    'Mark McGwire',
40    'Sammy Sosa',
41    'Ken Griffey',
42]
43
44COMPARE3 = """
45american:
46  - Boston Red Sox
47  - Detroit Tigers
48  - New York Yankees
49national:
50  - New York Mets
51  - Chicago Cubs
52  - Atlanta Braves
53""", {
54    'american': [
55        'Boston Red Sox',
56        'Detroit Tigers',
57        'New York Yankees',
58    ],
59    'national': [
60        'New York Mets',
61        'Chicago Cubs',
62        'Atlanta Braves',
63    ],
64}
65
66DOCUMENTS0 = ""
67
68DOCUMENTS1 = """
69---
70Time: 2001-11-23 15:01:42 -05:00
71User: ed
72Warning: >
73  This is an error message
74  for the log file
75"""
76
77DOCUMENTS2 = """
78---
79Time: 2001-11-23 15:01:42 -05:00
80User: ed
81Warning: >
82  This is an error message
83  for the log file
84---
85Time: 2001-11-23 15:02:31 -05:00
86User: ed
87Warning: >
88  A slightly different error
89  message.
90"""
91
92DOCUMENTS3 = """
93---
94Time: 2001-11-23 15:01:42 -05:00
95User: ed
96Warning: >
97  This is an error message
98  for the log file
99---
100Time: 2001-11-23 15:02:31 -05:00
101User: ed
102Warning: >
103  A slightly different error
104  message.
105---
106Date: 2001-11-23 15:03:17 -05:00
107User: ed
108Fatal: >
109  Unknown variable "bar"
110Stack:
111  - file: TopClass.py
112    line: 23
113    code: |
114      x = MoreObject("345\\n")
115  - file: MoreClass.py
116    line: 58
117    code: |-
118      foo = bar
119"""
120
121IMPLICIT_TYPING = """
122- 'foo'
123- >-
124  bar
125- baz
126- 123
127- 3.14
128- true
129- false
130- []
131- {}
132""", [
133    ('str', True),
134    ('str', True),
135    ('str', False),
136    ('int', False),
137    ('float#fix', False),
138    ('bool#yes', False),
139    ('bool#no', False),
140    (None, False),
141    (None, False),
142]
143
144EXPLICIT_TYPING = """
145- !int '123'
146- !yamltype 'foo'
147- !python/type 'bar'
148- !domain.tld,2002/type 'baz'
149- !!private 'private'
150- !map {}
151- !seq []
152""", [
153    'tag:yaml.org,2002:int',
154    'tag:yaml.org,2002:yamltype',
155    'tag:python.yaml.org,2002:type',
156    'tag:domain.tld,2002:type',
157    'x-private:private',
158    'tag:yaml.org,2002:map',
159    'tag:yaml.org,2002:seq',
160]
161
162RECURSIVE = """
163--- &id002
164- &id001 Mark McGwire
165- Sammy Sosa
166- Ken Griffey
167- *id001
168- *id002
169"""
170
171class TestAttributes(unittest.TestCase):
172
173    def testAttributes(self):
174        parser = _syck.Parser(EXAMPLE)
175        self.assertEqual(type(parser), _syck.Parser)
176        self.assertEqual(parser.source, EXAMPLE)
177        self.assertEqual(parser.implicit_typing, True)
178        self.assertEqual(parser.taguri_expansion, True)
179        self.assertEqual(parser.eof, False)
180        node = parser.parse()
181        self.assert_(isinstance(node, _syck.Node))
182        self.assertEqual(parser.source, EXAMPLE)
183        self.assertEqual(parser.implicit_typing, True)
184        self.assertEqual(parser.taguri_expansion, True)
185        self.assertEqual(parser.eof, False)
186        self.assertEqual(parser.parse(), None)
187        self.assertEqual(parser.eof, True)
188
189class TestGarbage(unittest.TestCase):
190
191    def testGarbage(self):
192        gc.collect()
193        source = []
194        parser = _syck.Parser(source)
195        source.append(parser)
196        del source, parser
197        self.assertEqual(gc.collect(), 2)
198
199class TestErrors(unittest.TestCase):
200
201    def testError(self):
202        parser = _syck.Parser(INVALID[0])
203        self.assertRaises(_syck.error, lambda: parser.parse())
204
205    def testErrorLocation(self):
206        source, line, column = INVALID
207        parser = _syck.Parser(source)
208        try:
209            parser.parse()
210            raise Exception
211        except _syck.error, e:
212            self.assertEqual(e.args[1], line)
213            self.assertEqual(e.args[2], column)
214
215class EqualStructure:
216
217    def assertEqualStructure(self, node, structure):
218        if node.kind == 'scalar':
219            self.assertEqual(type(structure), str)
220            self.assertEqual(node.value, structure)
221        elif node.kind == 'seq':
222            self.assertEqual(type(structure), list)
223            self.assertEqual(len(node.value), len(structure))
224            for i, item in enumerate(node.value):
225                self.assertEqualStructure(item, structure[i])
226        elif node.kind == 'map':
227            self.assertEqual(type(structure), dict)
228            self.assertEqual(len(node.value), len(structure))
229            for key in node.value:
230                self.assert_(key.value in structure)
231                self.assertEqualStructure(node.value[key], structure[key.value])
232
233class TestValuesAndSources(unittest.TestCase, EqualStructure):
234
235    def testValues1(self):
236        self._testValues(COMPARE1)
237
238    def testValues2(self):
239        self._testValues(COMPARE2)
240
241    def testValues3(self):
242        self._testValues(COMPARE3)
243
244    def testFileValues1(self):
245        self._testFileValues(COMPARE1)
246
247    def testFileValues2(self):
248        self._testFileValues(COMPARE2)
249
250    def testFileValues3(self):
251        self._testFileValues(COMPARE3)
252
253    def testNonsense(self):
254        parser = _syck.Parser(None)
255        self.assertRaises(AttributeError, lambda: parser.parse())
256
257    def testCallMeNot(self):
258        class Source:
259            def __init__(self):
260                self.parser = None
261            def read(self, size=None):
262                if self.parser:
263                    self.parser.parse()
264                    return
265        source = Source()
266        parser = _syck.Parser(source)
267        source.parser = parser
268        self.assertRaises(RuntimeError, lambda: parser.parse())
269
270    def testAbsoluteHorror(self):
271        class Source:
272            def __init__(self):
273                self.parser = None
274            def read(self, size=None):
275                if self.parser:
276                    self.parser = None
277                return ''
278        source = Source()
279        parser = _syck.Parser(source)
280        source.parser = parser
281        del parser
282        self.assertEqual(None, source.parser.parse())
283
284    def _testValues(self, (source, structure)):
285        parser = _syck.Parser(source)
286        document = parser.parse()
287        self.assertEqualStructure(document, structure)
288
289    def _testFileValues(self, (source, structure)):
290        parser = _syck.Parser(StringIO.StringIO(source))
291        document = parser.parse()
292        self.assertEqualStructure(document, structure)
293
294class TestDocuments(unittest.TestCase):
295
296    def testDocuments0(self):
297        self._testDocuments(DOCUMENTS0, 0)
298
299    def testDocuments1(self):
300        self._testDocuments(DOCUMENTS1, 1)
301
302    def testDocuments2(self):
303        self._testDocuments(DOCUMENTS2, 2)
304
305    def testDocuments3(self):
306        self._testDocuments(DOCUMENTS3, 3)
307
308    def _testDocuments(self, source, length):
309        parser = _syck.Parser(source)
310        actual_length = 0
311        while True:
312            document = parser.parse()
313            if parser.eof:
314                self.assertEqual(document, None)
315                break
316            actual_length += 1
317        self.assertEqual(actual_length, length)
318        self.assertEqual(parser.parse(), None)
319        self.assert_(parser.eof)
320        self.assertEqual(parser.parse(), None)
321        self.assert_(parser.eof)
322        self.assert_(parser.eof)
323
324class TestImplicitTyping(unittest.TestCase):
325
326    def testImplicitAndExpansionTyping(self):
327        self._testTyping(True, True)
328
329    def testImplicitTyping(self):
330        self._testTyping(True, False)
331
332    def testExpansionTyping(self):
333        self._testTyping(False, True)
334
335    def testNoTyping(self):
336        self._testTyping(False, False)
337
338    def _testTyping(self, implicit_typing, taguri_expansion):
339        parser = _syck.Parser(IMPLICIT_TYPING[0], implicit_typing, taguri_expansion)
340        for node, (tag, explicit) in zip(parser.parse().value, IMPLICIT_TYPING[1]):
341            if tag is not None and taguri_expansion:
342                tag = 'tag:yaml.org,2002:%s' % tag
343            if implicit_typing or explicit:
344                self.assertEqual(node.tag, tag)
345            else:
346                self.assertEqual(node.tag, None)
347
348class TestExplicitTyping(unittest.TestCase):
349
350    def testExplicitTyping(self):
351        parser = _syck.Parser(EXPLICIT_TYPING[0])
352        for node, tag in zip(parser.parse().value, EXPLICIT_TYPING[1]):
353            self.assertEqual(node.tag, tag)
354
355class TestRecursive(unittest.TestCase):
356
357    def testRecursive(self):
358        parser = _syck.Parser(RECURSIVE)
359        self.assertRaises(TypeError, lambda: parser.parse())
360
Note: See TracBrowser for help on using the repository browser.