Drop support for Python 2.3.
[docutils.git] / test / test_nodes.py
blobef423b4c484b2c8cc1b2f178e93326f5f0feb7d0
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 sys
13 import unittest
14 import types
15 import DocutilsTestSupport # must be imported before docutils
16 from DocutilsTestSupport import nodes, utils
17 from docutils._compat import b
19 debug = False
22 class TextTests(unittest.TestCase):
24 def setUp(self):
25 self.text = nodes.Text('Line 1.\nLine 2.')
26 self.unicode_text = nodes.Text(u'Möhren')
27 self.longtext = nodes.Text('Mary had a little lamb whose '
28 'fleece was white as snow and '
29 'everwhere that Mary went the '
30 'lamb was sure to go.')
32 def test_repr(self):
33 self.assertEqual(repr(self.text), r"<#text: 'Line 1.\nLine 2.'>")
34 self.assertEqual(self.text.shortrepr(),
35 r"<#text: 'Line 1.\nLine 2.'>")
37 def test_str(self):
38 self.assertEqual(str(self.text), 'Line 1.\nLine 2.')
40 def test_unicode(self):
41 self.assertEqual(unicode(self.unicode_text), u'Möhren')
42 self.assertEqual(str(self.unicode_text), 'M\xf6hren')
44 def test_astext(self):
45 self.assertEqual(self.text.astext(), 'Line 1.\nLine 2.')
47 def test_pformat(self):
48 self.assertEqual(self.text.pformat(), 'Line 1.\nLine 2.\n')
50 def test_asciirestriction(self):
51 if sys.version_info < (3,):
52 self.assertRaises(UnicodeDecodeError, nodes.Text,
53 b('hol%s' % chr(224)))
54 else:
55 # no bytes at all allowed
56 self.assertRaises(TypeError, nodes.Text, b('hol'))
58 def test_longrepr(self):
59 self.assertEqual(repr(self.longtext), r"<#text: 'Mary had a "
60 r"little lamb whose fleece was white as snow "
61 r"and everwh ...'>")
62 self.assertEqual(self.longtext.shortrepr(),
63 r"<#text: 'Mary had a lit ...'>")
65 class ElementTests(unittest.TestCase):
67 def test_empty(self):
68 element = nodes.Element()
69 self.assertEqual(repr(element), '<Element: >')
70 self.assertEqual(str(element), '<Element/>')
71 dom = element.asdom()
72 self.assertEqual(dom.toxml(), '<Element/>')
73 dom.unlink()
74 element['attr'] = '1'
75 self.assertEqual(repr(element), '<Element: >')
76 self.assertEqual(str(element), '<Element attr="1"/>')
77 dom = element.asdom()
78 self.assertEqual(dom.toxml(), '<Element attr="1"/>')
79 dom.unlink()
80 self.assertEqual(element.pformat(), '<Element attr="1">\n')
81 del element['attr']
82 element['mark'] = u'\u2022'
83 self.assertEqual(repr(element), '<Element: >')
84 if sys.version_info < (3,):
85 self.assertEqual(str(element), '<Element mark="\\u2022"/>')
86 else:
87 self.assertEqual(str(element), '<Element mark="\u2022"/>')
88 dom = element.asdom()
89 self.assertEqual(dom.toxml(), u'<Element mark="\u2022"/>')
90 dom.unlink()
92 def test_withtext(self):
93 element = nodes.Element('text\nmore', nodes.Text('text\nmore'))
94 self.assertEqual(repr(element), r"<Element: <#text: 'text\nmore'>>")
95 self.assertEqual(str(element), '<Element>text\nmore</Element>')
96 dom = element.asdom()
97 self.assertEqual(dom.toxml(), '<Element>text\nmore</Element>')
98 dom.unlink()
99 element['attr'] = '1'
100 self.assertEqual(repr(element), r"<Element: <#text: 'text\nmore'>>")
101 self.assertEqual(str(element),
102 '<Element attr="1">text\nmore</Element>')
103 dom = element.asdom()
104 self.assertEqual(dom.toxml(),
105 '<Element attr="1">text\nmore</Element>')
106 dom.unlink()
107 self.assertEqual(element.pformat(),
108 '<Element attr="1">\n text\n more\n')
110 def test_clear(self):
111 element = nodes.Element()
112 element += nodes.Element()
113 self.assertTrue(len(element))
114 element.clear()
115 self.assertTrue(not len(element))
117 def test_normal_attributes(self):
118 element = nodes.Element()
119 self.assertTrue('foo' not in element)
120 self.assertRaises(KeyError, element.__getitem__, 'foo')
121 element['foo'] = 'sometext'
122 self.assertEqual(element['foo'], 'sometext')
123 del element['foo']
124 self.assertRaises(KeyError, element.__getitem__, 'foo')
126 def test_default_attributes(self):
127 element = nodes.Element()
128 self.assertEqual(element['ids'], [])
129 self.assertEqual(element.non_default_attributes(), {})
130 self.assertTrue(not element.is_not_default('ids'))
131 self.assertTrue(element['ids'] is not nodes.Element()['ids'])
132 element['ids'].append('someid')
133 self.assertEqual(element['ids'], ['someid'])
134 self.assertEqual(element.non_default_attributes(),
135 {'ids': ['someid']})
136 self.assertTrue(element.is_not_default('ids'))
138 def test_update_basic_atts(self):
139 element1 = nodes.Element(ids=['foo', 'bar'], test=['test1'])
140 element2 = nodes.Element(ids=['baz', 'qux'], test=['test2'])
141 element1.update_basic_atts(element2)
142 # 'ids' are appended because 'ids' is a basic attribute.
143 self.assertEqual(element1['ids'], ['foo', 'bar', 'baz', 'qux'])
144 # 'test' is not overwritten because it is not a basic attribute.
145 self.assertEqual(element1['test'], ['test1'])
147 def test_replace_self(self):
148 parent = nodes.Element(ids=['parent'])
149 child1 = nodes.Element(ids=['child1'])
150 grandchild = nodes.Element(ids=['grandchild'])
151 child1 += grandchild
152 child2 = nodes.Element(ids=['child2'])
153 twins = [nodes.Element(ids=['twin%s' % i]) for i in (1, 2)]
154 child2 += twins
155 child3 = nodes.Element(ids=['child3'])
156 child4 = nodes.Element(ids=['child4'])
157 parent += [child1, child2, child3, child4]
158 self.assertEqual(parent.pformat(), """\
159 <Element ids="parent">
160 <Element ids="child1">
161 <Element ids="grandchild">
162 <Element ids="child2">
163 <Element ids="twin1">
164 <Element ids="twin2">
165 <Element ids="child3">
166 <Element ids="child4">
167 """)
168 # Replace child1 with the grandchild.
169 child1.replace_self(child1[0])
170 self.assertEqual(parent[0], grandchild)
171 # Assert that 'ids' have been updated.
172 self.assertEqual(grandchild['ids'], ['grandchild', 'child1'])
173 # Replace child2 with its children.
174 child2.replace_self(child2[:])
175 self.assertEqual(parent[1:3], twins)
176 # Assert that 'ids' have been propagated to first child.
177 self.assertEqual(twins[0]['ids'], ['twin1', 'child2'])
178 self.assertEqual(twins[1]['ids'], ['twin2'])
179 # Replace child3 with new child.
180 newchild = nodes.Element(ids=['newchild'])
181 child3.replace_self(newchild)
182 self.assertEqual(parent[3], newchild)
183 self.assertEqual(newchild['ids'], ['newchild', 'child3'])
184 # Crazy but possible case: Substitute child4 for itself.
185 child4.replace_self(child4)
186 # Make sure the 'child4' ID hasn't been duplicated.
187 self.assertEqual(child4['ids'], ['child4'])
188 self.assertEqual(len(parent), 5)
190 def test_unicode(self):
191 node = nodes.Element(u'Möhren', nodes.Text(u'Möhren', u'Möhren'))
192 self.assertEqual(unicode(node), u'<Element>Möhren</Element>')
195 class MiscTests(unittest.TestCase):
197 def test_node_class_names(self):
198 node_class_names = []
199 for x in dir(nodes):
200 c = getattr(nodes, x)
201 if isinstance(c, (type, types.ClassType)) and \
202 issubclass(c, nodes.Node) and len(c.__bases__) > 1:
203 node_class_names.append(x)
204 node_class_names.sort()
205 nodes.node_class_names.sort()
206 self.assertEqual(node_class_names, nodes.node_class_names)
208 ids = [(u'a', 'a'), ('A', 'a'), ('', ''), ('a b \n c', 'a-b-c'),
209 ('a.b.c', 'a-b-c'), (' - a - b - c - ', 'a-b-c'), (' - ', ''),
210 (u'\u2020\u2066', ''), (u'a \xa7 b \u2020 c', 'a-b-c'),
211 ('1', ''), ('1abc', 'abc'),
213 ids_unicode_all = [
214 (u'\u00f8 o with stroke', 'o-o-with-stroke'),
215 (u'\u0111 d with stroke', 'd-d-with-stroke'),
216 (u'\u0127 h with stroke', 'h-h-with-stroke'),
217 (u'\u0131 dotless i', 'i-dotless-i'),
218 (u'\u0142 l with stroke', 'l-l-with-stroke'),
219 (u'\u0167 t with stroke', 't-t-with-stroke'),
220 # From Latin Extended-B
221 (u'\u0180 b with stroke', 'b-b-with-stroke'),
222 (u'\u0183 b with topbar', 'b-b-with-topbar'),
223 (u'\u0188 c with hook', 'c-c-with-hook'),
224 (u'\u018c d with topbar', 'd-d-with-topbar'),
225 (u'\u0192 f with hook', 'f-f-with-hook'),
226 (u'\u0199 k with hook', 'k-k-with-hook'),
227 (u'\u019a l with bar', 'l-l-with-bar'),
228 (u'\u019e n with long right leg', 'n-n-with-long-right-leg'),
229 (u'\u01a5 p with hook', 'p-p-with-hook'),
230 (u'\u01ab t with palatal hook', 't-t-with-palatal-hook'),
231 (u'\u01ad t with hook', 't-t-with-hook'),
232 (u'\u01b4 y with hook', 'y-y-with-hook'),
233 (u'\u01b6 z with stroke', 'z-z-with-stroke'),
234 (u'\u01e5 g with stroke', 'g-g-with-stroke'),
235 (u'\u0225 z with hook', 'z-z-with-hook'),
236 (u'\u0234 l with curl', 'l-l-with-curl'),
237 (u'\u0235 n with curl', 'n-n-with-curl'),
238 (u'\u0236 t with curl', 't-t-with-curl'),
239 (u'\u0237 dotless j', 'j-dotless-j'),
240 (u'\u023c c with stroke', 'c-c-with-stroke'),
241 (u'\u023f s with swash tail', 's-s-with-swash-tail'),
242 (u'\u0240 z with swash tail', 'z-z-with-swash-tail'),
243 (u'\u0247 e with stroke', 'e-e-with-stroke'),
244 (u'\u0249 j with stroke', 'j-j-with-stroke'),
245 (u'\u024b q with hook tail', 'q-q-with-hook-tail'),
246 (u'\u024d r with stroke', 'r-r-with-stroke'),
247 (u'\u024f y with stroke', 'y-y-with-stroke'),
248 # From Latin-1 Supplements
249 (u'\u00e0: a with grave', 'a-a-with-grave'),
250 (u'\u00e1 a with acute', 'a-a-with-acute'),
251 (u'\u00e2 a with circumflex', 'a-a-with-circumflex'),
252 (u'\u00e3 a with tilde', 'a-a-with-tilde'),
253 (u'\u00e4 a with diaeresis', 'a-a-with-diaeresis'),
254 (u'\u00e5 a with ring above', 'a-a-with-ring-above'),
255 (u'\u00e7 c with cedilla', 'c-c-with-cedilla'),
256 (u'\u00e8 e with grave', 'e-e-with-grave'),
257 (u'\u00e9 e with acute', 'e-e-with-acute'),
258 (u'\u00ea e with circumflex', 'e-e-with-circumflex'),
259 (u'\u00eb e with diaeresis', 'e-e-with-diaeresis'),
260 (u'\u00ec i with grave', 'i-i-with-grave'),
261 (u'\u00ed i with acute', 'i-i-with-acute'),
262 (u'\u00ee i with circumflex', 'i-i-with-circumflex'),
263 (u'\u00ef i with diaeresis', 'i-i-with-diaeresis'),
264 (u'\u00f1 n with tilde', 'n-n-with-tilde'),
265 (u'\u00f2 o with grave', 'o-o-with-grave'),
266 (u'\u00f3 o with acute', 'o-o-with-acute'),
267 (u'\u00f4 o with circumflex', 'o-o-with-circumflex'),
268 (u'\u00f5 o with tilde', 'o-o-with-tilde'),
269 (u'\u00f6 o with diaeresis', 'o-o-with-diaeresis'),
270 (u'\u00f9 u with grave', 'u-u-with-grave'),
271 (u'\u00fa u with acute', 'u-u-with-acute'),
272 (u'\u00fb u with circumflex', 'u-u-with-circumflex'),
273 (u'\u00fc u with diaeresis', 'u-u-with-diaeresis'),
274 (u'\u00fd y with acute', 'y-y-with-acute'),
275 (u'\u00ff y with diaeresis', 'y-y-with-diaeresis'),
276 # From Latin Extended-A
277 (u'\u0101 a with macron', 'a-a-with-macron'),
278 (u'\u0103 a with breve', 'a-a-with-breve'),
279 (u'\u0105 a with ogonek', 'a-a-with-ogonek'),
280 (u'\u0107 c with acute', 'c-c-with-acute'),
281 (u'\u0109 c with circumflex', 'c-c-with-circumflex'),
282 (u'\u010b c with dot above', 'c-c-with-dot-above'),
283 (u'\u010d c with caron', 'c-c-with-caron'),
284 (u'\u010f d with caron', 'd-d-with-caron'),
285 (u'\u0113 e with macron', 'e-e-with-macron'),
286 (u'\u0115 e with breve', 'e-e-with-breve'),
287 (u'\u0117 e with dot above', 'e-e-with-dot-above'),
288 (u'\u0119 e with ogonek', 'e-e-with-ogonek'),
289 (u'\u011b e with caron', 'e-e-with-caron'),
290 (u'\u011d g with circumflex', 'g-g-with-circumflex'),
291 (u'\u011f g with breve', 'g-g-with-breve'),
292 (u'\u0121 g with dot above', 'g-g-with-dot-above'),
293 (u'\u0123 g with cedilla', 'g-g-with-cedilla'),
294 (u'\u0125 h with circumflex', 'h-h-with-circumflex'),
295 (u'\u0129 i with tilde', 'i-i-with-tilde'),
296 (u'\u012b i with macron', 'i-i-with-macron'),
297 (u'\u012d i with breve', 'i-i-with-breve'),
298 (u'\u012f i with ogonek', 'i-i-with-ogonek'),
299 (u'\u0133 ligature ij', 'ij-ligature-ij'),
300 (u'\u0135 j with circumflex', 'j-j-with-circumflex'),
301 (u'\u0137 k with cedilla', 'k-k-with-cedilla'),
302 (u'\u013a l with acute', 'l-l-with-acute'),
303 (u'\u013c l with cedilla', 'l-l-with-cedilla'),
304 (u'\u013e l with caron', 'l-l-with-caron'),
305 (u'\u0140 l with middle dot', 'l-l-with-middle-dot'),
306 (u'\u0144 n with acute', 'n-n-with-acute'),
307 (u'\u0146 n with cedilla', 'n-n-with-cedilla'),
308 (u'\u0148 n with caron', 'n-n-with-caron'),
309 (u'\u014d o with macron', 'o-o-with-macron'),
310 (u'\u014f o with breve', 'o-o-with-breve'),
311 (u'\u0151 o with double acute', 'o-o-with-double-acute'),
312 (u'\u0155 r with acute', 'r-r-with-acute'),
313 (u'\u0157 r with cedilla', 'r-r-with-cedilla'),
314 (u'\u0159 r with caron', 'r-r-with-caron'),
315 (u'\u015b s with acute', 's-s-with-acute'),
316 (u'\u015d s with circumflex', 's-s-with-circumflex'),
317 (u'\u015f s with cedilla', 's-s-with-cedilla'),
318 (u'\u0161 s with caron', 's-s-with-caron'),
319 (u'\u0163 t with cedilla', 't-t-with-cedilla'),
320 (u'\u0165 t with caron', 't-t-with-caron'),
321 (u'\u0169 u with tilde', 'u-u-with-tilde'),
322 (u'\u016b u with macron', 'u-u-with-macron'),
323 (u'\u016d u with breve', 'u-u-with-breve'),
324 (u'\u016f u with ring above', 'u-u-with-ring-above'),
325 (u'\u0171 u with double acute', 'u-u-with-double-acute'),
326 (u'\u0173 u with ogonek', 'u-u-with-ogonek'),
327 (u'\u0175 w with circumflex', 'w-w-with-circumflex'),
328 (u'\u0177 y with circumflex', 'y-y-with-circumflex'),
329 (u'\u017a z with acute', 'z-z-with-acute'),
330 (u'\u017c z with dot above', 'z-z-with-dot-above'),
331 (u'\u017e z with caron', 'z-z-with-caron'),
332 # From Latin Extended-B
333 (u'\u01a1 o with horn', 'o-o-with-horn'),
334 (u'\u01b0 u with horn', 'u-u-with-horn'),
335 (u'\u01c6 dz with caron', 'dz-dz-with-caron'),
336 (u'\u01c9 lj', 'lj-lj'),
337 (u'\u01cc nj', 'nj-nj'),
338 (u'\u01ce a with caron', 'a-a-with-caron'),
339 (u'\u01d0 i with caron', 'i-i-with-caron'),
340 (u'\u01d2 o with caron', 'o-o-with-caron'),
341 (u'\u01d4 u with caron', 'u-u-with-caron'),
342 (u'\u01e7 g with caron', 'g-g-with-caron'),
343 (u'\u01e9 k with caron', 'k-k-with-caron'),
344 (u'\u01eb o with ogonek', 'o-o-with-ogonek'),
345 (u'\u01ed o with ogonek and macron', 'o-o-with-ogonek-and-macron'),
346 (u'\u01f0 j with caron', 'j-j-with-caron'),
347 (u'\u01f3 dz', 'dz-dz'),
348 (u'\u01f5 g with acute', 'g-g-with-acute'),
349 (u'\u01f9 n with grave', 'n-n-with-grave'),
350 (u'\u0201 a with double grave', 'a-a-with-double-grave'),
351 (u'\u0203 a with inverted breve', 'a-a-with-inverted-breve'),
352 (u'\u0205 e with double grave', 'e-e-with-double-grave'),
353 (u'\u0207 e with inverted breve', 'e-e-with-inverted-breve'),
354 (u'\u0209 i with double grave', 'i-i-with-double-grave'),
355 (u'\u020b i with inverted breve', 'i-i-with-inverted-breve'),
356 (u'\u020d o with double grave', 'o-o-with-double-grave'),
357 (u'\u020f o with inverted breve', 'o-o-with-inverted-breve'),
358 (u'\u0211 r with double grave', 'r-r-with-double-grave'),
359 (u'\u0213 r with inverted breve', 'r-r-with-inverted-breve'),
360 (u'\u0215 u with double grave', 'u-u-with-double-grave'),
361 (u'\u0217 u with inverted breve', 'u-u-with-inverted-breve'),
362 (u'\u0219 s with comma below', 's-s-with-comma-below'),
363 (u'\u021b t with comma below', 't-t-with-comma-below'),
364 (u'\u021f h with caron', 'h-h-with-caron'),
365 (u'\u0227 a with dot above', 'a-a-with-dot-above'),
366 (u'\u0229 e with cedilla', 'e-e-with-cedilla'),
367 (u'\u022f o with dot above', 'o-o-with-dot-above'),
368 (u'\u0233 y with macron', 'y-y-with-macron'),
369 # digraphs From Latin-1 Supplements
370 (u'\u00df: ligature sz', 'sz-ligature-sz'),
371 (u'\u00e6 ae', 'ae-ae'),
372 (u'\u0153 ligature oe', 'oe-ligature-oe'),
373 (u'\u0238 db digraph', 'db-db-digraph'),
374 (u'\u0239 qp digraph', 'qp-qp-digraph'),
377 def test_make_id(self):
378 failures = []
379 tests = self.ids + self.ids_unicode_all
380 for input, expect in tests:
381 output = nodes.make_id(input)
382 if expect != output:
383 failures.append("'%s' != '%s'" % (expect, output))
384 if failures:
385 self.fail("%d failures in %d\n%s" % (len(failures), len(self.ids), "\n".join(failures)))
387 def test_traverse(self):
388 e = nodes.Element()
389 e += nodes.Element()
390 e[0] += nodes.Element()
391 e[0] += nodes.TextElement()
392 e[0][1] += nodes.Text('some text')
393 e += nodes.Element()
394 e += nodes.Element()
395 self.assertEqual(list(e.traverse()),
396 [e, e[0], e[0][0], e[0][1], e[0][1][0], e[1], e[2]])
397 self.assertEqual(list(e.traverse(include_self=False)),
398 [e[0], e[0][0], e[0][1], e[0][1][0], e[1], e[2]])
399 self.assertEqual(list(e.traverse(descend=False)),
400 [e])
401 self.assertEqual(list(e[0].traverse(descend=False, ascend=True)),
402 [e[0], e[1], e[2]])
403 self.assertEqual(list(e[0][0].traverse(descend=False, ascend=True)),
404 [e[0][0], e[0][1], e[1], e[2]])
405 self.assertEqual(list(e[0][0].traverse(descend=False, siblings=True)),
406 [e[0][0], e[0][1]])
407 self.testlist = e[0:2]
408 self.assertEqual(list(e.traverse(condition=self.not_in_testlist)),
409 [e, e[0][0], e[0][1], e[0][1][0], e[2]])
410 # Return siblings despite siblings=False because ascend is true.
411 self.assertEqual(list(e[1].traverse(ascend=True, siblings=False)),
412 [e[1], e[2]])
413 self.assertEqual(list(e[0].traverse()),
414 [e[0], e[0][0], e[0][1], e[0][1][0]])
415 self.testlist = [e[0][0], e[0][1]]
416 self.assertEqual(list(e[0].traverse(condition=self.not_in_testlist)),
417 [e[0], e[0][1][0]])
418 self.testlist.append(e[0][1][0])
419 self.assertEqual(list(e[0].traverse(condition=self.not_in_testlist)),
420 [e[0]])
421 self.assertEqual(list(e.traverse(nodes.TextElement)), [e[0][1]])
423 def test_next_node(self):
424 e = nodes.Element()
425 e += nodes.Element()
426 e[0] += nodes.Element()
427 e[0] += nodes.TextElement()
428 e[0][1] += nodes.Text('some text')
429 e += nodes.Element()
430 e += nodes.Element()
431 self.testlist = [e[0], e[0][1], e[1]]
432 compare = [(e, e[0][0]),
433 (e[0], e[0][0]),
434 (e[0][0], e[0][1][0]),
435 (e[0][1], e[0][1][0]),
436 (e[0][1][0], e[2]),
437 (e[1], e[2]),
438 (e[2], None)]
439 for node, next_node in compare:
440 self.assertEqual(node.next_node(self.not_in_testlist, ascend=True),
441 next_node)
442 self.assertEqual(e[0][0].next_node(ascend=True), e[0][1])
443 self.assertEqual(e[2].next_node(), None)
445 def not_in_testlist(self, x):
446 return x not in self.testlist
448 def test_copy(self):
449 grandchild = nodes.Text('rawsource')
450 child = nodes.emphasis('rawsource', grandchild, att='child')
451 e = nodes.Element('rawsource', child, att='e')
452 # Shallow copy:
453 e_copy = e.copy()
454 self.assertTrue(e is not e_copy)
455 # Internal attributes (like `rawsource`) are also copied.
456 self.assertEqual(e.rawsource, 'rawsource')
457 self.assertEqual(e_copy.rawsource, e.rawsource)
458 self.assertEqual(e_copy['att'], 'e')
459 # Children are not copied.
460 self.assertEqual(len(e_copy), 0)
461 # Deep copy:
462 e_deepcopy = e.deepcopy()
463 self.assertEqual(e_deepcopy.rawsource, e.rawsource)
464 self.assertEqual(e_deepcopy['att'], 'e')
465 # Children are copied recursively.
466 self.assertEqual(e_deepcopy[0][0], grandchild)
467 self.assertTrue(e_deepcopy[0][0] is not grandchild)
468 self.assertEqual(e_deepcopy[0]['att'], 'child')
471 class TreeCopyVisitorTests(unittest.TestCase):
473 def setUp(self):
474 document = utils.new_document('test data')
475 document += nodes.paragraph('', 'Paragraph 1.')
476 blist = nodes.bullet_list()
477 for i in range(1, 6):
478 item = nodes.list_item()
479 for j in range(1, 4):
480 item += nodes.paragraph('', 'Item %s, paragraph %s.' % (i, j))
481 blist += item
482 document += blist
483 self.document = document
485 def compare_trees(self, one, two):
486 self.assertEqual(one.__class__, two.__class__)
487 self.assertNotEquals(id(one), id(two))
488 self.assertEqual(len(one.children), len(two.children))
489 for i in range(len(one.children)):
490 self.compare_trees(one.children[i], two.children[i])
492 def test_copy_whole(self):
493 visitor = nodes.TreeCopyVisitor(self.document)
494 self.document.walkabout(visitor)
495 newtree = visitor.get_tree_copy()
496 self.assertEqual(self.document.pformat(), newtree.pformat())
497 self.compare_trees(self.document, newtree)
500 class MiscFunctionTests(unittest.TestCase):
502 names = [('a', 'a'), ('A', 'a'), ('A a A', 'a a a'),
503 ('A a A a', 'a a a a'),
504 (' AaA\n\r\naAa\tAaA\t\t', 'aaa aaa aaa')]
506 def test_normalize_name(self):
507 for input, output in self.names:
508 normed = nodes.fully_normalize_name(input)
509 self.assertEqual(normed, output)
511 def test_set_id_default(self):
512 # Default prefixes.
513 document = utils.new_document('test')
514 # From name.
515 element = nodes.Element(names=['test'])
516 document.set_id(element)
517 self.assertEqual(element['ids'], ['test'])
518 # Auto-generated.
519 element = nodes.Element()
520 document.set_id(element)
521 self.assertEqual(element['ids'], ['id1'])
523 def test_set_id_custom(self):
524 # Custom prefixes.
525 document = utils.new_document('test')
526 # Change settings.
527 document.settings.id_prefix = 'prefix'
528 document.settings.auto_id_prefix = 'auto'
529 # From name.
530 element = nodes.Element(names=['test'])
531 document.set_id(element)
532 self.assertEqual(element['ids'], ['prefixtest'])
533 # Auto-generated.
534 element = nodes.Element()
535 document.set_id(element)
536 self.assertEqual(element['ids'], ['prefixauto1'])
539 if __name__ == '__main__':
540 unittest.main()