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

344 行
13 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2012-2013 Ben Kurtovic <ben.kurtovic@verizon.net>
  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. import unittest
  24. from mwparserfromhell.compat import py3k, range
  25. from mwparserfromhell.smart_list import SmartList, _ListProxy
  26. class TestSmartList(unittest.TestCase):
  27. """Test cases for the SmartList class and its child, _ListProxy."""
  28. def _test_list_methods(self, builder):
  29. """Run tests on the public methods of a list built with *builder*."""
  30. list1 = builder(range(5))
  31. list2 = builder(["foo"])
  32. list3 = builder([("a", 5), ("d", 2), ("b", 8), ("c", 3)])
  33. list1.append(5)
  34. list1.append(1)
  35. list1.append(2)
  36. self.assertEquals([0, 1, 2, 3, 4, 5, 1, 2], list1)
  37. self.assertEquals(0, list1.count(6))
  38. self.assertEquals(2, list1.count(1))
  39. list1.extend(range(5, 8))
  40. self.assertEquals([0, 1, 2, 3, 4, 5, 1, 2, 5, 6, 7], list1)
  41. self.assertEquals(1, list1.index(1))
  42. self.assertEquals(6, list1.index(1, 3))
  43. self.assertEquals(6, list1.index(1, 3, 7))
  44. self.assertRaises(ValueError, list1.index, 1, 3, 5)
  45. list1.insert(0, -1)
  46. self.assertEquals([-1, 0, 1, 2, 3, 4, 5, 1, 2, 5, 6, 7], list1)
  47. list1.insert(-1, 6.5)
  48. self.assertEquals([-1, 0, 1, 2, 3, 4, 5, 1, 2, 5, 6, 6.5, 7], list1)
  49. list1.insert(13, 8)
  50. self.assertEquals([-1, 0, 1, 2, 3, 4, 5, 1, 2, 5, 6, 6.5, 7, 8], list1)
  51. self.assertEquals(8, list1.pop())
  52. self.assertEquals(7, list1.pop())
  53. self.assertEquals([-1, 0, 1, 2, 3, 4, 5, 1, 2, 5, 6, 6.5], list1)
  54. self.assertEquals(-1, list1.pop(0))
  55. self.assertEquals(5, list1.pop(5))
  56. self.assertEquals(6.5, list1.pop(-1))
  57. self.assertEquals([0, 1, 2, 3, 4, 1, 2, 5, 6], list1)
  58. self.assertEquals("foo", list2.pop())
  59. self.assertRaises(IndexError, list2.pop)
  60. self.assertEquals([], list2)
  61. list1.remove(6)
  62. self.assertEquals([0, 1, 2, 3, 4, 1, 2, 5], list1)
  63. list1.remove(1)
  64. self.assertEquals([0, 2, 3, 4, 1, 2, 5], list1)
  65. list1.remove(1)
  66. self.assertEquals([0, 2, 3, 4, 2, 5], list1)
  67. self.assertRaises(ValueError, list1.remove, 1)
  68. list1.reverse()
  69. self.assertEquals([5, 2, 4, 3, 2, 0], list1)
  70. list1.sort()
  71. self.assertEquals([0, 2, 2, 3, 4, 5], list1)
  72. list1.sort(reverse=True)
  73. self.assertEquals([5, 4, 3, 2, 2, 0], list1)
  74. list1.sort(cmp=lambda x, y: abs(3 - x) - abs(3 - y)) # Distance from 3
  75. self.assertEquals([3, 4, 2, 2, 5, 0], list1)
  76. list1.sort(cmp=lambda x, y: abs(3 - x) - abs(3 - y), reverse=True)
  77. self.assertEquals([0, 5, 4, 2, 2, 3], list1)
  78. list3.sort(key=lambda i: i[1])
  79. self.assertEquals([("d", 2), ("c", 3), ("a", 5), ("b", 8)], list3)
  80. list3.sort(key=lambda i: i[1], reverse=True)
  81. self.assertEquals([("b", 8), ("a", 5), ("c", 3), ("d", 2)], list3)
  82. def test_docs(self):
  83. """make sure the methods of SmartList/_ListProxy have docstrings"""
  84. methods = ["append", "count", "extend", "index", "insert", "pop",
  85. "remove", "reverse", "sort"]
  86. for meth in methods:
  87. expected = getattr(list, meth).__doc__
  88. smartlist_doc = getattr(SmartList, meth).__doc__
  89. listproxy_doc = getattr(_ListProxy, meth).__doc__
  90. self.assertEquals(expected, smartlist_doc)
  91. self.assertEquals(expected, listproxy_doc)
  92. def test_doctest(self):
  93. """make sure the test embedded in SmartList's docstring passes"""
  94. parent = SmartList([0, 1, 2, 3])
  95. self.assertEquals([0, 1, 2, 3], parent)
  96. child = parent[2:]
  97. self.assertEquals([2, 3], child)
  98. child.append(4)
  99. self.assertEquals([2, 3, 4], child)
  100. self.assertEquals([0, 1, 2, 3, 4], parent)
  101. def test_parent_get_set_del(self):
  102. """make sure SmartList's getitem/setitem/delitem work"""
  103. def assign(L, s1, s2, s3, val):
  104. L[s1:s2:s3] = val
  105. def delete(L, s1):
  106. del L[s1]
  107. list1 = SmartList([0, 1, 2, 3, "one", "two"])
  108. list2 = SmartList(list(range(10)))
  109. self.assertEquals(1, list1[1])
  110. self.assertEquals("one", list1[-2])
  111. self.assertEquals([2, 3], list1[2:4])
  112. self.assertRaises(IndexError, lambda: list1[6])
  113. self.assertRaises(IndexError, lambda: list1[-7])
  114. self.assertEquals([0, 1, 2], list1[:3])
  115. self.assertEquals([0, 1, 2, 3, "one", "two"], list1[:])
  116. self.assertEquals([3, "one", "two"], list1[3:])
  117. self.assertEquals(["one", "two"], list1[-2:])
  118. self.assertEquals([0, 1], list1[:-4])
  119. self.assertEquals([], list1[6:])
  120. self.assertEquals([], list1[4:2])
  121. self.assertEquals([0, 2, "one"], list1[0:5:2])
  122. self.assertEquals([0, 2], list1[0:-3:2])
  123. self.assertEquals([0, 1, 2, 3, "one", "two"], list1[::])
  124. self.assertEquals([2, 3, "one", "two"], list1[2::])
  125. self.assertEquals([0, 1, 2, 3], list1[:4:])
  126. self.assertEquals([2, 3], list1[2:4:])
  127. self.assertEquals([0, 2, 4, 6, 8], list2[::2])
  128. self.assertEquals([2, 5, 8], list2[2::3])
  129. self.assertEquals([0, 3], list2[:6:3])
  130. self.assertEquals([2, 5, 8], list2[-8:9:3])
  131. self.assertEquals([], list2[100000:1000:-100])
  132. list1[3] = 100
  133. self.assertEquals(100, list1[3])
  134. list1[5:] = [6, 7, 8]
  135. self.assertEquals([6, 7, 8], list1[5:])
  136. self.assertEquals([0, 1, 2, 100, "one", 6, 7, 8], list1)
  137. list1[2:4] = [-1, -2, -3, -4, -5]
  138. self.assertEquals([0, 1, -1, -2, -3, -4, -5, "one", 6, 7, 8], list1)
  139. list1[0:-3] = [99]
  140. self.assertEquals([99, 6, 7, 8], list1)
  141. list2[0:6:2] = [100, 102, 104]
  142. self.assertEquals([100, 1, 102, 3, 104, 5, 6, 7, 8, 9], list2)
  143. list2[::3] = [200, 203, 206, 209]
  144. self.assertEquals([200, 1, 102, 203, 104, 5, 206, 7, 8, 209], list2)
  145. list2[::] = range(7)
  146. self.assertEquals([0, 1, 2, 3, 4, 5, 6], list2)
  147. self.assertRaises(ValueError, assign, list2, 0, 5, 2,
  148. [100, 102, 104, 106])
  149. del list2[2]
  150. self.assertEquals([0, 1, 3, 4, 5, 6], list2)
  151. del list2[-3]
  152. self.assertEquals([0, 1, 3, 5, 6], list2)
  153. self.assertRaises(IndexError, delete, list2, 100)
  154. self.assertRaises(IndexError, delete, list2, -6)
  155. list2[:] = range(10)
  156. del list2[3:6]
  157. self.assertEquals([0, 1, 2, 6, 7, 8, 9], list2)
  158. del list2[-2:]
  159. self.assertEquals([0, 1, 2, 6, 7], list2)
  160. del list2[:2]
  161. self.assertEquals([2, 6, 7], list2)
  162. list2[:] = range(10)
  163. del list2[2:8:2]
  164. self.assertEquals([0, 1, 3, 5, 7, 8, 9], list2)
  165. def test_parent_add(self):
  166. """make sure SmartList's add/radd/iadd work"""
  167. list1 = SmartList(range(5))
  168. list2 = SmartList(range(5, 10))
  169. self.assertEquals([0, 1, 2, 3, 4, 5, 6], list1 + [5, 6])
  170. self.assertEquals([0, 1, 2, 3, 4], list1)
  171. self.assertEquals(list(range(10)), list1 + list2)
  172. self.assertEquals([-2, -1, 0, 1, 2, 3, 4], [-2, -1] + list1)
  173. self.assertEquals([0, 1, 2, 3, 4], list1)
  174. list1 += ["foo", "bar", "baz"]
  175. self.assertEquals([0, 1, 2, 3, 4, "foo", "bar", "baz"], list1)
  176. def test_parent_unaffected_magics(self):
  177. """sanity checks against SmartList features that were not modified"""
  178. list1 = SmartList([0, 1, 2, 3, "one", "two"])
  179. list2 = SmartList([])
  180. list3 = SmartList([0, 2, 3, 4])
  181. list4 = SmartList([0, 1, 2])
  182. if py3k:
  183. self.assertEquals("[0, 1, 2, 3, 'one', 'two']", str(list1))
  184. self.assertEquals(b"[0, 1, 2, 3, 'one', 'two']", bytes(list1))
  185. self.assertEquals("[0, 1, 2, 3, 'one', 'two']", repr(list1))
  186. else:
  187. self.assertEquals("[0, 1, 2, 3, u'one', u'two']", unicode(list1))
  188. self.assertEquals(b"[0, 1, 2, 3, u'one', u'two']", str(list1))
  189. self.assertEquals(b"[0, 1, 2, 3, u'one', u'two']", repr(list1))
  190. self.assertTrue(list1 < list3)
  191. self.assertTrue(list1 <= list3)
  192. self.assertFalse(list1 == list3)
  193. self.assertTrue(list1 != list3)
  194. self.assertFalse(list1 > list3)
  195. self.assertFalse(list1 >= list3)
  196. other1 = [0, 2, 3, 4]
  197. self.assertTrue(list1 < other1)
  198. self.assertTrue(list1 <= other1)
  199. self.assertFalse(list1 == other1)
  200. self.assertTrue(list1 != other1)
  201. self.assertFalse(list1 > other1)
  202. self.assertFalse(list1 >= other1)
  203. other2 = [0, 0, 1, 2]
  204. self.assertFalse(list1 < other2)
  205. self.assertFalse(list1 <= other2)
  206. self.assertFalse(list1 == other2)
  207. self.assertTrue(list1 != other2)
  208. self.assertTrue(list1 > other2)
  209. self.assertTrue(list1 >= other2)
  210. other3 = [0, 1, 2, 3, "one", "two"]
  211. self.assertFalse(list1 < other3)
  212. self.assertTrue(list1 <= other3)
  213. self.assertTrue(list1 == other3)
  214. self.assertFalse(list1 != other3)
  215. self.assertFalse(list1 > other3)
  216. self.assertTrue(list1 >= other3)
  217. self.assertTrue(bool(list1))
  218. self.assertFalse(bool(list2))
  219. self.assertEquals(6, len(list1))
  220. self.assertEquals(0, len(list2))
  221. out = []
  222. for obj in list1:
  223. out.append(obj)
  224. self.assertEquals([0, 1, 2, 3, "one", "two"], out)
  225. out = []
  226. for ch in list2:
  227. out.append(ch)
  228. self.assertEquals([], out)
  229. gen1 = iter(list1)
  230. out = []
  231. for i in range(len(list1)):
  232. out.append(gen1.next())
  233. self.assertRaises(StopIteration, gen1.next)
  234. self.assertEquals([0, 1, 2, 3, "one", "two"], out)
  235. gen2 = iter(list2)
  236. self.assertRaises(StopIteration, gen2.next)
  237. self.assertEquals(["two", "one", 3, 2, 1, 0], list(reversed(list1)))
  238. self.assertEquals([], list(reversed(list2)))
  239. self.assertTrue("one" in list1)
  240. self.assertTrue(3 in list1)
  241. self.assertFalse(10 in list1)
  242. self.assertFalse(0 in list2)
  243. self.assertEquals([], list2 * 5)
  244. self.assertEquals([], 5 * list2)
  245. self.assertEquals([0, 1, 2, 0, 1, 2, 0, 1, 2], list4 * 3)
  246. self.assertEquals([0, 1, 2, 0, 1, 2, 0, 1, 2], 3 * list4)
  247. list4 *= 2
  248. self.assertEquals([0, 1, 2, 0, 1, 2], list4)
  249. def test_parent_methods(self):
  250. """make sure SmartList's non-magic methods work, like append()"""
  251. self._test_list_methods(lambda L: SmartList(L))
  252. def test_child_magics(self):
  253. """make sure _ListProxy's magically implemented features work"""
  254. pass
  255. # if py3k:
  256. # __str__
  257. # __bytes__
  258. # else:
  259. # __unicode__
  260. # __str__
  261. # __repr__
  262. # __lt__
  263. # __le__
  264. # __eq__
  265. # __ne__
  266. # __gt__
  267. # __ge__
  268. # if py3k:
  269. # __bool__
  270. # else:
  271. # __nonzero__
  272. # __len__
  273. # __getitem__
  274. # __setitem__
  275. # __delitem__
  276. # __iter__
  277. # __reversed__
  278. # __contains__
  279. # if not py3k:
  280. # __getslice__
  281. # __setslice__
  282. # __delslice__
  283. # __add__
  284. # __radd__
  285. # __iadd__
  286. # __mul__
  287. # __rmul__
  288. # __imul__
  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. pass
  299. # also test whether children that exit scope are removed from parent's map
  300. if __name__ == "__main__":
  301. unittest.main(verbosity=2)