A Python parser for MediaWiki wikicode https://mwparserfromhell.readthedocs.io/
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

778 行
26 KiB

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