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.
 
 
 
 

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