Apply [ 2051599 ] multi-page tables in latex writer (from pabigot).
[docutils.git] / test / test_nodes.py
blobff6aac940f7a824e4f60f5e6bc6010690fc8d27c
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
4 # $Id$
5 # Author: David Goodger <goodger@python.org>
6 # Copyright: This module has been placed in the public domain.
8 """
9 Test module for nodes.py.
10 """
12 import unittest
13 from types import ClassType
14 import DocutilsTestSupport # must be imported before docutils
15 from DocutilsTestSupport import nodes, utils
17 debug = 0
20 class TextTests(unittest.TestCase):
22 def setUp(self):
23 self.text = nodes.Text('Line 1.\nLine 2.')
24 self.unicode_text = nodes.Text(unicode('Möhren', 'utf8'))
26 def test_repr(self):
27 self.assertEquals(repr(self.text), r"<#text: 'Line 1.\nLine 2.'>")
29 def test_str(self):
30 self.assertEquals(str(self.text), 'Line 1.\nLine 2.')
32 def test_unicode(self):
33 self.assertEquals(unicode(self.unicode_text), unicode('Möhren', 'utf8'))
34 self.assertEquals(str(self.unicode_text), 'M\xf6hren')
36 def test_astext(self):
37 self.assertEquals(self.text.astext(), 'Line 1.\nLine 2.')
39 def test_pformat(self):
40 self.assertEquals(self.text.pformat(), 'Line 1.\nLine 2.\n')
42 def test_asciirestriction(self):
43 self.assertRaises(UnicodeError, nodes.Text, 'hol%s' % chr(224))
44 # more specifically: UnicodeDecodeError since py2.3
47 class ElementTests(unittest.TestCase):
49 def test_empty(self):
50 element = nodes.Element()
51 self.assertEquals(repr(element), '<Element: >')
52 self.assertEquals(str(element), '<Element/>')
53 dom = element.asdom()
54 self.assertEquals(dom.toxml(), '<Element/>')
55 dom.unlink()
56 element['attr'] = '1'
57 self.assertEquals(repr(element), '<Element: >')
58 self.assertEquals(str(element), '<Element attr="1"/>')
59 dom = element.asdom()
60 self.assertEquals(dom.toxml(), '<Element attr="1"/>')
61 dom.unlink()
62 self.assertEquals(element.pformat(), '<Element attr="1">\n')
63 del element['attr']
64 element['mark'] = u'\u2022'
65 self.assertEquals(repr(element), '<Element: >')
66 self.assertEquals(str(element), '<Element mark="\\u2022"/>')
67 dom = element.asdom()
68 self.assertEquals(dom.toxml(), u'<Element mark="\u2022"/>')
69 dom.unlink()
71 def test_withtext(self):
72 element = nodes.Element('text\nmore', nodes.Text('text\nmore'))
73 self.assertEquals(repr(element), r"<Element: <#text: 'text\nmore'>>")
74 self.assertEquals(str(element), '<Element>text\nmore</Element>')
75 dom = element.asdom()
76 self.assertEquals(dom.toxml(), '<Element>text\nmore</Element>')
77 dom.unlink()
78 element['attr'] = '1'
79 self.assertEquals(repr(element), r"<Element: <#text: 'text\nmore'>>")
80 self.assertEquals(str(element),
81 '<Element attr="1">text\nmore</Element>')
82 dom = element.asdom()
83 self.assertEquals(dom.toxml(),
84 '<Element attr="1">text\nmore</Element>')
85 dom.unlink()
86 self.assertEquals(element.pformat(),
87 '<Element attr="1">\n text\n more\n')
89 def test_clear(self):
90 element = nodes.Element()
91 element += nodes.Element()
92 self.assert_(len(element))
93 element.clear()
94 self.assert_(not len(element))
96 def test_normal_attributes(self):
97 element = nodes.Element()
98 self.assert_('foo' not in element)
99 self.assertRaises(KeyError, element.__getitem__, 'foo')
100 element['foo'] = 'sometext'
101 self.assertEquals(element['foo'], 'sometext')
102 del element['foo']
103 self.assertRaises(KeyError, element.__getitem__, 'foo')
105 def test_default_attributes(self):
106 element = nodes.Element()
107 self.assertEquals(element['ids'], [])
108 self.assertEquals(element.non_default_attributes(), {})
109 self.assert_(not element.is_not_default('ids'))
110 self.assert_(element['ids'] is not nodes.Element()['ids'])
111 element['ids'].append('someid')
112 self.assertEquals(element['ids'], ['someid'])
113 self.assertEquals(element.non_default_attributes(),
114 {'ids': ['someid']})
115 self.assert_(element.is_not_default('ids'))
117 def test_update_basic_atts(self):
118 element1 = nodes.Element(ids=['foo', 'bar'], test=['test1'])
119 element2 = nodes.Element(ids=['baz', 'qux'], test=['test2'])
120 element1.update_basic_atts(element2)
121 # 'ids' are appended because 'ids' is a basic attribute.
122 self.assertEquals(element1['ids'], ['foo', 'bar', 'baz', 'qux'])
123 # 'test' is not overwritten because it is not a basic attribute.
124 self.assertEquals(element1['test'], ['test1'])
126 def test_replace_self(self):
127 parent = nodes.Element(ids=['parent'])
128 child1 = nodes.Element(ids=['child1'])
129 grandchild = nodes.Element(ids=['grandchild'])
130 child1 += grandchild
131 child2 = nodes.Element(ids=['child2'])
132 twins = [nodes.Element(ids=['twin%s' % i]) for i in (1, 2)]
133 child2 += twins
134 child3 = nodes.Element(ids=['child3'])
135 child4 = nodes.Element(ids=['child4'])
136 parent += [child1, child2, child3, child4]
137 self.assertEquals(parent.pformat(), """\
138 <Element ids="parent">
139 <Element ids="child1">
140 <Element ids="grandchild">
141 <Element ids="child2">
142 <Element ids="twin1">
143 <Element ids="twin2">
144 <Element ids="child3">
145 <Element ids="child4">
146 """)
147 # Replace child1 with the grandchild.
148 child1.replace_self(child1[0])
149 self.assertEquals(parent[0], grandchild)
150 # Assert that 'ids' have been updated.
151 self.assertEquals(grandchild['ids'], ['grandchild', 'child1'])
152 # Replace child2 with its children.
153 child2.replace_self(child2[:])
154 self.assertEquals(parent[1:3], twins)
155 # Assert that 'ids' have been propagated to first child.
156 self.assertEquals(twins[0]['ids'], ['twin1', 'child2'])
157 self.assertEquals(twins[1]['ids'], ['twin2'])
158 # Replace child3 with new child.
159 newchild = nodes.Element(ids=['newchild'])
160 child3.replace_self(newchild)
161 self.assertEquals(parent[3], newchild)
162 self.assertEquals(newchild['ids'], ['newchild', 'child3'])
163 # Crazy but possible case: Substitute child4 for itself.
164 child4.replace_self(child4)
165 # Make sure the 'child4' ID hasn't been duplicated.
166 self.assertEquals(child4['ids'], ['child4'])
167 self.assertEquals(len(parent), 5)
169 def test_unicode(self):
170 node = nodes.Element(u'Möhren', nodes.Text(unicode('Möhren', 'utf8'),
171 unicode('Möhren', 'utf8')))
172 self.assertEquals(unicode(node), unicode('<Element>Möhren</Element>',
173 'utf8'))
176 class MiscTests(unittest.TestCase):
178 def test_node_class_names(self):
179 node_class_names = []
180 for x in dir(nodes):
181 c = getattr(nodes, x)
182 if isinstance(c, (type, ClassType)) and issubclass(c, nodes.Node) \
183 and len(c.__bases__) > 1:
184 node_class_names.append(x)
185 node_class_names.sort()
186 nodes.node_class_names.sort()
187 self.assertEquals(node_class_names, nodes.node_class_names)
189 ids = [('a', 'a'), ('A', 'a'), ('', ''), ('a b \n c', 'a-b-c'),
190 ('a.b.c', 'a-b-c'), (' - a - b - c - ', 'a-b-c'), (' - ', ''),
191 (u'\u2020\u2066', ''), (u'a \xa7 b \u2020 c', 'a-b-c'),
192 ('1', ''), ('1abc', 'abc')]
194 def test_make_id(self):
195 for input, output in self.ids:
196 normed = nodes.make_id(input)
197 self.assertEquals(normed, output)
199 def test_traverse(self):
200 e = nodes.Element()
201 e += nodes.Element()
202 e[0] += nodes.Element()
203 e[0] += nodes.TextElement()
204 e[0][1] += nodes.Text('some text')
205 e += nodes.Element()
206 e += nodes.Element()
207 self.assertEquals(list(e.traverse()),
208 [e, e[0], e[0][0], e[0][1], e[0][1][0], e[1], e[2]])
209 self.assertEquals(list(e.traverse(include_self=0)),
210 [e[0], e[0][0], e[0][1], e[0][1][0], e[1], e[2]])
211 self.assertEquals(list(e.traverse(descend=0)),
212 [e])
213 self.assertEquals(list(e[0].traverse(descend=0, ascend=1)),
214 [e[0], e[1], e[2]])
215 self.assertEquals(list(e[0][0].traverse(descend=0, ascend=1)),
216 [e[0][0], e[0][1], e[1], e[2]])
217 self.assertEquals(list(e[0][0].traverse(descend=0, siblings=1)),
218 [e[0][0], e[0][1]])
219 self.testlist = e[0:2]
220 self.assertEquals(list(e.traverse(condition=self.not_in_testlist)),
221 [e, e[0][0], e[0][1], e[0][1][0], e[2]])
222 # Return siblings despite siblings=0 because ascend is true.
223 self.assertEquals(list(e[1].traverse(ascend=1, siblings=0)),
224 [e[1], e[2]])
225 self.assertEquals(list(e[0].traverse()),
226 [e[0], e[0][0], e[0][1], e[0][1][0]])
227 self.testlist = [e[0][0], e[0][1]]
228 self.assertEquals(list(e[0].traverse(condition=self.not_in_testlist)),
229 [e[0], e[0][1][0]])
230 self.testlist.append(e[0][1][0])
231 self.assertEquals(list(e[0].traverse(condition=self.not_in_testlist)),
232 [e[0]])
233 self.assertEquals(list(e.traverse(nodes.TextElement)), [e[0][1]])
235 def test_next_node(self):
236 e = nodes.Element()
237 e += nodes.Element()
238 e[0] += nodes.Element()
239 e[0] += nodes.TextElement()
240 e[0][1] += nodes.Text('some text')
241 e += nodes.Element()
242 e += nodes.Element()
243 self.testlist = [e[0], e[0][1], e[1]]
244 compare = [(e, e[0][0]),
245 (e[0], e[0][0]),
246 (e[0][0], e[0][1][0]),
247 (e[0][1], e[0][1][0]),
248 (e[0][1][0], e[2]),
249 (e[1], e[2]),
250 (e[2], None)]
251 for node, next_node in compare:
252 self.assertEquals(node.next_node(self.not_in_testlist, ascend=1),
253 next_node)
254 self.assertEquals(e[0][0].next_node(ascend=1), e[0][1])
255 self.assertEquals(e[2].next_node(), None)
257 def not_in_testlist(self, x):
258 return x not in self.testlist
260 def test_copy(self):
261 grandchild = nodes.Text('rawsource')
262 child = nodes.emphasis('rawsource', grandchild, att='child')
263 e = nodes.Element('rawsource', child, att='e')
264 # Shallow copy:
265 e_copy = e.copy()
266 self.assert_(e is not e_copy)
267 # Internal attributes (like `rawsource`) are not copied.
268 self.assertEquals(e.rawsource, 'rawsource')
269 self.assertEquals(e_copy.rawsource, '')
270 self.assertEquals(e_copy['att'], 'e')
271 # Children are not copied.
272 self.assertEquals(len(e_copy), 0)
273 # Deep copy:
274 e_deepcopy = e.deepcopy()
275 self.assertEquals(e_deepcopy.rawsource, '')
276 self.assertEquals(e_deepcopy['att'], 'e')
277 # Children are copied recursively.
278 self.assertEquals(e_deepcopy[0][0], grandchild)
279 self.assert_(e_deepcopy[0][0] is not grandchild)
280 self.assertEquals(e_deepcopy[0]['att'], 'child')
283 class TreeCopyVisitorTests(unittest.TestCase):
285 def setUp(self):
286 document = utils.new_document('test data')
287 document += nodes.paragraph('', 'Paragraph 1.')
288 blist = nodes.bullet_list()
289 for i in range(1, 6):
290 item = nodes.list_item()
291 for j in range(1, 4):
292 item += nodes.paragraph('', 'Item %s, paragraph %s.' % (i, j))
293 blist += item
294 document += blist
295 self.document = document
297 def compare_trees(self, one, two):
298 self.assertEquals(one.__class__, two.__class__)
299 self.assertNotEquals(id(one), id(two))
300 self.assertEquals(len(one.children), len(two.children))
301 for i in range(len(one.children)):
302 self.compare_trees(one.children[i], two.children[i])
304 def test_copy_whole(self):
305 visitor = nodes.TreeCopyVisitor(self.document)
306 self.document.walkabout(visitor)
307 newtree = visitor.get_tree_copy()
308 self.assertEquals(self.document.pformat(), newtree.pformat())
309 self.compare_trees(self.document, newtree)
312 class MiscFunctionTests(unittest.TestCase):
314 names = [('a', 'a'), ('A', 'a'), ('A a A', 'a a a'),
315 ('A a A a', 'a a a a'),
316 (' AaA\n\r\naAa\tAaA\t\t', 'aaa aaa aaa')]
318 def test_normalize_name(self):
319 for input, output in self.names:
320 normed = nodes.fully_normalize_name(input)
321 self.assertEquals(normed, output)
323 def test_set_id_default(self):
324 # Default prefixes.
325 document = utils.new_document('test')
326 # From name.
327 element = nodes.Element(names=['test'])
328 document.set_id(element)
329 self.assertEquals(element['ids'], ['test'])
330 # Auto-generated.
331 element = nodes.Element()
332 document.set_id(element)
333 self.assertEquals(element['ids'], ['id1'])
335 def test_set_id_custom(self):
336 # Custom prefixes.
337 document = utils.new_document('test')
338 # Change settings.
339 document.settings.id_prefix = 'prefix'
340 document.settings.auto_id_prefix = 'auto'
341 # From name.
342 element = nodes.Element(names=['test'])
343 document.set_id(element)
344 self.assertEquals(element['ids'], ['prefixtest'])
345 # Auto-generated.
346 element = nodes.Element()
347 document.set_id(element)
348 self.assertEquals(element['ids'], ['prefixauto1'])
351 if __name__ == '__main__':
352 unittest.main()