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.
 
 
 
 

612 lines
25 KiB

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