A Python parser for MediaWiki wikicode https://mwparserfromhell.readthedocs.io/
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

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