PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/python/Lib/test/test_difflib.py

https://gitlab.com/pmuontains/Odoo
Python | 281 lines | 258 code | 13 blank | 10 comment | 3 complexity | c5d39c45fb8444a12de0ddc092d3abc5 MD5 | raw file
  1. import difflib
  2. from test.test_support import run_unittest, findfile
  3. import unittest
  4. import doctest
  5. import sys
  6. class TestWithAscii(unittest.TestCase):
  7. def test_one_insert(self):
  8. sm = difflib.SequenceMatcher(None, 'b' * 100, 'a' + 'b' * 100)
  9. self.assertAlmostEqual(sm.ratio(), 0.995, places=3)
  10. self.assertEqual(list(sm.get_opcodes()),
  11. [ ('insert', 0, 0, 0, 1),
  12. ('equal', 0, 100, 1, 101)])
  13. sm = difflib.SequenceMatcher(None, 'b' * 100, 'b' * 50 + 'a' + 'b' * 50)
  14. self.assertAlmostEqual(sm.ratio(), 0.995, places=3)
  15. self.assertEqual(list(sm.get_opcodes()),
  16. [ ('equal', 0, 50, 0, 50),
  17. ('insert', 50, 50, 50, 51),
  18. ('equal', 50, 100, 51, 101)])
  19. def test_one_delete(self):
  20. sm = difflib.SequenceMatcher(None, 'a' * 40 + 'c' + 'b' * 40, 'a' * 40 + 'b' * 40)
  21. self.assertAlmostEqual(sm.ratio(), 0.994, places=3)
  22. self.assertEqual(list(sm.get_opcodes()),
  23. [ ('equal', 0, 40, 0, 40),
  24. ('delete', 40, 41, 40, 40),
  25. ('equal', 41, 81, 40, 80)])
  26. class TestAutojunk(unittest.TestCase):
  27. """Tests for the autojunk parameter added in 2.7"""
  28. def test_one_insert_homogenous_sequence(self):
  29. # By default autojunk=True and the heuristic kicks in for a sequence
  30. # of length 200+
  31. seq1 = 'b' * 200
  32. seq2 = 'a' + 'b' * 200
  33. sm = difflib.SequenceMatcher(None, seq1, seq2)
  34. self.assertAlmostEqual(sm.ratio(), 0, places=3)
  35. # Now turn the heuristic off
  36. sm = difflib.SequenceMatcher(None, seq1, seq2, autojunk=False)
  37. self.assertAlmostEqual(sm.ratio(), 0.9975, places=3)
  38. class TestSFbugs(unittest.TestCase):
  39. def test_ratio_for_null_seqn(self):
  40. # Check clearing of SF bug 763023
  41. s = difflib.SequenceMatcher(None, [], [])
  42. self.assertEqual(s.ratio(), 1)
  43. self.assertEqual(s.quick_ratio(), 1)
  44. self.assertEqual(s.real_quick_ratio(), 1)
  45. def test_comparing_empty_lists(self):
  46. # Check fix for bug #979794
  47. group_gen = difflib.SequenceMatcher(None, [], []).get_grouped_opcodes()
  48. self.assertRaises(StopIteration, group_gen.next)
  49. diff_gen = difflib.unified_diff([], [])
  50. self.assertRaises(StopIteration, diff_gen.next)
  51. def test_matching_blocks_cache(self):
  52. # Issue #21635
  53. s = difflib.SequenceMatcher(None, "abxcd", "abcd")
  54. first = s.get_matching_blocks()
  55. second = s.get_matching_blocks()
  56. self.assertEqual(second[0].size, 2)
  57. self.assertEqual(second[1].size, 2)
  58. self.assertEqual(second[2].size, 0)
  59. def test_added_tab_hint(self):
  60. # Check fix for bug #1488943
  61. diff = list(difflib.Differ().compare(["\tI am a buggy"],["\t\tI am a bug"]))
  62. self.assertEqual("- \tI am a buggy", diff[0])
  63. self.assertEqual("? --\n", diff[1])
  64. self.assertEqual("+ \t\tI am a bug", diff[2])
  65. self.assertEqual("? +\n", diff[3])
  66. patch914575_from1 = """
  67. 1. Beautiful is beTTer than ugly.
  68. 2. Explicit is better than implicit.
  69. 3. Simple is better than complex.
  70. 4. Complex is better than complicated.
  71. """
  72. patch914575_to1 = """
  73. 1. Beautiful is better than ugly.
  74. 3. Simple is better than complex.
  75. 4. Complicated is better than complex.
  76. 5. Flat is better than nested.
  77. """
  78. patch914575_from2 = """
  79. \t\tLine 1: preceeded by from:[tt] to:[ssss]
  80. \t\tLine 2: preceeded by from:[sstt] to:[sssst]
  81. \t \tLine 3: preceeded by from:[sstst] to:[ssssss]
  82. Line 4: \thas from:[sst] to:[sss] after :
  83. Line 5: has from:[t] to:[ss] at end\t
  84. """
  85. patch914575_to2 = """
  86. Line 1: preceeded by from:[tt] to:[ssss]
  87. \tLine 2: preceeded by from:[sstt] to:[sssst]
  88. Line 3: preceeded by from:[sstst] to:[ssssss]
  89. Line 4: has from:[sst] to:[sss] after :
  90. Line 5: has from:[t] to:[ss] at end
  91. """
  92. patch914575_from3 = """line 0
  93. 1234567890123456789012345689012345
  94. line 1
  95. line 2
  96. line 3
  97. line 4 changed
  98. line 5 changed
  99. line 6 changed
  100. line 7
  101. line 8 subtracted
  102. line 9
  103. 1234567890123456789012345689012345
  104. short line
  105. just fits in!!
  106. just fits in two lines yup!!
  107. the end"""
  108. patch914575_to3 = """line 0
  109. 1234567890123456789012345689012345
  110. line 1
  111. line 2 added
  112. line 3
  113. line 4 chanGEd
  114. line 5a chanGed
  115. line 6a changEd
  116. line 7
  117. line 8
  118. line 9
  119. 1234567890
  120. another long line that needs to be wrapped
  121. just fitS in!!
  122. just fits in two lineS yup!!
  123. the end"""
  124. class TestSFpatches(unittest.TestCase):
  125. def test_html_diff(self):
  126. # Check SF patch 914575 for generating HTML differences
  127. f1a = ((patch914575_from1 + '123\n'*10)*3)
  128. t1a = (patch914575_to1 + '123\n'*10)*3
  129. f1b = '456\n'*10 + f1a
  130. t1b = '456\n'*10 + t1a
  131. f1a = f1a.splitlines()
  132. t1a = t1a.splitlines()
  133. f1b = f1b.splitlines()
  134. t1b = t1b.splitlines()
  135. f2 = patch914575_from2.splitlines()
  136. t2 = patch914575_to2.splitlines()
  137. f3 = patch914575_from3
  138. t3 = patch914575_to3
  139. i = difflib.HtmlDiff()
  140. j = difflib.HtmlDiff(tabsize=2)
  141. k = difflib.HtmlDiff(wrapcolumn=14)
  142. full = i.make_file(f1a,t1a,'from','to',context=False,numlines=5)
  143. tables = '\n'.join(
  144. [
  145. '<h2>Context (first diff within numlines=5(default))</h2>',
  146. i.make_table(f1a,t1a,'from','to',context=True),
  147. '<h2>Context (first diff after numlines=5(default))</h2>',
  148. i.make_table(f1b,t1b,'from','to',context=True),
  149. '<h2>Context (numlines=6)</h2>',
  150. i.make_table(f1a,t1a,'from','to',context=True,numlines=6),
  151. '<h2>Context (numlines=0)</h2>',
  152. i.make_table(f1a,t1a,'from','to',context=True,numlines=0),
  153. '<h2>Same Context</h2>',
  154. i.make_table(f1a,f1a,'from','to',context=True),
  155. '<h2>Same Full</h2>',
  156. i.make_table(f1a,f1a,'from','to',context=False),
  157. '<h2>Empty Context</h2>',
  158. i.make_table([],[],'from','to',context=True),
  159. '<h2>Empty Full</h2>',
  160. i.make_table([],[],'from','to',context=False),
  161. '<h2>tabsize=2</h2>',
  162. j.make_table(f2,t2),
  163. '<h2>tabsize=default</h2>',
  164. i.make_table(f2,t2),
  165. '<h2>Context (wrapcolumn=14,numlines=0)</h2>',
  166. k.make_table(f3.splitlines(),t3.splitlines(),context=True,numlines=0),
  167. '<h2>wrapcolumn=14,splitlines()</h2>',
  168. k.make_table(f3.splitlines(),t3.splitlines()),
  169. '<h2>wrapcolumn=14,splitlines(True)</h2>',
  170. k.make_table(f3.splitlines(True),t3.splitlines(True)),
  171. ])
  172. actual = full.replace('</body>','\n%s\n</body>' % tables)
  173. # temporarily uncomment next two lines to baseline this test
  174. #with open('test_difflib_expect.html','w') as fp:
  175. # fp.write(actual)
  176. with open(findfile('test_difflib_expect.html')) as fp:
  177. self.assertEqual(actual, fp.read())
  178. def test_recursion_limit(self):
  179. # Check if the problem described in patch #1413711 exists.
  180. limit = sys.getrecursionlimit()
  181. old = [(i%2 and "K:%d" or "V:A:%d") % i for i in range(limit*2)]
  182. new = [(i%2 and "K:%d" or "V:B:%d") % i for i in range(limit*2)]
  183. difflib.SequenceMatcher(None, old, new).get_opcodes()
  184. class TestOutputFormat(unittest.TestCase):
  185. def test_tab_delimiter(self):
  186. args = ['one', 'two', 'Original', 'Current',
  187. '2005-01-26 23:30:50', '2010-04-02 10:20:52']
  188. ud = difflib.unified_diff(*args, lineterm='')
  189. self.assertEqual(list(ud)[0:2], [
  190. "--- Original\t2005-01-26 23:30:50",
  191. "+++ Current\t2010-04-02 10:20:52"])
  192. cd = difflib.context_diff(*args, lineterm='')
  193. self.assertEqual(list(cd)[0:2], [
  194. "*** Original\t2005-01-26 23:30:50",
  195. "--- Current\t2010-04-02 10:20:52"])
  196. def test_no_trailing_tab_on_empty_filedate(self):
  197. args = ['one', 'two', 'Original', 'Current']
  198. ud = difflib.unified_diff(*args, lineterm='')
  199. self.assertEqual(list(ud)[0:2], ["--- Original", "+++ Current"])
  200. cd = difflib.context_diff(*args, lineterm='')
  201. self.assertEqual(list(cd)[0:2], ["*** Original", "--- Current"])
  202. def test_range_format_unified(self):
  203. # Per the diff spec at http://www.unix.org/single_unix_specification/
  204. spec = '''\
  205. Each <range> field shall be of the form:
  206. %1d", <beginning line number> if the range contains exactly one line,
  207. and:
  208. "%1d,%1d", <beginning line number>, <number of lines> otherwise.
  209. If a range is empty, its beginning line number shall be the number of
  210. the line just before the range, or 0 if the empty range starts the file.
  211. '''
  212. fmt = difflib._format_range_unified
  213. self.assertEqual(fmt(3,3), '3,0')
  214. self.assertEqual(fmt(3,4), '4')
  215. self.assertEqual(fmt(3,5), '4,2')
  216. self.assertEqual(fmt(3,6), '4,3')
  217. self.assertEqual(fmt(0,0), '0,0')
  218. def test_range_format_context(self):
  219. # Per the diff spec at http://www.unix.org/single_unix_specification/
  220. spec = '''\
  221. The range of lines in file1 shall be written in the following format
  222. if the range contains two or more lines:
  223. "*** %d,%d ****\n", <beginning line number>, <ending line number>
  224. and the following format otherwise:
  225. "*** %d ****\n", <ending line number>
  226. The ending line number of an empty range shall be the number of the preceding line,
  227. or 0 if the range is at the start of the file.
  228. Next, the range of lines in file2 shall be written in the following format
  229. if the range contains two or more lines:
  230. "--- %d,%d ----\n", <beginning line number>, <ending line number>
  231. and the following format otherwise:
  232. "--- %d ----\n", <ending line number>
  233. '''
  234. fmt = difflib._format_range_context
  235. self.assertEqual(fmt(3,3), '3')
  236. self.assertEqual(fmt(3,4), '4')
  237. self.assertEqual(fmt(3,5), '4,5')
  238. self.assertEqual(fmt(3,6), '4,6')
  239. self.assertEqual(fmt(0,0), '0')
  240. def test_main():
  241. difflib.HtmlDiff._default_prefix = 0
  242. Doctests = doctest.DocTestSuite(difflib)
  243. run_unittest(
  244. TestWithAscii, TestAutojunk, TestSFpatches, TestSFbugs,
  245. TestOutputFormat, Doctests)
  246. if __name__ == '__main__':
  247. test_main()