A Python parser for MediaWiki wikicode https://mwparserfromhell.readthedocs.io/
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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