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.
 
 
 
 

357 regels
18 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 unittest
  24. from mwparserfromhell.compat import str
  25. from mwparserfromhell.nodes import HTMLEntity, Template, Text
  26. from mwparserfromhell.nodes.extras import Parameter
  27. from mwparserfromhell.smart_list import SmartList
  28. from mwparserfromhell.wikicode import Wikicode
  29. from ._test_tree_equality import TreeEqualityTestCase
  30. wrap = lambda L: Wikicode(SmartList(L))
  31. wraptext = lambda t: wrap([Text(t)])
  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_strip(self):
  44. """test Template.__strip__()"""
  45. node1 = Template(wraptext("foobar"))
  46. node2 = Template(wraptext("foo"),
  47. [pgenh("1", "bar"), pgens("abc", "def")])
  48. for a in (True, False):
  49. for b in (True, False):
  50. self.assertEqual(None, node1.__strip__(a, b))
  51. self.assertEqual(None, node2.__strip__(a, b))
  52. def test_showtree(self):
  53. """test Template.__showtree__()"""
  54. output = []
  55. getter, marker = object(), object()
  56. get = lambda code: output.append((getter, code))
  57. mark = lambda: output.append(marker)
  58. node1 = Template(wraptext("foobar"))
  59. node2 = Template(wraptext("foo"),
  60. [pgenh("1", "bar"), pgens("abc", "def")])
  61. node1.__showtree__(output.append, get, mark)
  62. node2.__showtree__(output.append, get, mark)
  63. valid = [
  64. "{{", (getter, node1.name), "}}", "{{", (getter, node2.name),
  65. " | ", marker, (getter, node2.params[0].name), " = ", marker,
  66. (getter, node2.params[0].value), " | ", marker,
  67. (getter, node2.params[1].name), " = ", marker,
  68. (getter, node2.params[1].value), "}}"]
  69. self.assertEqual(valid, output)
  70. def test_name(self):
  71. """test getter/setter for the name attribute"""
  72. name = wraptext("foobar")
  73. node1 = Template(name)
  74. node2 = Template(name, [pgenh("1", "bar")])
  75. self.assertIs(name, node1.name)
  76. self.assertIs(name, node2.name)
  77. node1.name = "asdf"
  78. node2.name = "téstïng"
  79. self.assertWikicodeEqual(wraptext("asdf"), node1.name)
  80. self.assertWikicodeEqual(wraptext("téstïng"), node2.name)
  81. def test_params(self):
  82. """test getter for the params attribute"""
  83. node1 = Template(wraptext("foobar"))
  84. plist = [pgenh("1", "bar"), pgens("abc", "def")]
  85. node2 = Template(wraptext("foo"), plist)
  86. self.assertEqual([], node1.params)
  87. self.assertIs(plist, node2.params)
  88. def test_has_param(self):
  89. """test Template.has_param()"""
  90. node1 = Template(wraptext("foobar"))
  91. node2 = Template(wraptext("foo"),
  92. [pgenh("1", "bar"), pgens("\nabc ", "def")])
  93. node3 = Template(wraptext("foo"),
  94. [pgenh("1", "a"), pgens("b", "c"), pgens("1", "d")])
  95. node4 = Template(wraptext("foo"), [pgenh("1", "a"), pgens("b", " ")])
  96. self.assertFalse(node1.has_param("foobar"))
  97. self.assertTrue(node2.has_param(1))
  98. self.assertTrue(node2.has_param("abc"))
  99. self.assertFalse(node2.has_param("def"))
  100. self.assertTrue(node3.has_param("1"))
  101. self.assertTrue(node3.has_param(" b "))
  102. self.assertFalse(node4.has_param("b"))
  103. self.assertTrue(node3.has_param("b", False))
  104. self.assertTrue(node4.has_param("b", False))
  105. def test_get(self):
  106. """test Template.get()"""
  107. node1 = Template(wraptext("foobar"))
  108. node2p1 = pgenh("1", "bar")
  109. node2p2 = pgens("abc", "def")
  110. node2 = Template(wraptext("foo"), [node2p1, node2p2])
  111. node3p1 = pgens("b", "c")
  112. node3p2 = pgens("1", "d")
  113. node3 = Template(wraptext("foo"), [pgenh("1", "a"), node3p1, node3p2])
  114. node4p1 = pgens(" b", " ")
  115. node4 = Template(wraptext("foo"), [pgenh("1", "a"), node4p1])
  116. self.assertRaises(ValueError, node1.get, "foobar")
  117. self.assertIs(node2p1, node2.get(1))
  118. self.assertIs(node2p2, node2.get("abc"))
  119. self.assertRaises(ValueError, node2.get, "def")
  120. self.assertIs(node3p1, node3.get("b"))
  121. self.assertIs(node3p2, node3.get("1"))
  122. self.assertIs(node4p1, node4.get("b "))
  123. def test_add(self):
  124. """test Template.add()"""
  125. node1 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  126. node2 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  127. node3 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  128. node4 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  129. node5 = Template(wraptext("a"), [pgens("b", "c"),
  130. pgens(" d ", "e")])
  131. node6 = Template(wraptext("a"), [pgens("b", "c"), pgens("b", "d"),
  132. pgens("b", "e")])
  133. node7 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  134. node8p = pgenh("1", "d")
  135. node8 = Template(wraptext("a"), [pgens("b", "c"), node8p])
  136. node9 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  137. node10 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "e")])
  138. node11 = Template(wraptext("a"), [pgens("b", "c")])
  139. node12 = Template(wraptext("a"), [pgens("b", "c")])
  140. node13 = Template(wraptext("a"), [pgens("\nb ", " c"),
  141. pgens("\nd ", " e"),
  142. pgens("\nf ", " g")])
  143. node14 = Template(wraptext("a\n"), [pgens("b ", "c\n"),
  144. pgens("d ", " e"),
  145. pgens("f ", "g\n"),
  146. pgens("h ", " i\n")])
  147. node15 = Template(wraptext("a"), [pgens("b ", " c\n"),
  148. pgens("\nd ", " e"),
  149. pgens("\nf ", "g ")])
  150. node16 = Template(wraptext("a"), [pgens("\nb ", " c"),
  151. pgens("\nd ", " e"),
  152. pgens("\nf ", " g")])
  153. node17 = Template(wraptext("a"), [pgens("\nb ", " c"),
  154. pgens("\nd ", " e"),
  155. pgens("\nf ", " g")])
  156. node18 = Template(wraptext("a\n"), [pgens("b ", "c\n"),
  157. pgens("d ", " e"),
  158. pgens("f ", "g\n"),
  159. pgens("h ", " i\n")])
  160. node19 = Template(wraptext("a"), [pgens("b ", " c\n"),
  161. pgens("\nd ", " e"),
  162. pgens("\nf ", "g ")])
  163. node20 = Template(wraptext("a"), [pgens("\nb ", " c"),
  164. pgens("\nd ", " e"),
  165. pgens("\nf ", " g")])
  166. node21 = Template(wraptext("a"), [pgenh("1", "b")])
  167. node22 = Template(wraptext("a"), [pgenh("1", "b")])
  168. node23 = Template(wraptext("a"), [pgenh("1", "b")])
  169. node24 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
  170. pgenh("3", "d"), pgenh("4", "e")])
  171. node25 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
  172. pgens("4", "d"), pgens("5", "e")])
  173. node26 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
  174. pgens("4", "d"), pgens("5", "e")])
  175. node27 = Template(wraptext("a"), [pgenh("1", "b")])
  176. node28 = Template(wraptext("a"), [pgenh("1", "b")])
  177. node29 = Template(wraptext("a"), [pgens("b", "c")])
  178. node30 = Template(wraptext("a"), [pgenh("1", "b")])
  179. node31 = Template(wraptext("a"), [pgenh("1", "b")])
  180. node32 = Template(wraptext("a"), [pgens("1", "b")])
  181. node33 = Template(wraptext("a"), [pgens("\nb ", " c"),
  182. pgens("\nd ", " e"),
  183. pgens("\nf ", " g")])
  184. node34 = Template(wraptext("a\n"), [pgens("b ", "c\n"),
  185. pgens("d ", " e"),
  186. pgens("f ", "g\n"),
  187. pgens("h ", " i\n")])
  188. node35 = Template(wraptext("a"), [pgens("b ", " c\n"),
  189. pgens("\nd ", " e"),
  190. pgens("\nf ", "g ")])
  191. node36 = Template(wraptext("a"), [pgens("\nb ", " c "),
  192. pgens("\nd ", " e "),
  193. pgens("\nf ", " g ")])
  194. node37 = Template(wraptext("a"), [pgens("b", "c"), pgens("d", "e"),
  195. pgens("b", "f"), pgens("b", "h"),
  196. pgens("i", "j")])
  197. node37 = Template(wraptext("a"), [pgens("b", "c"), pgens("d", "e"),
  198. pgens("b", "f"), pgens("b", "h"),
  199. pgens("i", "j")])
  200. node38 = Template(wraptext("a"), [pgens("1", "b"), pgens("x", "y"),
  201. pgens("1", "c"), pgens("2", "d")])
  202. node39 = Template(wraptext("a"), [pgens("1", "b"), pgens("x", "y"),
  203. pgenh("1", "c"), pgenh("2", "d")])
  204. node40 = Template(wraptext("a"), [pgens("b", "c"), pgens("d", "e"),
  205. pgens("f", "g")])
  206. node1.add("e", "f", showkey=True)
  207. node2.add(2, "g", showkey=False)
  208. node3.add("e", "foo|bar", showkey=True)
  209. node4.add("e", "f", showkey=True, before="b")
  210. node5.add("f", "g", showkey=True, before=" d ")
  211. node6.add("f", "g", showkey=True, before="b")
  212. self.assertRaises(ValueError, node7.add, "e", "f", showkey=True,
  213. before="q")
  214. node8.add("e", "f", showkey=True, before=node8p)
  215. node9.add("e", "f", showkey=True, before=pgenh("1", "d"))
  216. self.assertRaises(ValueError, node10.add, "e", "f", showkey=True,
  217. before=pgenh("1", "d"))
  218. node11.add("d", "foo=bar", showkey=True)
  219. node12.add("1", "foo=bar", showkey=False)
  220. node13.add("h", "i", showkey=True)
  221. node14.add("j", "k", showkey=True)
  222. node15.add("h", "i", showkey=True)
  223. node16.add("h", "i", showkey=True, preserve_spacing=False)
  224. node17.add("h", "i", showkey=False)
  225. node18.add("j", "k", showkey=False)
  226. node19.add("h", "i", showkey=False)
  227. node20.add("h", "i", showkey=False, preserve_spacing=False)
  228. node21.add("2", "c")
  229. node22.add("3", "c")
  230. node23.add("c", "d")
  231. node24.add("5", "f")
  232. node25.add("3", "f")
  233. node26.add("6", "f")
  234. node27.add("c", "foo=bar")
  235. node28.add("2", "foo=bar")
  236. node29.add("b", "d")
  237. node30.add("1", "foo=bar")
  238. node31.add("1", "foo=bar", showkey=True)
  239. node32.add("1", "foo=bar", showkey=False)
  240. node33.add("d", "foo")
  241. node34.add("f", "foo")
  242. node35.add("f", "foo")
  243. node36.add("d", "foo", preserve_spacing=False)
  244. node37.add("b", "k")
  245. node38.add("1", "e")
  246. node39.add("1", "e")
  247. node40.add("d", "h", before="b")
  248. self.assertEqual("{{a|b=c|d|e=f}}", node1)
  249. self.assertEqual("{{a|b=c|d|g}}", node2)
  250. self.assertEqual("{{a|b=c|d|e=foo&#124;bar}}", node3)
  251. self.assertIsInstance(node3.params[2].value.get(1), HTMLEntity)
  252. self.assertEqual("{{a|e=f|b=c|d}}", node4)
  253. self.assertEqual("{{a|b=c|f=g| d =e}}", node5)
  254. self.assertEqual("{{a|b=c|b=d|f=g|b=e}}", node6)
  255. self.assertEqual("{{a|b=c|d}}", node7)
  256. self.assertEqual("{{a|b=c|e=f|d}}", node8)
  257. self.assertEqual("{{a|b=c|e=f|d}}", node9)
  258. self.assertEqual("{{a|b=c|e}}", node10)
  259. self.assertEqual("{{a|b=c|d=foo=bar}}", node11)
  260. self.assertEqual("{{a|b=c|foo&#61;bar}}", node12)
  261. self.assertIsInstance(node12.params[1].value.get(1), HTMLEntity)
  262. self.assertEqual("{{a|\nb = c|\nd = e|\nf = g|\nh = i}}", node13)
  263. self.assertEqual("{{a\n|b =c\n|d = e|f =g\n|h = i\n|j =k\n}}", node14)
  264. self.assertEqual("{{a|b = c\n|\nd = e|\nf =g |h =i}}", node15)
  265. self.assertEqual("{{a|\nb = c|\nd = e|\nf = g|h=i}}", node16)
  266. self.assertEqual("{{a|\nb = c|\nd = e|\nf = g| i}}", node17)
  267. self.assertEqual("{{a\n|b =c\n|d = e|f =g\n|h = i\n|k\n}}", node18)
  268. self.assertEqual("{{a|b = c\n|\nd = e|\nf =g |i}}", node19)
  269. self.assertEqual("{{a|\nb = c|\nd = e|\nf = g|i}}", node20)
  270. self.assertEqual("{{a|b|c}}", node21)
  271. self.assertEqual("{{a|b|3=c}}", node22)
  272. self.assertEqual("{{a|b|c=d}}", node23)
  273. self.assertEqual("{{a|b|c|d|e|f}}", node24)
  274. self.assertEqual("{{a|b|c|4=d|5=e|f}}", node25)
  275. self.assertEqual("{{a|b|c|4=d|5=e|6=f}}", node26)
  276. self.assertEqual("{{a|b|c=foo=bar}}", node27)
  277. self.assertEqual("{{a|b|foo&#61;bar}}", node28)
  278. self.assertIsInstance(node28.params[1].value.get(1), HTMLEntity)
  279. self.assertEqual("{{a|b=d}}", node29)
  280. self.assertEqual("{{a|foo&#61;bar}}", node30)
  281. self.assertIsInstance(node30.params[0].value.get(1), HTMLEntity)
  282. self.assertEqual("{{a|1=foo=bar}}", node31)
  283. self.assertEqual("{{a|foo&#61;bar}}", node32)
  284. self.assertIsInstance(node32.params[0].value.get(1), HTMLEntity)
  285. self.assertEqual("{{a|\nb = c|\nd = foo|\nf = g}}", node33)
  286. self.assertEqual("{{a\n|b =c\n|d = e|f =foo\n|h = i\n}}", node34)
  287. self.assertEqual("{{a|b = c\n|\nd = e|\nf =foo }}", node35)
  288. self.assertEqual("{{a|\nb = c |\nd =foo|\nf = g }}", node36)
  289. self.assertEqual("{{a|b=k|d=e|i=j}}", node37)
  290. self.assertEqual("{{a|1=e|x=y|2=d}}", node38)
  291. self.assertEqual("{{a|x=y|e|d}}", node39)
  292. self.assertEqual("{{a|b=c|d=h|f=g}}", node40)
  293. def test_remove(self):
  294. """test Template.remove()"""
  295. node1 = Template(wraptext("foobar"))
  296. node2 = Template(wraptext("foo"), [pgenh("1", "bar"),
  297. pgens("abc", "def")])
  298. node3 = Template(wraptext("foo"), [pgenh("1", "bar"),
  299. pgens("abc", "def")])
  300. node4 = Template(wraptext("foo"), [pgenh("1", "bar"),
  301. pgenh("2", "baz")])
  302. node5 = Template(wraptext("foo"), [
  303. pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
  304. node6 = Template(wraptext("foo"), [
  305. pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
  306. node7 = Template(wraptext("foo"), [
  307. pgens("1 ", "a"), pgens(" 1", "b"), pgens("2", "c")])
  308. node8 = Template(wraptext("foo"), [
  309. pgens("1 ", "a"), pgens(" 1", "b"), pgens("2", "c")])
  310. node9 = Template(wraptext("foo"), [
  311. pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])
  312. node10 = Template(wraptext("foo"), [
  313. pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])
  314. node2.remove("1")
  315. node2.remove("abc")
  316. node3.remove(1, keep_field=True)
  317. node3.remove("abc", keep_field=True)
  318. node4.remove("1", keep_field=False)
  319. node5.remove("a", keep_field=False)
  320. node6.remove("a", keep_field=True)
  321. node7.remove(1, keep_field=True)
  322. node8.remove(1, keep_field=False)
  323. node9.remove(1, keep_field=True)
  324. node10.remove(1, keep_field=False)
  325. self.assertRaises(ValueError, node1.remove, 1)
  326. self.assertRaises(ValueError, node1.remove, "a")
  327. self.assertRaises(ValueError, node2.remove, "1")
  328. self.assertEqual("{{foo}}", node2)
  329. self.assertEqual("{{foo||abc=}}", node3)
  330. self.assertEqual("{{foo||baz}}", node4)
  331. self.assertEqual("{{foo|b=c}}", node5)
  332. self.assertEqual("{{foo| a=|b=c}}", node6)
  333. self.assertEqual("{{foo|1 =|2=c}}", node7)
  334. self.assertEqual("{{foo|2=c}}", node8)
  335. self.assertEqual("{{foo||c}}", node9)
  336. self.assertEqual("{{foo||c}}", node10)
  337. if __name__ == "__main__":
  338. unittest.main(verbosity=2)