root/cly/trunk/cly/test.py

Revision 579, 6.9 kB (checked in by athomas, 1 month ago)

Automatically cull candidates by default. This can be disabled with cull_candidates=False.

  • Property svn:eol-style set to native
Line 
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2006-2007 Alec Thomas <alec@swapoff.org>
4 #
5 # This software is licensed as described in the file COPYING, which
6 # you should have received as part of this distribution.
7 #
8
9 import unittest
10 import doctest
11 from StringIO import StringIO
12 from cly.exceptions import InvalidToken
13 from cly import Defaults, Node, XMLGrammar, Parser
14
15
16 class TestXMLGrammar(unittest.TestCase):
17     """Test XML grammar parser."""
18     def setUp(self):
19         self._output = None
20
21     def _echo(self, *args, **kwargs):
22         self._output = (args, kwargs)
23
24     def test_basic(self):
25         xml = StringIO("""<?xml version="1.0"?>
26         <grammar>
27             <node name='echo'>
28                 <variable name='text'>
29                     <action callback='echo(text)'/>
30                 </variable>
31             </node>
32         </grammar>
33         """)
34
35         grammar = XMLGrammar(xml)
36         parser = Parser(grammar, data={'echo': self._echo})
37         parser.execute('echo magic')
38         self.assertEqual(self._output, (('magic',), {}))
39
40     def test_multiple_traversals(self):
41         xml = StringIO("""<?xml version="1.0"?>
42         <grammar>
43             <node name='echo'>
44                 <variable name='text' traversals='0'>
45                     <alias target='/echo/*'/>
46                     <action callback='echo(text)'/>
47                 </variable>
48             </node>
49         </grammar>
50         """)
51
52         grammar = XMLGrammar(xml)
53         parser = Parser(grammar, {'echo': self._echo})
54         parser.execute('echo magic monkey')
55         self.assertEqual(self._output, ((['magic', 'monkey'],), {}))
56
57     def test_group(self):
58         xml = StringIO("""<?xml version="1.0"?>
59         <grammar>
60             <node name='echo'>
61                 <variable traversals='0' name='text'>
62                     <alias target='../../*'/>
63                     <action callback='echo(text)'/>
64                 </variable>
65             </node>
66         </grammar>
67         """)
68
69         grammar = XMLGrammar(xml)
70         parser = Parser(grammar, data={'echo': self._echo})
71         parser.execute('echo magic monkey')
72         self.assertEqual(self._output, ((['magic', 'monkey'],), {}))
73
74     def test_completion(self):
75         xml = StringIO("""<?xml version="1.0"?>
76         <grammar>
77             <node name="echo">
78                 <variable name="text" candidates="['monkey', 'muppet']">
79                     <action callback="echo(text)"/>
80                 </variable>
81             </node>
82         </grammar>
83         """)
84
85         def candidates(context, text):
86             return ['monkey', 'muppet']
87
88         grammar = XMLGrammar(xml)
89         parser = Parser(grammar, data={'echo': self._echo})
90         context = parser.parse('echo ')
91         self.assertEqual(list(context.candidates()), ['monkey ', 'muppet '])
92
93     def test_node_extension(self):
94         from cly.builder import Variable
95
96
97         class ABC(Variable):
98             pattern = r'(?i)[abc]+'
99
100
101         xml = StringIO("""<?xml version="1.0"?>
102         <grammar>
103             <node name='echo'>
104                 <abc name='text'>
105                     <action callback='echo(text)'/>
106                 </abc>
107             </node>
108         </grammar>
109         """)
110
111         grammar = XMLGrammar(xml, extra_nodes=[ABC])
112         parser = Parser(grammar, data={'echo': self._echo})
113         parser.execute('echo abaabbccc')
114         self.assertEqual(self._output, (('abaabbccc',), {}))
115         def invalid_token():
116             parser.execute('echo asdf')
117         self.assertRaises(InvalidToken, invalid_token)
118
119     def test_lazy_evaluation(self):
120         class Lazy(object): pass
121         lazy = Lazy()
122
123         xml = StringIO("""<?xml version="1.0"?>
124         <grammar>
125             <node name='echo'>
126                 <variable name='text'>
127                     <action callback='a_local and lazy.echo(text)'/>
128                 </variable>
129             </node>
130         </grammar>
131         """)
132
133         grammar = XMLGrammar(xml)
134         parser = Parser(grammar, data={
135             'echo': self._echo,
136             'lazy': lazy,
137             'a_local': True,
138             })
139         lazy.echo = self._echo
140         parser.execute('echo abaabbccc')
141         self.assertEqual(self._output, (('abaabbccc',), {}))
142
143     def test_attribute_aliases(self):
144         xml = StringIO("""<?xml version="1.0"?>
145         <grammar>
146             <node if="echo_allowed" name='echo'>
147                 <variable name='text'>
148                     <action exec='echo(text)'/>
149                 </variable>
150             </node>
151         </grammar>
152         """)
153
154         grammar = XMLGrammar(xml)
155         parser = Parser(grammar, data={
156             'echo': self._echo,
157             'echo_allowed': True,
158             })
159         parser.execute('echo hello')
160         self.assertEqual(self._output, (('hello',), {}))
161
162     def test_cast_attribute(self):
163         class Test(Node):
164             @classmethod
165             def cast_attribute(cls, namespace, name, value):
166                 if name == 'test':
167                     return int(value), {}
168                 return value, {}
169
170         xml = StringIO("""<?xml version="1.0"?>
171         <grammar>
172             <test test="10" name="test">
173             </test>
174         </grammar>
175         """)
176         grammar = XMLGrammar(xml, extra_nodes=[Test])
177         self.assertTrue(isinstance(grammar.find('/test').test, int))
178
179     def test_attribute_aliases(self):
180         class Parent(Node):
181             @classmethod
182             def attribute_aliases(cls):
183                 return {'foo': 'bar'}
184
185         class Test(Parent):
186             @classmethod
187             def attribute_aliases(cls):
188                 return {'baz': 'waz'}
189
190         xml = StringIO("""<?xml version="1.0"?>
191         <grammar>
192             <test baz="10" foo="20" name="test">
193             </test>
194         </grammar>
195         """)
196         grammar = XMLGrammar(xml, extra_nodes=[Test])
197         node = grammar.find('/test')
198         self.assertTrue(node.bar, '10')
199         self.assertTrue(node.waz, '20')
200
201     def test_set_cast(self):
202         xml = StringIO("""<?xml version="1.0"?>
203         <grammar>
204             <defaults baz="10" foo="20" waz="'waz'">
205                 <node name="test"></node>
206             </defaults>
207         </grammar>
208         """)
209         parser = Parser(XMLGrammar(xml))
210         self.assertEqual(parser.parse('test').vars,
211                          {'foo': 20, 'baz': 10, 'waz': 'waz'})
212
213 def suite():
214     import cly
215     import cly.interactive
216     import cly.console
217     import cly.parser
218     import cly.builder
219     import cly.exceptions
220
221     suite = unittest.TestSuite()
222     suite.addTest(unittest.makeSuite(TestXMLGrammar, 'test'))
223     suite.addTest(doctest.DocTestSuite(cly))
224     suite.addTest(doctest.DocTestSuite(cly.interactive))
225     suite.addTest(doctest.DocTestSuite(cly.console))
226     suite.addTest(doctest.DocTestSuite(cly.parser))
227     suite.addTest(doctest.DocTestSuite(cly.builder))
228     suite.addTest(doctest.DocTestSuite(cly.exceptions))
229
230     return suite
231
232
233 if __name__ == '__main__':
234     unittest.main(defaultTest='suite')
Note: See TracBrowser for help on using the browser.