A Python parser for MediaWiki wikicode https://mwparserfromhell.readthedocs.io/
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

451 linhas
22 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2012-2013 Ben Kurtovic <ben.kurtovic@verizon.net>
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a copy
  6. # of this software and associated documentation files (the "Software"), to deal
  7. # in the Software without restriction, including without limitation the rights
  8. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. # copies of the Software, and to permit persons to whom the Software is
  10. # furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. # SOFTWARE.
  22. from __future__ import unicode_literals
  23. import re
  24. from types import GeneratorType
  25. import unittest
  26. from mwparserfromhell.nodes import (Argument, Comment, Heading, HTMLEntity,
  27. Node, Tag, Template, Text, Wikilink)
  28. from mwparserfromhell.smart_list import SmartList
  29. from mwparserfromhell.wikicode import Wikicode
  30. from mwparserfromhell import parse
  31. from mwparserfromhell.compat import py3k, str
  32. from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext
  33. class TestWikicode(TreeEqualityTestCase):
  34. """Tests for the Wikicode class, which manages a list of nodes."""
  35. def test_unicode(self):
  36. """test Wikicode.__unicode__()"""
  37. code1 = parse("foobar")
  38. code2 = parse("Have a {{template}} and a [[page|link]]")
  39. self.assertEqual("foobar", str(code1))
  40. self.assertEqual("Have a {{template}} and a [[page|link]]", str(code2))
  41. def test_nodes(self):
  42. """test getter/setter for the nodes attribute"""
  43. code = parse("Have a {{template}}")
  44. self.assertEqual(["Have a ", "{{template}}"], code.nodes)
  45. L1 = SmartList([Text("foobar"), Template(wraptext("abc"))])
  46. L2 = [Text("barfoo"), Template(wraptext("cba"))]
  47. L3 = "abc{{def}}"
  48. code.nodes = L1
  49. self.assertIs(L1, code.nodes)
  50. code.nodes = L2
  51. self.assertIs(L2, code.nodes)
  52. code.nodes = L3
  53. self.assertEqual(["abc", "{{def}}"], code.nodes)
  54. self.assertRaises(ValueError, setattr, code, "nodes", object)
  55. def test_get(self):
  56. """test Wikicode.get()"""
  57. code = parse("Have a {{template}} and a [[page|link]]")
  58. self.assertIs(code.nodes[0], code.get(0))
  59. self.assertIs(code.nodes[2], code.get(2))
  60. self.assertRaises(IndexError, code.get, 4)
  61. def test_set(self):
  62. """test Wikicode.set()"""
  63. code = parse("Have a {{template}} and a [[page|link]]")
  64. code.set(1, "{{{argument}}}")
  65. self.assertEqual("Have a {{{argument}}} and a [[page|link]]", code)
  66. self.assertIsInstance(code.get(1), Argument)
  67. code.set(2, None)
  68. self.assertEqual("Have a {{{argument}}}[[page|link]]", code)
  69. code.set(-3, "This is an ")
  70. self.assertEqual("This is an {{{argument}}}[[page|link]]", code)
  71. self.assertRaises(ValueError, code.set, 1, "foo {{bar}}")
  72. self.assertRaises(IndexError, code.set, 3, "{{baz}}")
  73. self.assertRaises(IndexError, code.set, -4, "{{baz}}")
  74. def test_index(self):
  75. """test Wikicode.index()"""
  76. code = parse("Have a {{template}} and a [[page|link]]")
  77. self.assertEqual(0, code.index("Have a "))
  78. self.assertEqual(3, code.index("[[page|link]]"))
  79. self.assertEqual(1, code.index(code.get(1)))
  80. self.assertRaises(ValueError, code.index, "foo")
  81. code = parse("{{foo}}{{bar|{{baz}}}}")
  82. self.assertEqual(1, code.index("{{bar|{{baz}}}}"))
  83. self.assertEqual(1, code.index("{{baz}}", recursive=True))
  84. self.assertEqual(1, code.index(code.get(1).get(1).value,
  85. recursive=True))
  86. self.assertRaises(ValueError, code.index, "{{baz}}", recursive=False)
  87. self.assertRaises(ValueError, code.index,
  88. code.get(1).get(1).value, recursive=False)
  89. def test_insert(self):
  90. """test Wikicode.insert()"""
  91. code = parse("Have a {{template}} and a [[page|link]]")
  92. code.insert(1, "{{{argument}}}")
  93. self.assertEqual(
  94. "Have a {{{argument}}}{{template}} and a [[page|link]]", code)
  95. self.assertIsInstance(code.get(1), Argument)
  96. code.insert(2, None)
  97. self.assertEqual(
  98. "Have a {{{argument}}}{{template}} and a [[page|link]]", code)
  99. code.insert(-3, Text("foo"))
  100. self.assertEqual(
  101. "Have a {{{argument}}}foo{{template}} and a [[page|link]]", code)
  102. code2 = parse("{{foo}}{{bar}}{{baz}}")
  103. code2.insert(1, "abc{{def}}ghi[[jk]]")
  104. self.assertEqual("{{foo}}abc{{def}}ghi[[jk]]{{bar}}{{baz}}", code2)
  105. self.assertEqual(["{{foo}}", "abc", "{{def}}", "ghi", "[[jk]]",
  106. "{{bar}}", "{{baz}}"], code2.nodes)
  107. code3 = parse("{{foo}}bar")
  108. code3.insert(1000, "[[baz]]")
  109. code3.insert(-1000, "derp")
  110. self.assertEqual("derp{{foo}}bar[[baz]]", code3)
  111. def _test_search(self, meth, expected):
  112. """Base test for insert_before(), insert_after(), and replace()."""
  113. code = parse("{{a}}{{b}}{{c}}{{d}}")
  114. func = getattr(code, meth)
  115. func("{{b}}", "x", recursive=True)
  116. func("{{d}}", "[[y]]", recursive=False)
  117. self.assertEqual(expected[0], code)
  118. func(code.get(2), "z")
  119. self.assertEqual(expected[1], code)
  120. self.assertRaises(ValueError, func, "{{r}}", "n", recursive=True)
  121. self.assertRaises(ValueError, func, "{{r}}", "n", recursive=False)
  122. fake = parse("{{a}}").get(0)
  123. self.assertRaises(ValueError, func, fake, "n", recursive=True)
  124. self.assertRaises(ValueError, func, fake, "n", recursive=False)
  125. code2 = parse("{{a}}{{a}}{{a}}{{b}}{{b}}{{b}}")
  126. func = getattr(code2, meth)
  127. func(code2.get(1), "c", recursive=False)
  128. func("{{a}}", "d", recursive=False)
  129. func(code2.get(-1), "e", recursive=True)
  130. func("{{b}}", "f", recursive=True)
  131. self.assertEqual(expected[2], code2)
  132. code3 = parse("{{a|{{b}}|{{c|d={{f}}}}}}")
  133. func = getattr(code3, meth)
  134. obj = code3.get(0).params[0].value.get(0)
  135. self.assertRaises(ValueError, func, obj, "x", recursive=False)
  136. func(obj, "x", recursive=True)
  137. self.assertRaises(ValueError, func, "{{f}}", "y", recursive=False)
  138. func("{{f}}", "y", recursive=True)
  139. self.assertEqual(expected[3], code3)
  140. code4 = parse("{{a}}{{b}}{{c}}{{d}}{{e}}{{f}}{{g}}")
  141. func = getattr(code4, meth)
  142. fake = parse("{{b}}{{c}}")
  143. self.assertRaises(ValueError, func, fake, "q", recursive=False)
  144. self.assertRaises(ValueError, func, fake, "q", recursive=True)
  145. func("{{b}}{{c}}", "w", recursive=False)
  146. func("{{d}}{{e}}", "x", recursive=True)
  147. func(wrap(code4.nodes[-2:]), "y", recursive=False)
  148. func(wrap(code4.nodes[-2:]), "z", recursive=True)
  149. self.assertEqual(expected[4], code4)
  150. self.assertRaises(ValueError, func, "{{c}}{{d}}", "q", recursive=False)
  151. self.assertRaises(ValueError, func, "{{c}}{{d}}", "q", recursive=True)
  152. code5 = parse("{{a|{{b}}{{c}}|{{f|{{g}}={{h}}{{i}}}}}}")
  153. func = getattr(code5, meth)
  154. self.assertRaises(ValueError, func, "{{b}}{{c}}", "x", recursive=False)
  155. func("{{b}}{{c}}", "x", recursive=True)
  156. obj = code5.get(0).params[1].value.get(0).params[0].value
  157. self.assertRaises(ValueError, func, obj, "y", recursive=False)
  158. func(obj, "y", recursive=True)
  159. self.assertEqual(expected[5], code5)
  160. code6 = parse("here is {{some text and a {{template}}}}")
  161. func = getattr(code6, meth)
  162. self.assertRaises(ValueError, func, "text and", "ab", recursive=False)
  163. func("text and", "ab", recursive=True)
  164. self.assertRaises(ValueError, func, "is {{some", "cd", recursive=False)
  165. func("is {{some", "cd", recursive=True)
  166. self.assertEqual(expected[6], code6)
  167. def test_insert_before(self):
  168. """test Wikicode.insert_before()"""
  169. expected = [
  170. "{{a}}x{{b}}{{c}}[[y]]{{d}}", "{{a}}xz{{b}}{{c}}[[y]]{{d}}",
  171. "d{{a}}cd{{a}}d{{a}}f{{b}}f{{b}}ef{{b}}",
  172. "{{a|x{{b}}|{{c|d=y{{f}}}}}}",
  173. "{{a}}w{{b}}{{c}}x{{d}}{{e}}yz{{f}}{{g}}",
  174. "{{a|x{{b}}{{c}}|{{f|{{g}}=y{{h}}{{i}}}}}}",
  175. "here cdis {{some abtext and a {{template}}}}"]
  176. self._test_search("insert_before", expected)
  177. def test_insert_after(self):
  178. """test Wikicode.insert_after()"""
  179. expected = [
  180. "{{a}}{{b}}x{{c}}{{d}}[[y]]", "{{a}}{{b}}xz{{c}}{{d}}[[y]]",
  181. "{{a}}d{{a}}dc{{a}}d{{b}}f{{b}}f{{b}}fe",
  182. "{{a|{{b}}x|{{c|d={{f}}y}}}}",
  183. "{{a}}{{b}}{{c}}w{{d}}{{e}}x{{f}}{{g}}yz",
  184. "{{a|{{b}}{{c}}x|{{f|{{g}}={{h}}{{i}}y}}}}",
  185. "here is {{somecd text andab a {{template}}}}"]
  186. self._test_search("insert_after", expected)
  187. def test_replace(self):
  188. """test Wikicode.replace()"""
  189. expected = [
  190. "{{a}}x{{c}}[[y]]", "{{a}}xz[[y]]", "dcdffe", "{{a|x|{{c|d=y}}}}",
  191. "{{a}}wz", "{{a|x|{{f|{{g}}=y}}}}", "here cd ab a {{template}}}}"]
  192. self._test_search("replace", expected)
  193. def test_append(self):
  194. """test Wikicode.append()"""
  195. code = parse("Have a {{template}}")
  196. code.append("{{{argument}}}")
  197. self.assertEqual("Have a {{template}}{{{argument}}}", code)
  198. self.assertIsInstance(code.get(2), Argument)
  199. code.append(None)
  200. self.assertEqual("Have a {{template}}{{{argument}}}", code)
  201. code.append(Text(" foo"))
  202. self.assertEqual("Have a {{template}}{{{argument}}} foo", code)
  203. self.assertRaises(ValueError, code.append, slice(0, 1))
  204. def test_remove(self):
  205. """test Wikicode.remove()"""
  206. code = parse("{{a}}{{b}}{{c}}{{d}}")
  207. code.remove("{{b}}", recursive=True)
  208. code.remove(code.get(1), recursive=True)
  209. self.assertEqual("{{a}}{{d}}", code)
  210. self.assertRaises(ValueError, code.remove, "{{r}}", recursive=True)
  211. self.assertRaises(ValueError, code.remove, "{{r}}", recursive=False)
  212. fake = parse("{{a}}").get(0)
  213. self.assertRaises(ValueError, code.remove, fake, recursive=True)
  214. self.assertRaises(ValueError, code.remove, fake, recursive=False)
  215. code2 = parse("{{a}}{{a}}{{a}}{{b}}{{b}}{{b}}")
  216. code2.remove(code2.get(1), recursive=False)
  217. self.assertEqual("{{a}}{{a}}{{b}}{{b}}{{b}}", code2)
  218. code2.remove("{{a}}", recursive=False)
  219. self.assertEqual("{{b}}{{b}}{{b}}", code2)
  220. code2.remove(code2.get(-1), recursive=True)
  221. self.assertEqual("{{b}}{{b}}", code2)
  222. code2.remove("{{b}}", recursive=True)
  223. self.assertEqual("", code2)
  224. code3 = parse("{{a|{{b}}|{{c|d={{f}}}}}}")
  225. obj = code3.get(0).params[0].value.get(0)
  226. self.assertRaises(ValueError, code3.remove, obj, recursive=False)
  227. code3.remove(obj, recursive=True)
  228. self.assertRaises(ValueError, code3.remove, "{{f}}", recursive=False)
  229. code3.remove("{{f}}", recursive=True)
  230. self.assertEqual("{{a||{{c|d=}}}}", code3)
  231. code4 = parse("{{a}}{{b}}{{c}}{{d}}{{e}}{{f}}{{g}}{{h}}{{i}}{{j}}")
  232. fake = parse("{{b}}{{c}}")
  233. self.assertRaises(ValueError, code4.remove, fake, recursive=False)
  234. self.assertRaises(ValueError, code4.remove, fake, recursive=True)
  235. code4.remove("{{b}}{{c}}", recursive=False)
  236. code4.remove("{{d}}{{e}}", recursive=True)
  237. code4.remove(wrap(code4.nodes[-2:]), recursive=False)
  238. code4.remove(wrap(code4.nodes[-2:]), recursive=True)
  239. self.assertEqual("{{a}}{{f}}", code4)
  240. self.assertRaises(ValueError, code4.remove, "{{a}}{{b}}", False)
  241. self.assertRaises(ValueError, code4.remove, "{{a}}{{b}}", True)
  242. code5 = parse("{{a|{{b}}{{c}}|{{f|{{g}}={{h}}{{i}}}}}}")
  243. self.assertRaises(ValueError, code5.remove, "{{b}}{{c}}", False)
  244. code5.remove("{{b}}{{c}}", recursive=True)
  245. obj = code5.get(0).params[1].value.get(0).params[0].value
  246. self.assertRaises(ValueError, code5.remove, obj, recursive=False)
  247. code5.remove(obj, recursive=True)
  248. self.assertEqual("{{a||{{f|{{g}}=}}}}", code5)
  249. code6 = parse("here is {{some text and a {{template}}}}")
  250. func = code6.remove
  251. self.assertRaises(ValueError, func, "text and", recursive=False)
  252. func("text and", recursive=True)
  253. self.assertRaises(ValueError, func, "is {{some", recursive=False)
  254. func("is {{some", recursive=True)
  255. self.assertEqual("here a {{template}}}}", code6)
  256. def test_matches(self):
  257. """test Wikicode.matches()"""
  258. code1 = parse("Cleanup")
  259. code2 = parse("\nstub<!-- TODO: make more specific -->")
  260. self.assertTrue(code1.matches("Cleanup"))
  261. self.assertTrue(code1.matches("cleanup"))
  262. self.assertTrue(code1.matches(" cleanup\n"))
  263. self.assertFalse(code1.matches("CLEANup"))
  264. self.assertFalse(code1.matches("Blah"))
  265. self.assertTrue(code2.matches("stub"))
  266. self.assertTrue(code2.matches("Stub<!-- no, it's fine! -->"))
  267. self.assertFalse(code2.matches("StuB"))
  268. def test_filter_family(self):
  269. """test the Wikicode.i?filter() family of functions"""
  270. def genlist(gen):
  271. self.assertIsInstance(gen, GeneratorType)
  272. return list(gen)
  273. ifilter = lambda code: (lambda **kw: genlist(code.ifilter(**kw)))
  274. code = parse("a{{b}}c[[d]]{{{e}}}{{f}}[[g]]")
  275. for func in (code.filter, ifilter(code)):
  276. self.assertEqual(["a", "{{b}}", "b", "c", "[[d]]", "d", "{{{e}}}",
  277. "e", "{{f}}", "f", "[[g]]", "g"], func())
  278. self.assertEqual(["{{{e}}}"], func(forcetype=Argument))
  279. self.assertIs(code.get(4), func(forcetype=Argument)[0])
  280. self.assertEqual(list("abcdefg"), func(forcetype=Text))
  281. self.assertEqual([], func(forcetype=Heading))
  282. self.assertRaises(TypeError, func, forcetype=True)
  283. funcs = [
  284. lambda name, **kw: getattr(code, "filter_" + name)(**kw),
  285. lambda name, **kw: genlist(getattr(code, "ifilter_" + name)(**kw))
  286. ]
  287. for get_filter in funcs:
  288. self.assertEqual(["{{{e}}}"], get_filter("arguments"))
  289. self.assertIs(code.get(4), get_filter("arguments")[0])
  290. self.assertEqual([], get_filter("comments"))
  291. self.assertEqual([], get_filter("headings"))
  292. self.assertEqual([], get_filter("html_entities"))
  293. self.assertEqual([], get_filter("tags"))
  294. self.assertEqual(["{{b}}", "{{f}}"], get_filter("templates"))
  295. self.assertEqual(list("abcdefg"), get_filter("text"))
  296. self.assertEqual(["[[d]]", "[[g]]"], get_filter("wikilinks"))
  297. code2 = parse("{{a|{{b}}|{{c|d={{f}}{{h}}}}}}")
  298. for func in (code2.filter, ifilter(code2)):
  299. self.assertEqual(["{{a|{{b}}|{{c|d={{f}}{{h}}}}}}"],
  300. func(recursive=False, forcetype=Template))
  301. self.assertEqual(["{{a|{{b}}|{{c|d={{f}}{{h}}}}}}", "{{b}}",
  302. "{{c|d={{f}}{{h}}}}", "{{f}}", "{{h}}"],
  303. func(recursive=True, forcetype=Template))
  304. code3 = parse("{{foobar}}{{FOO}}{{baz}}{{bz}}")
  305. for func in (code3.filter, ifilter(code3)):
  306. self.assertEqual(["{{foobar}}", "{{FOO}}"], func(recursive=False, matches=r"foo"))
  307. self.assertEqual(["{{foobar}}", "{{FOO}}"],
  308. func(recursive=False, matches=r"^{{foo.*?}}"))
  309. self.assertEqual(["{{foobar}}"],
  310. func(recursive=False, matches=r"^{{foo.*?}}", flags=re.UNICODE))
  311. self.assertEqual(["{{baz}}", "{{bz}}"], func(recursive=False, matches=r"^{{b.*?z"))
  312. self.assertEqual(["{{baz}}"], func(recursive=False, matches=r"^{{b.+?z}}"))
  313. self.assertEqual(["{{a|{{b}}|{{c|d={{f}}{{h}}}}}}"],
  314. code2.filter_templates(recursive=False))
  315. self.assertEqual(["{{a|{{b}}|{{c|d={{f}}{{h}}}}}}", "{{b}}",
  316. "{{c|d={{f}}{{h}}}}", "{{f}}", "{{h}}"],
  317. code2.filter_templates(recursive=True))
  318. self.assertEqual(["{{baz}}", "{{bz}}"],
  319. code3.filter_templates(matches=r"^{{b.*?z"))
  320. self.assertEqual([], code3.filter_tags(matches=r"^{{b.*?z"))
  321. self.assertEqual([], code3.filter_tags(matches=r"^{{b.*?z", flags=0))
  322. self.assertRaises(TypeError, code.filter_templates, 100)
  323. self.assertRaises(TypeError, code.filter_templates, a=42)
  324. self.assertRaises(TypeError, code.filter_templates, forcetype=Template)
  325. def test_get_sections(self):
  326. """test Wikicode.get_sections()"""
  327. page1 = parse("")
  328. page2 = parse("==Heading==")
  329. page3 = parse("===Heading===\nFoo bar baz\n====Gnidaeh====\n")
  330. p4_lead = "This is a lead.\n"
  331. p4_IA = "=== Section I.A ===\nSection I.A [[body]].\n"
  332. p4_IB1 = "==== Section I.B.1 ====\nSection I.B.1 body.\n\n&bull;Some content.\n\n"
  333. p4_IB = "=== Section I.B ===\n" + p4_IB1
  334. p4_I = "== Section I ==\nSection I body. {{and a|template}}\n" + p4_IA + p4_IB
  335. p4_II = "== Section II ==\nSection II body.\n\n"
  336. p4_IIIA1a = "===== Section III.A.1.a =====\nMore text.\n"
  337. p4_IIIA2ai1 = "======= Section III.A.2.a.i.1 =======\nAn invalid section!"
  338. p4_IIIA2 = "==== Section III.A.2 ====\nEven more text.\n" + p4_IIIA2ai1
  339. p4_IIIA = "=== Section III.A ===\nText.\n" + p4_IIIA1a + p4_IIIA2
  340. p4_III = "== Section III ==\n" + p4_IIIA
  341. page4 = parse(p4_lead + p4_I + p4_II + p4_III)
  342. self.assertEqual([], page1.get_sections())
  343. self.assertEqual(["", "==Heading=="], page2.get_sections())
  344. self.assertEqual(["", "===Heading===\nFoo bar baz\n====Gnidaeh====\n",
  345. "====Gnidaeh====\n"], page3.get_sections())
  346. self.assertEqual([p4_lead, p4_IA, p4_I, p4_IB, p4_IB1, p4_II,
  347. p4_IIIA1a, p4_III, p4_IIIA, p4_IIIA2, p4_IIIA2ai1],
  348. page4.get_sections())
  349. self.assertEqual(["====Gnidaeh====\n"], page3.get_sections(levels=[4]))
  350. self.assertEqual(["===Heading===\nFoo bar baz\n====Gnidaeh====\n"],
  351. page3.get_sections(levels=(2, 3)))
  352. self.assertEqual([], page3.get_sections(levels=[0]))
  353. self.assertEqual(["", "====Gnidaeh====\n"],
  354. page3.get_sections(levels=[4], include_lead=True))
  355. self.assertEqual(["===Heading===\nFoo bar baz\n====Gnidaeh====\n",
  356. "====Gnidaeh====\n"],
  357. page3.get_sections(include_lead=False))
  358. self.assertEqual([p4_IB1, p4_IIIA2], page4.get_sections(levels=[4]))
  359. self.assertEqual([""], page2.get_sections(include_headings=False))
  360. self.assertEqual(["\nSection I.B.1 body.\n\n&bull;Some content.\n\n",
  361. "\nEven more text.\n" + p4_IIIA2ai1],
  362. page4.get_sections(levels=[4],
  363. include_headings=False))
  364. self.assertEqual([], page4.get_sections(matches=r"body"))
  365. self.assertEqual([p4_IA, p4_I, p4_IB, p4_IB1],
  366. page4.get_sections(matches=r"Section\sI[.\s].*?"))
  367. self.assertEqual([p4_IA, p4_IIIA1a, p4_IIIA, p4_IIIA2, p4_IIIA2ai1],
  368. page4.get_sections(matches=r".*?a.*?"))
  369. self.assertEqual([p4_IIIA1a, p4_IIIA2ai1],
  370. page4.get_sections(matches=r".*?a.*?", flags=re.U))
  371. self.assertEqual(["\nMore text.\n", "\nAn invalid section!"],
  372. page4.get_sections(matches=r".*?a.*?", flags=re.U,
  373. include_headings=False))
  374. page5 = parse("X\n== Foo ==\nBar\n== Baz ==\nBuzz")
  375. section = page5.get_sections(matches="Foo")[0]
  376. section.replace("\nBar\n", "\nBarf ")
  377. section.append("{{Haha}}\n")
  378. self.assertEqual("== Foo ==\nBarf {{Haha}}\n", section)
  379. self.assertEqual("X\n== Foo ==\nBarf {{Haha}}\n== Baz ==\nBuzz", page5)
  380. def test_strip_code(self):
  381. """test Wikicode.strip_code()"""
  382. # Since individual nodes have test cases for their __strip__ methods,
  383. # we're only going to do an integration test:
  384. code = parse("Foo [[bar]]\n\n{{baz}}\n\n[[a|b]] &Sigma;")
  385. self.assertEqual("Foo bar\n\nb Σ",
  386. code.strip_code(normalize=True, collapse=True))
  387. self.assertEqual("Foo bar\n\n\n\nb Σ",
  388. code.strip_code(normalize=True, collapse=False))
  389. self.assertEqual("Foo bar\n\nb &Sigma;",
  390. code.strip_code(normalize=False, collapse=True))
  391. self.assertEqual("Foo bar\n\n\n\nb &Sigma;",
  392. code.strip_code(normalize=False, collapse=False))
  393. def test_get_tree(self):
  394. """test Wikicode.get_tree()"""
  395. # Since individual nodes have test cases for their __showtree___
  396. # methods, and the docstring covers all possibilities for the output of
  397. # __showtree__, we'll test it only:
  398. code = parse("Lorem ipsum {{foo|bar|{{baz}}|spam=eggs}}")
  399. expected = "Lorem ipsum \n{{\n\t foo\n\t| 1\n\t= bar\n\t| 2\n\t= " + \
  400. "{{\n\t\t\tbaz\n\t }}\n\t| spam\n\t= eggs\n}}"
  401. self.assertEqual(expected.expandtabs(4), code.get_tree())
  402. if __name__ == "__main__":
  403. unittest.main(verbosity=2)