A Python parser for MediaWiki wikicode https://mwparserfromhell.readthedocs.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

669 lines
28 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2012-2017 Ben Kurtovic <ben.kurtovic@gmail.com>
  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. try:
  24. import unittest2 as unittest
  25. except ImportError:
  26. import unittest
  27. from mwparserfromhell.compat import str
  28. from mwparserfromhell.nodes import HTMLEntity, Template, Text
  29. from mwparserfromhell.nodes.extras import Parameter
  30. from mwparserfromhell import parse
  31. from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext
  32. pgens = lambda k, v: Parameter(wraptext(k), wraptext(v), showkey=True)
  33. pgenh = lambda k, v: Parameter(wraptext(k), wraptext(v), showkey=False)
  34. class TestTemplate(TreeEqualityTestCase):
  35. """Test cases for the Template node."""
  36. def test_unicode(self):
  37. """test Template.__unicode__()"""
  38. node = Template(wraptext("foobar"))
  39. self.assertEqual("{{foobar}}", str(node))
  40. node2 = Template(wraptext("foo"),
  41. [pgenh("1", "bar"), pgens("abc", "def")])
  42. self.assertEqual("{{foo|bar|abc=def}}", str(node2))
  43. def test_children(self):
  44. """test Template.__children__()"""
  45. node2p1 = Parameter(wraptext("1"), wraptext("bar"), showkey=False)
  46. node2p2 = Parameter(wraptext("abc"), wrap([Text("def"), Text("ghi")]),
  47. showkey=True)
  48. node1 = Template(wraptext("foobar"))
  49. node2 = Template(wraptext("foo"), [node2p1, node2p2])
  50. gen1 = node1.__children__()
  51. gen2 = node2.__children__()
  52. self.assertEqual(node1.name, next(gen1))
  53. self.assertEqual(node2.name, next(gen2))
  54. self.assertEqual(node2.params[0].value, next(gen2))
  55. self.assertEqual(node2.params[1].name, next(gen2))
  56. self.assertEqual(node2.params[1].value, next(gen2))
  57. self.assertRaises(StopIteration, next, gen1)
  58. self.assertRaises(StopIteration, next, gen2)
  59. def test_strip(self):
  60. """test Template.__strip__()"""
  61. node1 = Template(wraptext("foobar"))
  62. node2 = Template(wraptext("foo"), [
  63. pgenh("1", "bar"), pgens("foo", ""), pgens("abc", "def")])
  64. node3 = Template(wraptext("foo"), [
  65. pgenh("1", "foo"),
  66. Parameter(wraptext("2"), wrap([Template(wraptext("hello"))]),
  67. showkey=False),
  68. pgenh("3", "bar")])
  69. self.assertEqual(None, node1.__strip__(keep_template_params=False))
  70. self.assertEqual(None, node2.__strip__(keep_template_params=False))
  71. self.assertEqual("", node1.__strip__(keep_template_params=True))
  72. self.assertEqual("bar def", node2.__strip__(keep_template_params=True))
  73. self.assertEqual("foo bar", node3.__strip__(keep_template_params=True))
  74. def test_showtree(self):
  75. """test Template.__showtree__()"""
  76. output = []
  77. getter, marker = object(), object()
  78. get = lambda code: output.append((getter, code))
  79. mark = lambda: output.append(marker)
  80. node1 = Template(wraptext("foobar"))
  81. node2 = Template(wraptext("foo"),
  82. [pgenh("1", "bar"), pgens("abc", "def")])
  83. node1.__showtree__(output.append, get, mark)
  84. node2.__showtree__(output.append, get, mark)
  85. valid = [
  86. "{{", (getter, node1.name), "}}", "{{", (getter, node2.name),
  87. " | ", marker, (getter, node2.params[0].name), " = ", marker,
  88. (getter, node2.params[0].value), " | ", marker,
  89. (getter, node2.params[1].name), " = ", marker,
  90. (getter, node2.params[1].value), "}}"]
  91. self.assertEqual(valid, output)
  92. def test_name(self):
  93. """test getter/setter for the name attribute"""
  94. name = wraptext("foobar")
  95. node1 = Template(name)
  96. node2 = Template(name, [pgenh("1", "bar")])
  97. self.assertIs(name, node1.name)
  98. self.assertIs(name, node2.name)
  99. node1.name = "asdf"
  100. node2.name = "téstïng"
  101. self.assertWikicodeEqual(wraptext("asdf"), node1.name)
  102. self.assertWikicodeEqual(wraptext("téstïng"), node2.name)
  103. def test_params(self):
  104. """test getter for the params attribute"""
  105. node1 = Template(wraptext("foobar"))
  106. plist = [pgenh("1", "bar"), pgens("abc", "def")]
  107. node2 = Template(wraptext("foo"), plist)
  108. self.assertEqual([], node1.params)
  109. self.assertIs(plist, node2.params)
  110. def test_has(self):
  111. """test Template.has()"""
  112. node1 = Template(wraptext("foobar"))
  113. node2 = Template(wraptext("foo"),
  114. [pgenh("1", "bar"), pgens("\nabc ", "def")])
  115. node3 = Template(wraptext("foo"),
  116. [pgenh("1", "a"), pgens("b", "c"), pgens("1", "d")])
  117. node4 = Template(wraptext("foo"), [pgenh("1", "a"), pgens("b", " ")])
  118. self.assertFalse(node1.has("foobar", False))
  119. self.assertTrue(node2.has(1, False))
  120. self.assertTrue(node2.has("abc", False))
  121. self.assertFalse(node2.has("def", False))
  122. self.assertTrue(node3.has("1", False))
  123. self.assertTrue(node3.has(" b ", False))
  124. self.assertTrue(node4.has("b", False))
  125. self.assertTrue(node3.has("b", True))
  126. self.assertFalse(node4.has("b", True))
  127. self.assertFalse(node1.has_param("foobar", False))
  128. self.assertTrue(node2.has_param(1, False))
  129. def test_get(self):
  130. """test Template.get()"""
  131. node1 = Template(wraptext("foobar"))
  132. node2p1 = pgenh("1", "bar")
  133. node2p2 = pgens("abc", "def")
  134. node2 = Template(wraptext("foo"), [node2p1, node2p2])
  135. node3p1 = pgens("b", "c")
  136. node3p2 = pgens("1", "d")
  137. node3 = Template(wraptext("foo"), [pgenh("1", "a"), node3p1, node3p2])
  138. node4p1 = pgens(" b", " ")
  139. node4 = Template(wraptext("foo"), [pgenh("1", "a"), node4p1])
  140. self.assertRaises(ValueError, node1.get, "foobar")
  141. self.assertIs(node2p1, node2.get(1))
  142. self.assertIs(node2p2, node2.get("abc"))
  143. self.assertRaises(ValueError, node2.get, "def")
  144. self.assertIs(node3p1, node3.get("b"))
  145. self.assertIs(node3p2, node3.get("1"))
  146. self.assertIs(node4p1, node4.get("b "))
  147. def test_add(self):
  148. """test Template.add()"""
  149. node1 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  150. node2 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  151. node3 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  152. node4 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  153. node5 = Template(wraptext("a"), [pgens("b", "c"),
  154. pgens(" d ", "e")])
  155. node6 = Template(wraptext("a"), [pgens("b", "c"), pgens("b", "d"),
  156. pgens("b", "e")])
  157. node7 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  158. node8p = pgenh("1", "d")
  159. node8 = Template(wraptext("a"), [pgens("b", "c"), node8p])
  160. node9 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  161. node10 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "e")])
  162. node11 = Template(wraptext("a"), [pgens("b", "c")])
  163. node12 = Template(wraptext("a"), [pgens("b", "c")])
  164. node13 = Template(wraptext("a"), [
  165. pgens("\nb ", " c"), pgens("\nd ", " e"), pgens("\nf ", " g")])
  166. node14 = Template(wraptext("a\n"), [
  167. pgens("b ", "c\n"), pgens("d ", " e"), pgens("f ", "g\n"),
  168. pgens("h ", " i\n")])
  169. node15 = Template(wraptext("a"), [
  170. pgens("b ", " c\n"), pgens("\nd ", " e"), pgens("\nf ", "g ")])
  171. node16 = Template(wraptext("a"), [
  172. pgens("\nb ", " c"), pgens("\nd ", " e"), pgens("\nf ", " g")])
  173. node17 = Template(wraptext("a"), [pgenh("1", "b")])
  174. node18 = Template(wraptext("a"), [pgenh("1", "b")])
  175. node19 = Template(wraptext("a"), [pgenh("1", "b")])
  176. node20 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
  177. pgenh("3", "d"), pgenh("4", "e")])
  178. node21 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
  179. pgens("4", "d"), pgens("5", "e")])
  180. node22 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
  181. pgens("4", "d"), pgens("5", "e")])
  182. node23 = Template(wraptext("a"), [pgenh("1", "b")])
  183. node24 = Template(wraptext("a"), [pgenh("1", "b")])
  184. node25 = Template(wraptext("a"), [pgens("b", "c")])
  185. node26 = Template(wraptext("a"), [pgenh("1", "b")])
  186. node27 = Template(wraptext("a"), [pgenh("1", "b")])
  187. node28 = Template(wraptext("a"), [pgens("1", "b")])
  188. node29 = Template(wraptext("a"), [
  189. pgens("\nb ", " c"), pgens("\nd ", " e"), pgens("\nf ", " g")])
  190. node30 = Template(wraptext("a\n"), [
  191. pgens("b ", "c\n"), pgens("d ", " e"), pgens("f ", "g\n"),
  192. pgens("h ", " i\n")])
  193. node31 = Template(wraptext("a"), [
  194. pgens("b ", " c\n"), pgens("\nd ", " e"), pgens("\nf ", "g ")])
  195. node32 = Template(wraptext("a"), [
  196. pgens("\nb ", " c "), pgens("\nd ", " e "), pgens("\nf ", " g ")])
  197. node33 = Template(wraptext("a"), [pgens("b", "c"), pgens("d", "e"),
  198. pgens("b", "f"), pgens("b", "h"),
  199. pgens("i", "j")])
  200. node34 = Template(wraptext("a"), [pgens("1", "b"), pgens("x", "y"),
  201. pgens("1", "c"), pgens("2", "d")])
  202. node35 = Template(wraptext("a"), [pgens("1", "b"), pgens("x", "y"),
  203. pgenh("1", "c"), pgenh("2", "d")])
  204. node36 = Template(wraptext("a"), [pgens("b", "c"), pgens("d", "e"),
  205. pgens("f", "g")])
  206. node37 = Template(wraptext("a"), [pgenh("1", "")])
  207. node38 = Template(wraptext("abc"))
  208. node39 = Template(wraptext("a"), [pgenh("1", " b ")])
  209. node40 = Template(wraptext("a"), [pgenh("1", " b"), pgenh("2", " c")])
  210. node41 = Template(wraptext("a"), [pgens("1", " b"), pgens("2", " c")])
  211. node42 = Template(wraptext("a"), [pgens("b", " \n")])
  212. node1.add("e", "f", showkey=True)
  213. node2.add(2, "g", showkey=False)
  214. node3.add("e", "foo|bar", showkey=True)
  215. node4.add("e", "f", showkey=True, before="b")
  216. node5.add("f", "g", showkey=True, before=" d ")
  217. node6.add("f", "g", showkey=True, before="b")
  218. self.assertRaises(ValueError, node7.add, "e", "f", showkey=True,
  219. before="q")
  220. node8.add("e", "f", showkey=True, before=node8p)
  221. node9.add("e", "f", showkey=True, before=pgenh("1", "d"))
  222. self.assertRaises(ValueError, node10.add, "e", "f", showkey=True,
  223. before=pgenh("1", "d"))
  224. node11.add("d", "foo=bar", showkey=True)
  225. node12.add("1", "foo=bar", showkey=False)
  226. node13.add("h", "i", showkey=True)
  227. node14.add("j", "k", showkey=True)
  228. node15.add("h", "i", showkey=True)
  229. node16.add("h", "i", showkey=True, preserve_spacing=False)
  230. node17.add("2", "c")
  231. node18.add("3", "c")
  232. node19.add("c", "d")
  233. node20.add("5", "f")
  234. node21.add("3", "f")
  235. node22.add("6", "f")
  236. node23.add("c", "foo=bar")
  237. node24.add("2", "foo=bar")
  238. node25.add("b", "d")
  239. node26.add("1", "foo=bar")
  240. node27.add("1", "foo=bar", showkey=True)
  241. node28.add("1", "foo=bar", showkey=False)
  242. node29.add("d", "foo")
  243. node30.add("f", "foo")
  244. node31.add("f", "foo")
  245. node32.add("d", "foo", preserve_spacing=False)
  246. node33.add("b", "k")
  247. node34.add("1", "e")
  248. node35.add("1", "e")
  249. node36.add("d", "h", before="b")
  250. node37.add(1, "b")
  251. node38.add("1", "foo")
  252. self.assertRaises(ValueError, node38.add, "z", "bar", showkey=False)
  253. node39.add("1", "c")
  254. node40.add("3", "d")
  255. node41.add("3", "d")
  256. node42.add("b", "hello")
  257. self.assertEqual("{{a|b=c|d|e=f}}", node1)
  258. self.assertEqual("{{a|b=c|d|g}}", node2)
  259. self.assertEqual("{{a|b=c|d|e=foo&#124;bar}}", node3)
  260. self.assertIsInstance(node3.params[2].value.get(1), HTMLEntity)
  261. self.assertEqual("{{a|e=f|b=c|d}}", node4)
  262. self.assertEqual("{{a|b=c|f=g| d =e}}", node5)
  263. self.assertEqual("{{a|b=c|b=d|f=g|b=e}}", node6)
  264. self.assertEqual("{{a|b=c|d}}", node7)
  265. self.assertEqual("{{a|b=c|e=f|d}}", node8)
  266. self.assertEqual("{{a|b=c|e=f|d}}", node9)
  267. self.assertEqual("{{a|b=c|e}}", node10)
  268. self.assertEqual("{{a|b=c|d=foo=bar}}", node11)
  269. self.assertEqual("{{a|b=c|foo&#61;bar}}", node12)
  270. self.assertIsInstance(node12.params[1].value.get(1), HTMLEntity)
  271. self.assertEqual("{{a|\nb = c|\nd = e|\nf = g|\nh = i}}", node13)
  272. self.assertEqual("{{a\n|b =c\n|d = e|f =g\n|h = i\n|j =k\n}}", node14)
  273. self.assertEqual("{{a|b = c\n|\nd = e|\nf =g |\nh = i}}", node15)
  274. self.assertEqual("{{a|\nb = c|\nd = e|\nf = g|h=i}}", node16)
  275. self.assertEqual("{{a|b|c}}", node17)
  276. self.assertEqual("{{a|b|3=c}}", node18)
  277. self.assertEqual("{{a|b|c=d}}", node19)
  278. self.assertEqual("{{a|b|c|d|e|f}}", node20)
  279. self.assertEqual("{{a|b|c|4=d|5=e|f}}", node21)
  280. self.assertEqual("{{a|b|c|4=d|5=e|6=f}}", node22)
  281. self.assertEqual("{{a|b|c=foo=bar}}", node23)
  282. self.assertEqual("{{a|b|foo&#61;bar}}", node24)
  283. self.assertIsInstance(node24.params[1].value.get(1), HTMLEntity)
  284. self.assertEqual("{{a|b=d}}", node25)
  285. self.assertEqual("{{a|foo&#61;bar}}", node26)
  286. self.assertIsInstance(node26.params[0].value.get(1), HTMLEntity)
  287. self.assertEqual("{{a|1=foo=bar}}", node27)
  288. self.assertEqual("{{a|foo&#61;bar}}", node28)
  289. self.assertIsInstance(node28.params[0].value.get(1), HTMLEntity)
  290. self.assertEqual("{{a|\nb = c|\nd = foo|\nf = g}}", node29)
  291. self.assertEqual("{{a\n|b =c\n|d = e|f =foo\n|h = i\n}}", node30)
  292. self.assertEqual("{{a|b = c\n|\nd = e|\nf =foo }}", node31)
  293. self.assertEqual("{{a|\nb = c |\nd =foo|\nf = g }}", node32)
  294. self.assertEqual("{{a|b=k|d=e|i=j}}", node33)
  295. self.assertEqual("{{a|1=e|x=y|2=d}}", node34)
  296. self.assertEqual("{{a|x=y|e|d}}", node35)
  297. self.assertEqual("{{a|b=c|d=h|f=g}}", node36)
  298. self.assertEqual("{{a|b}}", node37)
  299. self.assertEqual("{{abc|foo}}", node38)
  300. self.assertEqual("{{a|c}}", node39)
  301. self.assertEqual("{{a| b| c|d}}", node40)
  302. self.assertEqual("{{a|1= b|2= c|3= d}}", node41)
  303. self.assertEqual("{{a|b=hello \n}}", node42)
  304. def test_remove(self):
  305. """test Template.remove()"""
  306. node1 = Template(wraptext("foobar"))
  307. node2 = Template(wraptext("foo"),
  308. [pgenh("1", "bar"), pgens("abc", "def")])
  309. node3 = Template(wraptext("foo"),
  310. [pgenh("1", "bar"), pgens("abc", "def")])
  311. node4 = Template(wraptext("foo"),
  312. [pgenh("1", "bar"), pgenh("2", "baz")])
  313. node5 = Template(wraptext("foo"), [
  314. pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
  315. node6 = Template(wraptext("foo"), [
  316. pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
  317. node7 = Template(wraptext("foo"), [
  318. pgens("1 ", "a"), pgens(" 1", "b"), pgens("2", "c")])
  319. node8 = Template(wraptext("foo"), [
  320. pgens("1 ", "a"), pgens(" 1", "b"), pgens("2", "c")])
  321. node9 = Template(wraptext("foo"), [
  322. pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])
  323. node10 = Template(wraptext("foo"), [
  324. pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])
  325. node11 = Template(wraptext("foo"), [
  326. pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
  327. node12 = Template(wraptext("foo"), [
  328. pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
  329. node13 = Template(wraptext("foo"), [
  330. pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
  331. node14 = Template(wraptext("foo"), [
  332. pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
  333. node15 = Template(wraptext("foo"), [
  334. pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
  335. node16 = Template(wraptext("foo"), [
  336. pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
  337. node17 = Template(wraptext("foo"), [
  338. pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])
  339. node18 = Template(wraptext("foo"), [
  340. pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])
  341. node19 = Template(wraptext("foo"), [
  342. pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])
  343. node20 = Template(wraptext("foo"), [
  344. pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])
  345. node21 = Template(wraptext("foo"), [
  346. pgens("a", "b"), pgens("c", "d"), pgens("e", "f"), pgens("a", "b"),
  347. pgens("a", "b")])
  348. node22 = Template(wraptext("foo"), [
  349. pgens("a", "b"), pgens("c", "d"), pgens("e", "f"), pgens("a", "b"),
  350. pgens("a", "b")])
  351. node23 = Template(wraptext("foo"), [
  352. pgens("a", "b"), pgens("c", "d"), pgens("e", "f"), pgens("a", "b"),
  353. pgens("a", "b")])
  354. node24 = Template(wraptext("foo"), [
  355. pgens("a", "b"), pgens("c", "d"), pgens("e", "f"), pgens("a", "b"),
  356. pgens("a", "b")])
  357. node25 = Template(wraptext("foo"), [
  358. pgens("a", "b"), pgens("c", "d"), pgens("e", "f"), pgens("a", "b"),
  359. pgens("a", "b")])
  360. node26 = Template(wraptext("foo"), [
  361. pgens("a", "b"), pgens("c", "d"), pgens("e", "f"), pgens("a", "b"),
  362. pgens("a", "b")])
  363. node27 = Template(wraptext("foo"), [pgenh("1", "bar")])
  364. node28 = Template(wraptext("foo"), [pgenh("1", "bar")])
  365. node2.remove("1")
  366. node2.remove("abc")
  367. node3.remove(1, keep_field=True)
  368. node3.remove("abc", keep_field=True)
  369. node4.remove("1", keep_field=False)
  370. node5.remove("a", keep_field=False)
  371. node6.remove("a", keep_field=True)
  372. node7.remove(1, keep_field=True)
  373. node8.remove(1, keep_field=False)
  374. node9.remove(1, keep_field=True)
  375. node10.remove(1, keep_field=False)
  376. node11.remove(node11.params[0], keep_field=False)
  377. node12.remove(node12.params[0], keep_field=True)
  378. node13.remove(node13.params[1], keep_field=False)
  379. node14.remove(node14.params[1], keep_field=True)
  380. node15.remove(node15.params[2], keep_field=False)
  381. node16.remove(node16.params[2], keep_field=True)
  382. node17.remove(node17.params[0], keep_field=False)
  383. node18.remove(node18.params[0], keep_field=True)
  384. node19.remove(node19.params[1], keep_field=False)
  385. node20.remove(node20.params[1], keep_field=True)
  386. node21.remove("a", keep_field=False)
  387. node22.remove("a", keep_field=True)
  388. node23.remove(node23.params[0], keep_field=False)
  389. node24.remove(node24.params[0], keep_field=True)
  390. node25.remove(node25.params[3], keep_field=False)
  391. node26.remove(node26.params[3], keep_field=True)
  392. self.assertRaises(ValueError, node1.remove, 1)
  393. self.assertRaises(ValueError, node1.remove, "a")
  394. self.assertRaises(ValueError, node2.remove, "1")
  395. self.assertEqual("{{foo}}", node2)
  396. self.assertEqual("{{foo||abc=}}", node3)
  397. self.assertEqual("{{foo|2=baz}}", node4)
  398. self.assertEqual("{{foo|b=c}}", node5)
  399. self.assertEqual("{{foo| a=|b=c}}", node6)
  400. self.assertEqual("{{foo|1 =|2=c}}", node7)
  401. self.assertEqual("{{foo|2=c}}", node8)
  402. self.assertEqual("{{foo||c}}", node9)
  403. self.assertEqual("{{foo|2=c}}", node10)
  404. self.assertEqual("{{foo|b=c|a =d}}", node11)
  405. self.assertEqual("{{foo| a=|b=c|a =d}}", node12)
  406. self.assertEqual("{{foo| a=b|a =d}}", node13)
  407. self.assertEqual("{{foo| a=b|b=|a =d}}", node14)
  408. self.assertEqual("{{foo| a=b|b=c}}", node15)
  409. self.assertEqual("{{foo| a=b|b=c|a =}}", node16)
  410. self.assertEqual("{{foo|b|c}}", node17)
  411. self.assertEqual("{{foo|1 =|b|c}}", node18)
  412. self.assertEqual("{{foo|1 =a|2=c}}", node19)
  413. self.assertEqual("{{foo|1 =a||c}}", node20)
  414. self.assertEqual("{{foo|c=d|e=f}}", node21)
  415. self.assertEqual("{{foo|a=|c=d|e=f}}", node22)
  416. self.assertEqual("{{foo|c=d|e=f|a=b|a=b}}", node23)
  417. self.assertEqual("{{foo|a=|c=d|e=f|a=b|a=b}}", node24)
  418. self.assertEqual("{{foo|a=b|c=d|e=f|a=b}}", node25)
  419. self.assertEqual("{{foo|a=b|c=d|e=f|a=|a=b}}", node26)
  420. self.assertRaises(ValueError, node27.remove, node28.get(1))
  421. def test_formatting(self):
  422. """test realistic param manipulation with complex whitespace formatting
  423. (assumes that parsing works correctly)"""
  424. tests = [
  425. # https://en.wikipedia.org/w/index.php?title=Lamar_County,_Georgia&oldid=792356004
  426. ("""{{Infobox U.S. county
  427. | county = Lamar County
  428. | state = Georgia
  429. | seal =
  430. | founded = 1920
  431. | seat wl = Barnesville
  432. | largest city wl = Barnesville
  433. | area_total_sq_mi = 186
  434. | area_land_sq_mi = 184
  435. | area_water_sq_mi = 2.3
  436. | area percentage = 1.3%
  437. | census yr = 2010
  438. | pop = 18317
  439. | density_sq_mi = 100
  440. | time zone = Eastern
  441. | footnotes =
  442. | web = www.lamarcountyga.com
  443. | ex image = Lamar County Georgia Courthouse.jpg
  444. | ex image cap = Lamar County courthouse in Barnesville
  445. | district = 3rd
  446. | named for = [[Lucius Quintus Cincinnatus Lamar II]]
  447. }}""", """{{Infobox U.S. county
  448. | county = Lamar County
  449. | state = Georgia
  450. | seal =
  451. | founded = 1920
  452. | seat wl = Barnesville
  453. | largest city wl = Barnesville
  454. | area_total_sq_mi = 186
  455. | area_land_sq_mi = 184
  456. | area_water_sq_mi = 2.3
  457. | area percentage = 1.3%
  458. | census estimate yr = 2016
  459. | pop = 12345<ref>example ref</ref>
  460. | density_sq_mi = 100
  461. | time zone = Eastern
  462. | footnotes =
  463. | web = www.lamarcountyga.com
  464. | ex image = Lamar County Georgia Courthouse.jpg
  465. | ex image cap = Lamar County courthouse in Barnesville
  466. | district = 3rd
  467. | named for = [[Lucius Quintus Cincinnatus Lamar II]]
  468. }}"""),
  469. # https://en.wikipedia.org/w/index.php?title=Rockdale_County,_Georgia&oldid=792359760
  470. ("""{{Infobox U.S. County|
  471. county = Rockdale County |
  472. state = Georgia |
  473. seal = |
  474. founded = October 18, 1870 |
  475. seat wl = Conyers |
  476. largest city wl = Conyers |
  477. area_total_sq_mi = 132 |
  478. area_land_sq_mi = 130 |
  479. area_water_sq_mi = 2.3 |
  480. area percentage = 1.7% |
  481. census yr = 2010|
  482. pop = 85215 |
  483. density_sq_mi = 657 |
  484. web = www.rockdalecounty.org
  485. | ex image = Rockdale-county-courthouse.jpg
  486. | ex image cap = Rockdale County Courthouse in Conyers
  487. | district = 4th
  488. | time zone= Eastern
  489. }}""", """{{Infobox U.S. County|
  490. county = Rockdale County |
  491. state = Georgia |
  492. seal = |
  493. founded = October 18, 1870 |
  494. seat wl = Conyers |
  495. largest city wl = Conyers |
  496. area_total_sq_mi = 132 |
  497. area_land_sq_mi = 130 |
  498. area_water_sq_mi = 2.3 |
  499. area percentage = 1.7% |
  500. census estimate yr = 2016 |
  501. pop = 12345<ref>example ref</ref> |
  502. density_sq_mi = 657 |
  503. web = www.rockdalecounty.org
  504. | ex image = Rockdale-county-courthouse.jpg
  505. | ex image cap = Rockdale County Courthouse in Conyers
  506. | district = 4th
  507. | time zone= Eastern
  508. }}"""),
  509. # https://en.wikipedia.org/w/index.php?title=Spalding_County,_Georgia&oldid=792360413
  510. ("""{{Infobox U.S. County|
  511. | county = Spalding County |
  512. | state = Georgia |
  513. | seal = |
  514. | founded = 1851 |
  515. | seat wl = Griffin |
  516. | largest city wl = Griffin |
  517. | area_total_sq_mi = 200 |
  518. | area_land_sq_mi = 196 |
  519. | area_water_sq_mi = 3.1 |
  520. | area percentage = 1.6% |
  521. | census yr = 2010|
  522. | pop = 64073 |
  523. | density_sq_mi = 326 |
  524. | web = www.spaldingcounty.com |
  525. | named for = [[Thomas Spalding]]
  526. | ex image = Spalding County Courthouse (NE corner).JPG
  527. | ex image cap = Spalding County Courthouse in Griffin
  528. | district = 3rd
  529. | time zone = Eastern
  530. }}""", """{{Infobox U.S. County|
  531. | county = Spalding County |
  532. | state = Georgia |
  533. | seal = |
  534. | founded = 1851 |
  535. | seat wl = Griffin |
  536. | largest city wl = Griffin |
  537. | area_total_sq_mi = 200 |
  538. | area_land_sq_mi = 196 |
  539. | area_water_sq_mi = 3.1 |
  540. | area percentage = 1.6% |
  541. |
  542. | census estimate yr = 2016 | pop = 12345<ref>example ref</ref> |
  543. | density_sq_mi = 326 |
  544. | web = www.spaldingcounty.com |
  545. | named for = [[Thomas Spalding]]
  546. | ex image = Spalding County Courthouse (NE corner).JPG
  547. | ex image cap = Spalding County Courthouse in Griffin
  548. | district = 3rd
  549. | time zone = Eastern
  550. }}"""),
  551. # https://en.wikipedia.org/w/index.php?title=Clinton_County,_Illinois&oldid=794694648
  552. ("""{{Infobox U.S. county
  553. |county = Clinton County
  554. |state = Illinois
  555. | ex image = File:Clinton County Courthouse, Carlyle.jpg
  556. | ex image cap = [[Clinton County Courthouse (Illinois)|Clinton County Courthouse]]
  557. |seal =
  558. |founded = 1824
  559. |named for = [[DeWitt Clinton]]
  560. |seat wl= Carlyle
  561. | largest city wl = Breese
  562. |time zone=Central
  563. |area_total_sq_mi = 503
  564. |area_land_sq_mi = 474
  565. |area_water_sq_mi = 29
  566. |area percentage = 5.8%
  567. |census yr = 2010
  568. |pop = 37762
  569. |density_sq_mi = 80
  570. |web = www.clintonco.illinois.gov
  571. | district = 15th
  572. }}""", """{{Infobox U.S. county
  573. |county = Clinton County
  574. |state = Illinois
  575. | ex image = File:Clinton County Courthouse, Carlyle.jpg
  576. | ex image cap = [[Clinton County Courthouse (Illinois)|Clinton County Courthouse]]
  577. |seal =
  578. |founded = 1824
  579. |named for = [[DeWitt Clinton]]
  580. |seat wl= Carlyle
  581. | largest city wl = Breese
  582. |time zone=Central
  583. |area_total_sq_mi = 503
  584. |area_land_sq_mi = 474
  585. |area_water_sq_mi = 29
  586. |area percentage = 5.8%
  587. |census estimate yr = 2016
  588. |pop = 12345<ref>example ref</ref>
  589. |density_sq_mi = 80
  590. |web = www.clintonco.illinois.gov
  591. | district = 15th
  592. }}"""),
  593. # https://en.wikipedia.org/w/index.php?title=Winnebago_County,_Illinois&oldid=789193800
  594. ("""{{Infobox U.S. county |
  595. county = Winnebago County |
  596. state = Illinois |
  597. seal = Winnebago County il seal.png |
  598. named for = [[Winnebago (tribe)|Winnebago Tribe]] |
  599. seat wl= Rockford |
  600. largest city wl = Rockford|
  601. area_total_sq_mi = 519 |
  602. area_land_sq_mi = 513|
  603. area_water_sq_mi = 5.9 |
  604. area percentage = 1.1% |
  605. census yr = 2010|
  606. pop = 295266 |
  607. density_sq_mi = 575
  608. | web = www.wincoil.us
  609. | founded year = 1836
  610. | founded date = January 16
  611. | time zone = Central
  612. | district = 16th
  613. | district2 = 17th
  614. }}""", """{{Infobox U.S. county |
  615. county = Winnebago County |
  616. state = Illinois |
  617. seal = Winnebago County il seal.png |
  618. named for = [[Winnebago (tribe)|Winnebago Tribe]] |
  619. seat wl= Rockford |
  620. largest city wl = Rockford|
  621. area_total_sq_mi = 519 |
  622. area_land_sq_mi = 513|
  623. area_water_sq_mi = 5.9 |
  624. area percentage = 1.1% |
  625. census estimate yr = 2016|
  626. pop = 12345<ref>example ref</ref> |
  627. density_sq_mi = 575
  628. | web = www.wincoil.us
  629. | founded year = 1836
  630. | founded date = January 16
  631. | time zone = Central
  632. | district = 16th
  633. | district2 = 17th
  634. }}""")]
  635. for (original, expected) in tests:
  636. code = parse(original)
  637. template = code.filter_templates()[0]
  638. template.add("pop", "12345<ref>example ref</ref>")
  639. template.add('census estimate yr', "2016", before="pop")
  640. template.remove("census yr")
  641. self.assertEqual(expected, str(code))
  642. if __name__ == "__main__":
  643. unittest.main(verbosity=2)