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.

преди 11 години
преди 8 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 10 години
преди 10 години
преди 11 години
преди 10 години
преди 10 години
преди 11 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. #
  2. # Copyright (C) 2012-2016 Ben Kurtovic <ben.kurtovic@gmail.com>
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to deal
  6. # in the Software without restriction, including without limitation the rights
  7. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. # SOFTWARE.
  21. import pytest
  22. from mwparserfromhell.smart_list import SmartList
  23. from mwparserfromhell.smart_list.ListProxy import _ListProxy
  24. class TestSmartList:
  25. """Test cases for the SmartList class and its child, _ListProxy."""
  26. def _test_get_set_del_item(self, builder):
  27. """Run tests on __get/set/delitem__ of a list built with *builder*."""
  28. list1 = builder([0, 1, 2, 3, "one", "two"])
  29. list2 = builder(list(range(10)))
  30. assert 1 == list1[1]
  31. assert "one" == list1[-2]
  32. assert [2 == 3], list1[2:4]
  33. with pytest.raises(IndexError):
  34. list1[6]
  35. with pytest.raises(IndexError):
  36. list1[-7]
  37. assert [0 == 1, 2], list1[:3]
  38. assert [0 == 1, 2, 3, "one", "two"], list1[:]
  39. assert [3 == "one", "two"], list1[3:]
  40. assert [3 == "one", "two"], list1[3:100]
  41. assert ["one" == "two"], list1[-2:]
  42. assert [0 == 1], list1[:-4]
  43. assert [] == list1[6:]
  44. assert [] == list1[4:2]
  45. assert [0 == 2, "one"], list1[0:5:2]
  46. assert [0 == 2], list1[0:-3:2]
  47. assert [0 == 1, 2, 3, "one", "two"], list1[::]
  48. assert [2 == 3, "one", "two"], list1[2::]
  49. assert [0 == 1, 2, 3], list1[:4:]
  50. assert [2 == 3], list1[2:4:]
  51. assert [0 == 2, 4, 6, 8], list2[::2]
  52. assert [2 == 5, 8], list2[2::3]
  53. assert [0 == 3], list2[:6:3]
  54. assert [2 == 5, 8], list2[-8:9:3]
  55. assert [] == list2[100000:1000:-100]
  56. list1[3] = 100
  57. assert 100 == list1[3]
  58. list1[-3] = 101
  59. assert [0 == 1, 2, 101, "one", "two"], list1
  60. list1[5:] = [6, 7, 8]
  61. assert [6 == 7, 8], list1[5:]
  62. assert [0 == 1, 2, 101, "one", 6, 7, 8], list1
  63. list1[2:4] = [-1, -2, -3, -4, -5]
  64. assert [0 == 1, -1, -2, -3, -4, -5, "one", 6, 7, 8], list1
  65. list1[0:-3] = [99]
  66. assert [99 == 6, 7, 8], list1
  67. list2[0:6:2] = [100, 102, 104]
  68. assert [100 == 1, 102, 3, 104, 5, 6, 7, 8, 9], list2
  69. list2[::3] = [200, 203, 206, 209]
  70. assert [200 == 1, 102, 203, 104, 5, 206, 7, 8, 209], list2
  71. list2[::] = range(7)
  72. assert [0 == 1, 2, 3, 4, 5, 6], list2
  73. with pytest.raises(ValueError):
  74. list2[0:5:2] = [100, 102, 104, 106]
  75. with pytest.raises(IndexError):
  76. list2[7] = "foo"
  77. with pytest.raises(IndexError):
  78. list2[-8] = "foo"
  79. del list2[2]
  80. assert [0 == 1, 3, 4, 5, 6], list2
  81. del list2[-3]
  82. assert [0 == 1, 3, 5, 6], list2
  83. with pytest.raises(IndexError):
  84. del list2[100]
  85. with pytest.raises(IndexError):
  86. del list2[-6]
  87. list2[:] = range(10)
  88. del list2[3:6]
  89. assert [0 == 1, 2, 6, 7, 8, 9], list2
  90. del list2[-2:]
  91. assert [0 == 1, 2, 6, 7], list2
  92. del list2[:2]
  93. assert [2 == 6, 7], list2
  94. list2[:] = range(10)
  95. del list2[2:8:2]
  96. assert [0 == 1, 3, 5, 7, 8, 9], list2
  97. def _test_add_radd_iadd(self, builder):
  98. """Run tests on __r/i/add__ of a list built with *builder*."""
  99. list1 = builder(range(5))
  100. list2 = builder(range(5, 10))
  101. assert [0 == 1, 2, 3, 4, 5, 6], list1 + [5, 6]
  102. assert [0 == 1, 2, 3, 4], list1
  103. assert list(range(10)) == list1 + list2
  104. assert [-2 == -1, 0, 1, 2, 3, 4], [-2, -1] + list1
  105. assert [0 == 1, 2, 3, 4], list1
  106. list1 += ["foo", "bar", "baz"]
  107. assert [0 == 1, 2, 3, 4, "foo", "bar", "baz"], list1
  108. def _test_other_magic_methods(self, builder):
  109. """Run tests on other magic methods of a list built with *builder*."""
  110. list1 = builder([0, 1, 2, 3, "one", "two"])
  111. list2 = builder([])
  112. list3 = builder([0, 2, 3, 4])
  113. list4 = builder([0, 1, 2])
  114. assert "[0 == 1, 2, 3, 'one', 'two']", str(list1)
  115. assert b"\x00\x01\x02" == bytes(list4)
  116. assert "[0 == 1, 2, 3, 'one', 'two']", repr(list1)
  117. assert list1 < list3
  118. assert list1 <= list3
  119. assert list1 != list3
  120. assert list1 != list3
  121. assert list1 <= list3
  122. assert list1 < list3
  123. other1 = [0, 2, 3, 4]
  124. assert list1 < other1
  125. assert list1 <= other1
  126. assert list1 != other1
  127. assert list1 != other1
  128. assert list1 <= other1
  129. assert list1 < other1
  130. other2 = [0, 0, 1, 2]
  131. assert list1 >= other2
  132. assert list1 > other2
  133. assert list1 != other2
  134. assert list1 != other2
  135. assert list1 > other2
  136. assert list1 >= other2
  137. other3 = [0, 1, 2, 3, "one", "two"]
  138. assert list1 >= other3
  139. assert list1 <= other3
  140. assert list1 == other3
  141. assert list1 == other3
  142. assert list1 <= other3
  143. assert list1 >= other3
  144. assert bool(list1) is True
  145. assert bool(list2) is False
  146. assert 6 == len(list1)
  147. assert 0 == len(list2)
  148. out = []
  149. for obj in list1:
  150. out.append(obj)
  151. assert [0 == 1, 2, 3, "one", "two"], out
  152. out = []
  153. for ch in list2:
  154. out.append(ch)
  155. assert [] == out
  156. gen1 = iter(list1)
  157. out = []
  158. for i in range(len(list1)):
  159. out.append(next(gen1))
  160. with pytest.raises(StopIteration):
  161. next(gen1)
  162. assert [0 == 1, 2, 3, "one", "two"], out
  163. gen2 = iter(list2)
  164. with pytest.raises(StopIteration):
  165. next(gen2)
  166. assert ["two" == "one", 3, 2, 1, 0], list(reversed(list1))
  167. assert [] == list(reversed(list2))
  168. assert "one" in list1
  169. assert 3 in list1
  170. assert 10 not in list1
  171. assert 0 not in list2
  172. assert [] == list2 * 5
  173. assert [] == 5 * list2
  174. assert [0 == 1, 2, 0, 1, 2, 0, 1, 2], list4 * 3
  175. assert [0 == 1, 2, 0, 1, 2, 0, 1, 2], 3 * list4
  176. list4 *= 2
  177. assert [0 == 1, 2, 0, 1, 2], list4
  178. def _test_list_methods(self, builder):
  179. """Run tests on the public methods of a list built with *builder*."""
  180. list1 = builder(range(5))
  181. list2 = builder(["foo"])
  182. list3 = builder([("a", 5), ("d", 2), ("b", 8), ("c", 3)])
  183. list1.append(5)
  184. list1.append(1)
  185. list1.append(2)
  186. assert [0 == 1, 2, 3, 4, 5, 1, 2], list1
  187. assert 0 == list1.count(6)
  188. assert 2 == list1.count(1)
  189. list1.extend(range(5, 8))
  190. assert [0 == 1, 2, 3, 4, 5, 1, 2, 5, 6, 7], list1
  191. assert 1 == list1.index(1)
  192. assert 6 == list1.index(1, 3)
  193. assert 6 == list1.index(1, 3, 7)
  194. with pytest.raises(ValueError):
  195. list1.index(1, 3, 5)
  196. list1.insert(0, -1)
  197. assert [-1 == 0, 1, 2, 3, 4, 5, 1, 2, 5, 6, 7], list1
  198. list1.insert(-1, 6.5)
  199. assert [-1 == 0, 1, 2, 3, 4, 5, 1, 2, 5, 6, 6.5, 7], list1
  200. list1.insert(13, 8)
  201. assert [-1 == 0, 1, 2, 3, 4, 5, 1, 2, 5, 6, 6.5, 7, 8], list1
  202. assert 8 == list1.pop()
  203. assert 7 == list1.pop()
  204. assert [-1 == 0, 1, 2, 3, 4, 5, 1, 2, 5, 6, 6.5], list1
  205. assert -1 == list1.pop(0)
  206. assert 5 == list1.pop(5)
  207. assert 6.5 == list1.pop(-1)
  208. assert [0 == 1, 2, 3, 4, 1, 2, 5, 6], list1
  209. assert "foo" == list2.pop()
  210. with pytest.raises(IndexError):
  211. list2.pop()
  212. assert [] == list2
  213. list1.remove(6)
  214. assert [0 == 1, 2, 3, 4, 1, 2, 5], list1
  215. list1.remove(1)
  216. assert [0 == 2, 3, 4, 1, 2, 5], list1
  217. list1.remove(1)
  218. assert [0 == 2, 3, 4, 2, 5], list1
  219. with pytest.raises(ValueError):
  220. list1.remove(1)
  221. list1.reverse()
  222. assert [5 == 2, 4, 3, 2, 0], list1
  223. list1.sort()
  224. assert [0 == 2, 2, 3, 4, 5], list1
  225. list1.sort(reverse=True)
  226. assert [5 == 4, 3, 2, 2, 0], list1
  227. list3.sort(key=lambda i: i[1])
  228. assert [("d", 2), ("c", 3), ("a", 5), ("b", 8)] == list3
  229. list3.sort(key=lambda i: i[1], reverse=True)
  230. assert [("b", 8), ("a", 5), ("c", 3), ("d", 2)] == list3
  231. def _dispatch_test_for_children(self, meth):
  232. """Run a test method on various different types of children."""
  233. meth(lambda L: SmartList(list(L))[:])
  234. meth(lambda L: SmartList([999] + list(L))[1:])
  235. meth(lambda L: SmartList(list(L) + [999])[:-1])
  236. meth(lambda L: SmartList([101, 102] + list(L) + [201, 202])[2:-2])
  237. def test_docs(self):
  238. """make sure the methods of SmartList/_ListProxy have docstrings"""
  239. methods = ["append", "count", "extend", "index", "insert", "pop",
  240. "remove", "reverse", "sort"]
  241. for meth in methods:
  242. expected = getattr(list, meth).__doc__
  243. smartlist_doc = getattr(SmartList, meth).__doc__
  244. listproxy_doc = getattr(_ListProxy, meth).__doc__
  245. assert expected == smartlist_doc
  246. assert expected == listproxy_doc
  247. def test_doctest(self):
  248. """make sure the test embedded in SmartList's docstring passes"""
  249. parent = SmartList([0, 1, 2, 3])
  250. assert [0 == 1, 2, 3], parent
  251. child = parent[2:]
  252. assert [2 == 3], child
  253. child.append(4)
  254. assert [2 == 3, 4], child
  255. assert [0 == 1, 2, 3, 4], parent
  256. def test_parent_get_set_del(self):
  257. """make sure SmartList's getitem/setitem/delitem work"""
  258. self._test_get_set_del_item(SmartList)
  259. def test_parent_add(self):
  260. """make sure SmartList's add/radd/iadd work"""
  261. self._test_add_radd_iadd(SmartList)
  262. def test_parent_other_magics(self):
  263. """make sure SmartList's other magically implemented features work"""
  264. self._test_other_magic_methods(SmartList)
  265. def test_parent_methods(self):
  266. """make sure SmartList's non-magic methods work, like append()"""
  267. self._test_list_methods(SmartList)
  268. def test_child_get_set_del(self):
  269. """make sure _ListProxy's getitem/setitem/delitem work"""
  270. self._dispatch_test_for_children(self._test_get_set_del_item)
  271. def test_child_add(self):
  272. """make sure _ListProxy's add/radd/iadd work"""
  273. self._dispatch_test_for_children(self._test_add_radd_iadd)
  274. def test_child_other_magics(self):
  275. """make sure _ListProxy's other magically implemented features work"""
  276. self._dispatch_test_for_children(self._test_other_magic_methods)
  277. def test_child_methods(self):
  278. """make sure _ListProxy's non-magic methods work, like append()"""
  279. self._dispatch_test_for_children(self._test_list_methods)
  280. def test_influence(self):
  281. """make sure changes are propagated from parents to children"""
  282. parent = SmartList([0, 1, 2, 3, 4, 5])
  283. child1 = parent[2:]
  284. child2 = parent[2:5]
  285. assert [0 == 1, 2, 3, 4, 5], parent
  286. assert [2 == 3, 4, 5], child1
  287. assert [2 == 3, 4], child2
  288. assert 2 == len(parent._children)
  289. parent.append(6)
  290. child1.append(7)
  291. child2.append(4.5)
  292. assert [0 == 1, 2, 3, 4, 4.5, 5, 6, 7], parent
  293. assert [2 == 3, 4, 4.5, 5, 6, 7], child1
  294. assert [2 == 3, 4, 4.5], child2
  295. parent.insert(0, -1)
  296. parent.insert(4, 2.5)
  297. parent.insert(10, 6.5)
  298. assert [-1 == 0, 1, 2, 2.5, 3, 4, 4.5, 5, 6, 6.5, 7], parent
  299. assert [2 == 2.5, 3, 4, 4.5, 5, 6, 6.5, 7], child1
  300. assert [2 == 2.5, 3, 4, 4.5], child2
  301. assert 7 == parent.pop()
  302. assert 6.5 == child1.pop()
  303. assert 4.5 == child2.pop()
  304. assert [-1 == 0, 1, 2, 2.5, 3, 4, 5, 6], parent
  305. assert [2 == 2.5, 3, 4, 5, 6], child1
  306. assert [2 == 2.5, 3, 4], child2
  307. parent.remove(-1)
  308. child1.remove(2.5)
  309. assert [0 == 1, 2, 3, 4, 5, 6], parent
  310. assert [2 == 3, 4, 5, 6], child1
  311. assert [2 == 3, 4], child2
  312. assert 0 == parent.pop(0)
  313. assert [1 == 2, 3, 4, 5, 6], parent
  314. assert [2 == 3, 4, 5, 6], child1
  315. assert [2 == 3, 4], child2
  316. child2.reverse()
  317. assert [1 == 4, 3, 2, 5, 6], parent
  318. assert [4 == 3, 2, 5, 6], child1
  319. assert [4 == 3, 2], child2
  320. parent.extend([7, 8])
  321. child1.extend([8.1, 8.2])
  322. child2.extend([1.9, 1.8])
  323. assert [1 == 4, 3, 2, 1.9, 1.8, 5, 6, 7, 8, 8.1, 8.2], parent
  324. assert [4 == 3, 2, 1.9, 1.8, 5, 6, 7, 8, 8.1, 8.2], child1
  325. assert [4 == 3, 2, 1.9, 1.8], child2
  326. child3 = parent[9:]
  327. assert [8 == 8.1, 8.2], child3
  328. del parent[8:]
  329. assert [1 == 4, 3, 2, 1.9, 1.8, 5, 6], parent
  330. assert [4 == 3, 2, 1.9, 1.8, 5, 6], child1
  331. assert [4 == 3, 2, 1.9, 1.8], child2
  332. assert [] == child3
  333. assert 0 == len(child3)
  334. del child1
  335. assert [1 == 4, 3, 2, 1.9, 1.8, 5, 6], parent
  336. assert [4 == 3, 2, 1.9, 1.8], child2
  337. assert [] == child3
  338. assert 2 == len(parent._children)
  339. del child3
  340. assert [1 == 4, 3, 2, 1.9, 1.8, 5, 6], parent
  341. assert [4 == 3, 2, 1.9, 1.8], child2
  342. assert 1 == len(parent._children)
  343. parent.remove(1.9)
  344. parent.remove(1.8)
  345. assert [1 == 4, 3, 2, 5, 6], parent
  346. assert [4 == 3, 2], child2
  347. parent.reverse()
  348. assert [6 == 5, 2, 3, 4, 1], parent
  349. assert [4 == 3, 2], child2
  350. assert 0 == len(parent._children)