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.
 
 
 
 

613 lines
25 KiB

  1. #
  2. # Copyright (C) 2012-2017 Ben Kurtovic <ben.kurtovic@gmail.com>
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to deal
  6. # in the Software without restriction, including without limitation the rights
  7. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. # SOFTWARE.
  21. from difflib import unified_diff
  22. import pytest
  23. from mwparserfromhell.nodes import HTMLEntity, Template, Text
  24. from mwparserfromhell.nodes.extras import Parameter
  25. from mwparserfromhell import parse
  26. from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext
  27. pgens = lambda k, v: Parameter(wraptext(k), wraptext(v), showkey=True)
  28. pgenh = lambda k, v: Parameter(wraptext(k), wraptext(v), showkey=False)
  29. class TestTemplate(TreeEqualityTestCase):
  30. """Test cases for the Template node."""
  31. def test_unicode(self):
  32. """test Template.__unicode__()"""
  33. node = Template(wraptext("foobar"))
  34. assert "{{foobar}}" == str(node)
  35. node2 = Template(wraptext("foo"),
  36. [pgenh("1", "bar"), pgens("abc", "def")])
  37. assert "{{foo|bar|abc=def}}" == str(node2)
  38. def test_children(self):
  39. """test Template.__children__()"""
  40. node2p1 = Parameter(wraptext("1"), wraptext("bar"), showkey=False)
  41. node2p2 = Parameter(wraptext("abc"), wrap([Text("def"), Text("ghi")]),
  42. showkey=True)
  43. node1 = Template(wraptext("foobar"))
  44. node2 = Template(wraptext("foo"), [node2p1, node2p2])
  45. gen1 = node1.__children__()
  46. gen2 = node2.__children__()
  47. assert node1.name == next(gen1)
  48. assert node2.name == next(gen2)
  49. assert node2.params[0].value == next(gen2)
  50. assert node2.params[1].name == next(gen2)
  51. assert node2.params[1].value == next(gen2)
  52. with pytest.raises(StopIteration):
  53. next(gen1)
  54. with pytest.raises(StopIteration):
  55. next(gen2)
  56. def test_strip(self):
  57. """test Template.__strip__()"""
  58. node1 = Template(wraptext("foobar"))
  59. node2 = Template(wraptext("foo"), [
  60. pgenh("1", "bar"), pgens("foo", ""), pgens("abc", "def")])
  61. node3 = Template(wraptext("foo"), [
  62. pgenh("1", "foo"),
  63. Parameter(wraptext("2"), wrap([Template(wraptext("hello"))]),
  64. showkey=False),
  65. pgenh("3", "bar")])
  66. assert node1.__strip__(keep_template_params=False) is None
  67. assert node2.__strip__(keep_template_params=False) is None
  68. assert "" == node1.__strip__(keep_template_params=True)
  69. assert "bar def" == node2.__strip__(keep_template_params=True)
  70. assert "foo bar" == node3.__strip__(keep_template_params=True)
  71. def test_showtree(self):
  72. """test Template.__showtree__()"""
  73. output = []
  74. getter, marker = object(), object()
  75. get = lambda code: output.append((getter, code))
  76. mark = lambda: output.append(marker)
  77. node1 = Template(wraptext("foobar"))
  78. node2 = Template(wraptext("foo"),
  79. [pgenh("1", "bar"), pgens("abc", "def")])
  80. node1.__showtree__(output.append, get, mark)
  81. node2.__showtree__(output.append, get, mark)
  82. valid = [
  83. "{{", (getter, node1.name), "}}", "{{", (getter, node2.name),
  84. " | ", marker, (getter, node2.params[0].name), " = ", marker,
  85. (getter, node2.params[0].value), " | ", marker,
  86. (getter, node2.params[1].name), " = ", marker,
  87. (getter, node2.params[1].value), "}}"]
  88. assert valid == output
  89. def test_name(self):
  90. """test getter/setter for the name attribute"""
  91. name = wraptext("foobar")
  92. node1 = Template(name)
  93. node2 = Template(name, [pgenh("1", "bar")])
  94. assert name is node1.name
  95. assert name is node2.name
  96. node1.name = "asdf"
  97. node2.name = "téstïng"
  98. self.assertWikicodeEqual(wraptext("asdf"), node1.name)
  99. self.assertWikicodeEqual(wraptext("téstïng"), node2.name)
  100. def test_params(self):
  101. """test getter for the params attribute"""
  102. node1 = Template(wraptext("foobar"))
  103. plist = [pgenh("1", "bar"), pgens("abc", "def")]
  104. node2 = Template(wraptext("foo"), plist)
  105. assert [] == node1.params
  106. assert plist is node2.params
  107. def test_has(self):
  108. """test Template.has()"""
  109. node1 = Template(wraptext("foobar"))
  110. node2 = Template(wraptext("foo"),
  111. [pgenh("1", "bar"), pgens("\nabc ", "def")])
  112. node3 = Template(wraptext("foo"),
  113. [pgenh("1", "a"), pgens("b", "c"), pgens("1", "d")])
  114. node4 = Template(wraptext("foo"), [pgenh("1", "a"), pgens("b", " ")])
  115. assert node1.has("foobar", False) is False
  116. assert node2.has(1, False) is True
  117. assert node2.has("abc", False) is True
  118. assert node2.has("def", False) is False
  119. assert node3.has("1", False) is True
  120. assert node3.has(" b ", False) is True
  121. assert node4.has("b", False) is True
  122. assert node3.has("b", True) is True
  123. assert node4.has("b", True) is False
  124. assert node1.has_param("foobar", False) is False
  125. assert node2.has_param(1, False) is True
  126. def test_get(self):
  127. """test Template.get()"""
  128. node1 = Template(wraptext("foobar"))
  129. node2p1 = pgenh("1", "bar")
  130. node2p2 = pgens("abc", "def")
  131. node2 = Template(wraptext("foo"), [node2p1, node2p2])
  132. node3p1 = pgens("b", "c")
  133. node3p2 = pgens("1", "d")
  134. node3 = Template(wraptext("foo"), [pgenh("1", "a"), node3p1, node3p2])
  135. node4p1 = pgens(" b", " ")
  136. node4 = Template(wraptext("foo"), [pgenh("1", "a"), node4p1])
  137. with pytest.raises(ValueError):
  138. node1.get("foobar")
  139. assert node2p1 is node2.get(1)
  140. assert node2p2 is node2.get("abc")
  141. with pytest.raises(ValueError):
  142. node2.get("def")
  143. assert node3p1 is node3.get("b")
  144. assert node3p2 is node3.get("1")
  145. assert node4p1 is node4.get("b ")
  146. def test_add(self):
  147. """test Template.add()"""
  148. node1 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  149. node2 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  150. node3 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  151. node4 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  152. node5 = Template(wraptext("a"), [pgens("b", "c"),
  153. pgens(" d ", "e")])
  154. node6 = Template(wraptext("a"), [pgens("b", "c"), pgens("b", "d"),
  155. pgens("b", "e")])
  156. node7 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  157. node8p = pgenh("1", "d")
  158. node8 = Template(wraptext("a"), [pgens("b", "c"), node8p])
  159. node9 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
  160. node10 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "e")])
  161. node11 = Template(wraptext("a"), [pgens("b", "c")])
  162. node12 = Template(wraptext("a"), [pgens("b", "c")])
  163. node13 = Template(wraptext("a"), [
  164. pgens("\nb ", " c"), pgens("\nd ", " e"), pgens("\nf ", " g")])
  165. node14 = Template(wraptext("a\n"), [
  166. pgens("b ", "c\n"), pgens("d ", " e"), pgens("f ", "g\n"),
  167. pgens("h ", " i\n")])
  168. node15 = Template(wraptext("a"), [
  169. pgens("b ", " c\n"), pgens("\nd ", " e"), pgens("\nf ", "g ")])
  170. node16 = Template(wraptext("a"), [
  171. pgens("\nb ", " c"), pgens("\nd ", " e"), pgens("\nf ", " g")])
  172. node17 = Template(wraptext("a"), [pgenh("1", "b")])
  173. node18 = Template(wraptext("a"), [pgenh("1", "b")])
  174. node19 = Template(wraptext("a"), [pgenh("1", "b")])
  175. node20 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
  176. pgenh("3", "d"), pgenh("4", "e")])
  177. node21 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
  178. pgens("4", "d"), pgens("5", "e")])
  179. node22 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
  180. pgens("4", "d"), pgens("5", "e")])
  181. node23 = Template(wraptext("a"), [pgenh("1", "b")])
  182. node24 = Template(wraptext("a"), [pgenh("1", "b")])
  183. node25 = Template(wraptext("a"), [pgens("b", "c")])
  184. node26 = Template(wraptext("a"), [pgenh("1", "b")])
  185. node27 = Template(wraptext("a"), [pgenh("1", "b")])
  186. node28 = Template(wraptext("a"), [pgens("1", "b")])
  187. node29 = Template(wraptext("a"), [
  188. pgens("\nb ", " c"), pgens("\nd ", " e"), pgens("\nf ", " g")])
  189. node30 = Template(wraptext("a\n"), [
  190. pgens("b ", "c\n"), pgens("d ", " e"), pgens("f ", "g\n"),
  191. pgens("h ", " i\n")])
  192. node31 = Template(wraptext("a"), [
  193. pgens("b ", " c\n"), pgens("\nd ", " e"), pgens("\nf ", "g ")])
  194. node32 = Template(wraptext("a"), [
  195. pgens("\nb ", " c "), pgens("\nd ", " e "), pgens("\nf ", " g ")])
  196. node33 = Template(wraptext("a"), [pgens("b", "c"), pgens("d", "e"),
  197. pgens("b", "f"), pgens("b", "h"),
  198. pgens("i", "j")])
  199. node34 = Template(wraptext("a"), [pgens("1", "b"), pgens("x", "y"),
  200. pgens("1", "c"), pgens("2", "d")])
  201. node35 = Template(wraptext("a"), [pgens("1", "b"), pgens("x", "y"),
  202. pgenh("1", "c"), pgenh("2", "d")])
  203. node36 = Template(wraptext("a"), [pgens("b", "c"), pgens("d", "e"),
  204. pgens("f", "g")])
  205. node37 = Template(wraptext("a"), [pgenh("1", "")])
  206. node38 = Template(wraptext("abc"))
  207. node39 = Template(wraptext("a"), [pgenh("1", " b ")])
  208. node40 = Template(wraptext("a"), [pgenh("1", " b"), pgenh("2", " c")])
  209. node41 = Template(wraptext("a"), [pgens("1", " b"), pgens("2", " c")])
  210. node42 = Template(wraptext("a"), [pgens("b", " \n")])
  211. node1.add("e", "f", showkey=True)
  212. node2.add(2, "g", showkey=False)
  213. node3.add("e", "foo|bar", showkey=True)
  214. node4.add("e", "f", showkey=True, before="b")
  215. node5.add("f", "g", showkey=True, before=" d ")
  216. node6.add("f", "g", showkey=True, before="b")
  217. with pytest.raises(ValueError):
  218. node7.add("e", "f", showkey=True, before="q")
  219. node8.add("e", "f", showkey=True, before=node8p)
  220. node9.add("e", "f", showkey=True, before=pgenh("1", "d"))
  221. with pytest.raises(ValueError):
  222. node10.add("e", "f", showkey=True, before=pgenh("1", "d"))
  223. node11.add("d", "foo=bar", showkey=True)
  224. node12.add("1", "foo=bar", showkey=False)
  225. node13.add("h", "i", showkey=True)
  226. node14.add("j", "k", showkey=True)
  227. node15.add("h", "i", showkey=True)
  228. node16.add("h", "i", showkey=True, preserve_spacing=False)
  229. node17.add("2", "c")
  230. node18.add("3", "c")
  231. node19.add("c", "d")
  232. node20.add("5", "f")
  233. node21.add("3", "f")
  234. node22.add("6", "f")
  235. node23.add("c", "foo=bar")
  236. node24.add("2", "foo=bar")
  237. node25.add("b", "d")
  238. node26.add("1", "foo=bar")
  239. node27.add("1", "foo=bar", showkey=True)
  240. node28.add("1", "foo=bar", showkey=False)
  241. node29.add("d", "foo")
  242. node30.add("f", "foo")
  243. node31.add("f", "foo")
  244. node32.add("d", "foo", preserve_spacing=False)
  245. node33.add("b", "k")
  246. node34.add("1", "e")
  247. node35.add("1", "e")
  248. node36.add("d", "h", before="b")
  249. node37.add(1, "b")
  250. node38.add("1", "foo")
  251. with pytest.raises(ValueError):
  252. 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. assert "{{a|b=c|d|e=f}}" == node1
  258. assert "{{a|b=c|d|g}}" == node2
  259. assert "{{a|b=c|d|e=foo&#124;bar}}" == node3
  260. assert isinstance(node3.params[2].value.get(1), HTMLEntity)
  261. assert "{{a|e=f|b=c|d}}" == node4
  262. assert "{{a|b=c|f=g| d =e}}" == node5
  263. assert "{{a|b=c|b=d|f=g|b=e}}" == node6
  264. assert "{{a|b=c|d}}" == node7
  265. assert "{{a|b=c|e=f|d}}" == node8
  266. assert "{{a|b=c|e=f|d}}" == node9
  267. assert "{{a|b=c|e}}" == node10
  268. assert "{{a|b=c|d=foo=bar}}" == node11
  269. assert "{{a|b=c|foo&#61;bar}}" == node12
  270. assert isinstance(node12.params[1].value.get(1), HTMLEntity)
  271. assert "{{a|\nb = c|\nd = e|\nf = g|\nh = i}}" == node13
  272. assert "{{a\n|b =c\n|d = e|f =g\n|h = i\n|j =k\n}}" == node14
  273. assert "{{a|b = c\n|\nd = e|\nf =g |\nh = i}}" == node15
  274. assert "{{a|\nb = c|\nd = e|\nf = g|h=i}}" == node16
  275. assert "{{a|b|c}}" == node17
  276. assert "{{a|b|3=c}}" == node18
  277. assert "{{a|b|c=d}}" == node19
  278. assert "{{a|b|c|d|e|f}}" == node20
  279. assert "{{a|b|c|4=d|5=e|f}}" == node21
  280. assert "{{a|b|c|4=d|5=e|6=f}}" == node22
  281. assert "{{a|b|c=foo=bar}}" == node23
  282. assert "{{a|b|foo&#61;bar}}" == node24
  283. assert isinstance(node24.params[1].value.get(1), HTMLEntity)
  284. assert "{{a|b=d}}" == node25
  285. assert "{{a|foo&#61;bar}}" == node26
  286. assert isinstance(node26.params[0].value.get(1), HTMLEntity)
  287. assert "{{a|1=foo=bar}}" == node27
  288. assert "{{a|foo&#61;bar}}" == node28
  289. assert isinstance(node28.params[0].value.get(1), HTMLEntity)
  290. assert "{{a|\nb = c|\nd = foo|\nf = g}}" == node29
  291. assert "{{a\n|b =c\n|d = e|f =foo\n|h = i\n}}" == node30
  292. assert "{{a|b = c\n|\nd = e|\nf =foo }}" == node31
  293. assert "{{a|\nb = c |\nd =foo|\nf = g }}" == node32
  294. assert "{{a|b=k|d=e|i=j}}" == node33
  295. assert "{{a|1=e|x=y|2=d}}" == node34
  296. assert "{{a|x=y|e|d}}" == node35
  297. assert "{{a|b=c|d=h|f=g}}" == node36
  298. assert "{{a|b}}" == node37
  299. assert "{{abc|foo}}" == node38
  300. assert "{{a|c}}" == node39
  301. assert "{{a| b| c|d}}" == node40
  302. assert "{{a|1= b|2= c|3= d}}" == node41
  303. assert "{{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. with pytest.raises(ValueError):
  393. node1.remove(1)
  394. with pytest.raises(ValueError):
  395. node1.remove("a")
  396. with pytest.raises(ValueError):
  397. node2.remove("1")
  398. assert "{{foo}}" == node2
  399. assert "{{foo||abc=}}" == node3
  400. assert "{{foo|2=baz}}" == node4
  401. assert "{{foo|b=c}}" == node5
  402. assert "{{foo| a=|b=c}}" == node6
  403. assert "{{foo|1 =|2=c}}" == node7
  404. assert "{{foo|2=c}}" == node8
  405. assert "{{foo||c}}" == node9
  406. assert "{{foo|2=c}}" == node10
  407. assert "{{foo|b=c|a =d}}" == node11
  408. assert "{{foo| a=|b=c|a =d}}" == node12
  409. assert "{{foo| a=b|a =d}}" == node13
  410. assert "{{foo| a=b|b=|a =d}}" == node14
  411. assert "{{foo| a=b|b=c}}" == node15
  412. assert "{{foo| a=b|b=c|a =}}" == node16
  413. assert "{{foo|b|c}}" == node17
  414. assert "{{foo|1 =|b|c}}" == node18
  415. assert "{{foo|1 =a|2=c}}" == node19
  416. assert "{{foo|1 =a||c}}" == node20
  417. assert "{{foo|c=d|e=f}}" == node21
  418. assert "{{foo|a=|c=d|e=f}}" == node22
  419. assert "{{foo|c=d|e=f|a=b|a=b}}" == node23
  420. assert "{{foo|a=|c=d|e=f|a=b|a=b}}" == node24
  421. assert "{{foo|a=b|c=d|e=f|a=b}}" == node25
  422. assert "{{foo|a=b|c=d|e=f|a=|a=b}}" == node26
  423. with pytest.raises(ValueError):
  424. node27.remove(node28.get(1))
  425. def test_formatting(self):
  426. """test realistic param manipulation with complex whitespace formatting
  427. (assumes that parsing works correctly)"""
  428. tests = [
  429. # https://en.wikipedia.org/w/index.php?title=Lamar_County,_Georgia&oldid=792356004
  430. ("""{{Infobox U.S. county
  431. | county = Lamar County
  432. | state = Georgia
  433. | seal =
  434. | founded = 1920
  435. | seat wl = Barnesville
  436. | largest city wl = Barnesville
  437. | area_total_sq_mi = 186
  438. | area_land_sq_mi = 184
  439. | area_water_sq_mi = 2.3
  440. | area percentage = 1.3%
  441. | census yr = 2010
  442. | pop = 18317
  443. | density_sq_mi = 100
  444. | time zone = Eastern
  445. | footnotes =
  446. | web = www.lamarcountyga.com
  447. | ex image = Lamar County Georgia Courthouse.jpg
  448. | ex image cap = Lamar County courthouse in Barnesville
  449. | district = 3rd
  450. | named for = [[Lucius Quintus Cincinnatus Lamar II]]
  451. }}""",
  452. """@@ -11,4 +11,4 @@
  453. | area percentage = 1.3%
  454. -| census yr = 2010
  455. -| pop = 18317
  456. +| census estimate yr = 2016
  457. +| pop = 12345<ref>example ref</ref>
  458. | density_sq_mi = 100"""),
  459. # https://en.wikipedia.org/w/index.php?title=Rockdale_County,_Georgia&oldid=792359760
  460. ("""{{Infobox U.S. County|
  461. county = Rockdale County |
  462. state = Georgia |
  463. seal = |
  464. founded = October 18, 1870 |
  465. seat wl = Conyers |
  466. largest city wl = Conyers |
  467. area_total_sq_mi = 132 |
  468. area_land_sq_mi = 130 |
  469. area_water_sq_mi = 2.3 |
  470. area percentage = 1.7% |
  471. census yr = 2010|
  472. pop = 85215 |
  473. density_sq_mi = 657 |
  474. web = www.rockdalecounty.org
  475. | ex image = Rockdale-county-courthouse.jpg
  476. | ex image cap = Rockdale County Courthouse in Conyers
  477. | district = 4th
  478. | time zone= Eastern
  479. }}""",
  480. """@@ -11,4 +11,4 @@
  481. area percentage = 1.7% |
  482. - census yr = 2010|
  483. - pop = 85215 |
  484. + census estimate yr = 2016 |
  485. + pop = 12345<ref>example ref</ref> |
  486. density_sq_mi = 657 |"""),
  487. # https://en.wikipedia.org/w/index.php?title=Spalding_County,_Georgia&oldid=792360413
  488. ("""{{Infobox U.S. County|
  489. | county = Spalding County |
  490. | state = Georgia |
  491. | seal = |
  492. | founded = 1851 |
  493. | seat wl = Griffin |
  494. | largest city wl = Griffin |
  495. | area_total_sq_mi = 200 |
  496. | area_land_sq_mi = 196 |
  497. | area_water_sq_mi = 3.1 |
  498. | area percentage = 1.6% |
  499. | census yr = 2010|
  500. | pop = 64073 |
  501. | density_sq_mi = 326 |
  502. | web = www.spaldingcounty.com |
  503. | named for = [[Thomas Spalding]]
  504. | ex image = Spalding County Courthouse (NE corner).JPG
  505. | ex image cap = Spalding County Courthouse in Griffin
  506. | district = 3rd
  507. | time zone = Eastern
  508. }}""",
  509. """@@ -11,4 +11,4 @@
  510. | area percentage = 1.6% |
  511. -| census yr = 2010|
  512. -| pop = 64073 |
  513. +|
  514. +| census estimate yr = 2016 | pop = 12345<ref>example ref</ref> |
  515. | density_sq_mi = 326 |"""),
  516. # https://en.wikipedia.org/w/index.php?title=Clinton_County,_Illinois&oldid=794694648
  517. ("""{{Infobox U.S. county
  518. |county = Clinton County
  519. |state = Illinois
  520. | ex image = File:Clinton County Courthouse, Carlyle.jpg
  521. | ex image cap = [[Clinton County Courthouse (Illinois)|Clinton County Courthouse]]
  522. |seal =
  523. |founded = 1824
  524. |named for = [[DeWitt Clinton]]
  525. |seat wl= Carlyle
  526. | largest city wl = Breese
  527. |time zone=Central
  528. |area_total_sq_mi = 503
  529. |area_land_sq_mi = 474
  530. |area_water_sq_mi = 29
  531. |area percentage = 5.8%
  532. |census yr = 2010
  533. |pop = 37762
  534. |density_sq_mi = 80
  535. |web = www.clintonco.illinois.gov
  536. | district = 15th
  537. }}""",
  538. """@@ -15,4 +15,4 @@
  539. |area percentage = 5.8%
  540. - |census yr = 2010
  541. - |pop = 37762
  542. + |census estimate yr = 2016
  543. + |pop = 12345<ref>example ref</ref>
  544. |density_sq_mi = 80"""),
  545. # https://en.wikipedia.org/w/index.php?title=Winnebago_County,_Illinois&oldid=789193800
  546. ("""{{Infobox U.S. county |
  547. county = Winnebago County |
  548. state = Illinois |
  549. seal = Winnebago County il seal.png |
  550. named for = [[Winnebago (tribe)|Winnebago Tribe]] |
  551. seat wl= Rockford |
  552. largest city wl = Rockford|
  553. area_total_sq_mi = 519 |
  554. area_land_sq_mi = 513|
  555. area_water_sq_mi = 5.9 |
  556. area percentage = 1.1% |
  557. census yr = 2010|
  558. pop = 295266 |
  559. density_sq_mi = 575
  560. | web = www.wincoil.us
  561. | founded year = 1836
  562. | founded date = January 16
  563. | time zone = Central
  564. | district = 16th
  565. | district2 = 17th
  566. }}""",
  567. """@@ -11,4 +11,4 @@
  568. area percentage = 1.1% |
  569. - census yr = 2010|
  570. - pop = 295266 |
  571. + census estimate yr = 2016|
  572. + pop = 12345<ref>example ref</ref> |
  573. density_sq_mi = 575""")]
  574. for (original, expected) in tests:
  575. code = parse(original)
  576. template = code.filter_templates()[0]
  577. template.add("pop", "12345<ref>example ref</ref>")
  578. template.add('census estimate yr', "2016", before="pop")
  579. template.remove("census yr")
  580. oldlines = original.splitlines(True)
  581. newlines = str(code).splitlines(True)
  582. difflines = unified_diff(oldlines, newlines, n=1)
  583. diff = "".join(list(difflines)[2:]).strip()
  584. assert expected == diff