Coverage for idle_test/test_format.py: 54%

376 statements  

« prev     ^ index     » next       coverage.py v7.2.5, created at 2023-05-11 13:22 -0700

1"Test format, coverage 99%." 

2 

3from idlelib import format as ft 

4import unittest 

5from unittest import mock 

6from test.support import requires 

7from tkinter import Tk, Text 

8from idlelib.editor import EditorWindow 

9from idlelib.idle_test.mock_idle import Editor as MockEditor 

10 

11 

12class Is_Get_Test(unittest.TestCase): 

13 """Test the is_ and get_ functions""" 

14 test_comment = '# This is a comment' 

15 test_nocomment = 'This is not a comment' 

16 trailingws_comment = '# This is a comment ' 

17 leadingws_comment = ' # This is a comment' 

18 leadingws_nocomment = ' This is not a comment' 

19 

20 def test_is_all_white(self): 

21 self.assertTrue(ft.is_all_white('')) 1k

22 self.assertTrue(ft.is_all_white('\t\n\r\f\v')) 1k

23 self.assertFalse(ft.is_all_white(self.test_comment)) 1k

24 

25 def test_get_indent(self): 

26 Equal = self.assertEqual 1i

27 Equal(ft.get_indent(self.test_comment), '') 1i

28 Equal(ft.get_indent(self.trailingws_comment), '') 1i

29 Equal(ft.get_indent(self.leadingws_comment), ' ') 1i

30 Equal(ft.get_indent(self.leadingws_nocomment), ' ') 1i

31 

32 def test_get_comment_header(self): 

33 Equal = self.assertEqual 1h

34 # Test comment strings 

35 Equal(ft.get_comment_header(self.test_comment), '#') 1h

36 Equal(ft.get_comment_header(self.trailingws_comment), '#') 1h

37 Equal(ft.get_comment_header(self.leadingws_comment), ' #') 1h

38 # Test non-comment strings 

39 Equal(ft.get_comment_header(self.leadingws_nocomment), ' ') 1h

40 Equal(ft.get_comment_header(self.test_nocomment), '') 1h

41 

42 

43class FindTest(unittest.TestCase): 

44 """Test the find_paragraph function in paragraph module. 

45 

46 Using the runcase() function, find_paragraph() is called with 'mark' set at 

47 multiple indexes before and inside the test paragraph. 

48 

49 It appears that code with the same indentation as a quoted string is grouped 

50 as part of the same paragraph, which is probably incorrect behavior. 

51 """ 

52 

53 @classmethod 

54 def setUpClass(cls): 

55 from idlelib.idle_test.mock_tk import Text 

56 cls.text = Text() 

57 

58 def runcase(self, inserttext, stopline, expected): 

59 # Check that find_paragraph returns the expected paragraph when 

60 # the mark index is set to beginning, middle, end of each line 

61 # up to but not including the stop line 

62 text = self.text 1bc

63 text.insert('1.0', inserttext) 1bc

64 for line in range(1, stopline): 1bc

65 linelength = int(text.index("%d.end" % line).split('.')[1]) 1bc

66 for col in (0, linelength//2, linelength): 1bc

67 tempindex = "%d.%d" % (line, col) 1bc

68 self.assertEqual(ft.find_paragraph(text, tempindex), expected) 1bc

69 text.delete('1.0', 'end') 1bc

70 

71 def test_find_comment(self): 

72 comment = ( 1b

73 "# Comment block with no blank lines before\n" 

74 "# Comment line\n" 

75 "\n") 

76 self.runcase(comment, 3, ('1.0', '3.0', '#', comment[0:58])) 1b

77 

78 comment = ( 1b

79 "\n" 

80 "# Comment block with whitespace line before and after\n" 

81 "# Comment line\n" 

82 "\n") 

83 self.runcase(comment, 4, ('2.0', '4.0', '#', comment[1:70])) 1b

84 

85 comment = ( 1b

86 "\n" 

87 " # Indented comment block with whitespace before and after\n" 

88 " # Comment line\n" 

89 "\n") 

90 self.runcase(comment, 4, ('2.0', '4.0', ' #', comment[1:82])) 1b

91 

92 comment = ( 1b

93 "\n" 

94 "# Single line comment\n" 

95 "\n") 

96 self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:23])) 1b

97 

98 comment = ( 1b

99 "\n" 

100 " # Single line comment with leading whitespace\n" 

101 "\n") 

102 self.runcase(comment, 3, ('2.0', '3.0', ' #', comment[1:51])) 1b

103 

104 comment = ( 1b

105 "\n" 

106 "# Comment immediately followed by code\n" 

107 "x = 42\n" 

108 "\n") 

109 self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:40])) 1b

110 

111 comment = ( 1b

112 "\n" 

113 " # Indented comment immediately followed by code\n" 

114 "x = 42\n" 

115 "\n") 

116 self.runcase(comment, 3, ('2.0', '3.0', ' #', comment[1:53])) 1b

117 

118 comment = ( 1b

119 "\n" 

120 "# Comment immediately followed by indented code\n" 

121 " x = 42\n" 

122 "\n") 

123 self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:49])) 1b

124 

125 def test_find_paragraph(self): 

126 teststring = ( 1c

127 '"""String with no blank lines before\n' 

128 'String line\n' 

129 '"""\n' 

130 '\n') 

131 self.runcase(teststring, 4, ('1.0', '4.0', '', teststring[0:53])) 1c

132 

133 teststring = ( 1c

134 "\n" 

135 '"""String with whitespace line before and after\n' 

136 'String line.\n' 

137 '"""\n' 

138 '\n') 

139 self.runcase(teststring, 5, ('2.0', '5.0', '', teststring[1:66])) 1c

140 

141 teststring = ( 1c

142 '\n' 

143 ' """Indented string with whitespace before and after\n' 

144 ' Comment string.\n' 

145 ' """\n' 

146 '\n') 

147 self.runcase(teststring, 5, ('2.0', '5.0', ' ', teststring[1:85])) 1c

148 

149 teststring = ( 1c

150 '\n' 

151 '"""Single line string."""\n' 

152 '\n') 

153 self.runcase(teststring, 3, ('2.0', '3.0', '', teststring[1:27])) 1c

154 

155 teststring = ( 1c

156 '\n' 

157 ' """Single line string with leading whitespace."""\n' 

158 '\n') 

159 self.runcase(teststring, 3, ('2.0', '3.0', ' ', teststring[1:55])) 1c

160 

161 

162class ReformatFunctionTest(unittest.TestCase): 

163 """Test the reformat_paragraph function without the editor window.""" 

164 

165 def test_reformat_paragraph(self): 

166 Equal = self.assertEqual 1e

167 reform = ft.reformat_paragraph 1e

168 hw = "O hello world" 1e

169 Equal(reform(' ', 1), ' ') 1e

170 Equal(reform("Hello world", 20), "Hello world") 1e

171 

172 # Test without leading newline 

173 Equal(reform(hw, 1), "O\nhello\nworld") 1e

174 Equal(reform(hw, 6), "O\nhello\nworld") 1e

175 Equal(reform(hw, 7), "O hello\nworld") 1e

176 Equal(reform(hw, 12), "O hello\nworld") 1e

177 Equal(reform(hw, 13), "O hello world") 1e

178 

179 # Test with leading newline 

180 hw = "\nO hello world" 1e

181 Equal(reform(hw, 1), "\nO\nhello\nworld") 1e

182 Equal(reform(hw, 6), "\nO\nhello\nworld") 1e

183 Equal(reform(hw, 7), "\nO hello\nworld") 1e

184 Equal(reform(hw, 12), "\nO hello\nworld") 1e

185 Equal(reform(hw, 13), "\nO hello world") 1e

186 

187 

188class ReformatCommentTest(unittest.TestCase): 

189 """Test the reformat_comment function without the editor window.""" 

190 

191 def test_reformat_comment(self): 

192 Equal = self.assertEqual 1g

193 

194 # reformat_comment formats to a minimum of 20 characters 

195 test_string = ( 1g

196 " \"\"\"this is a test of a reformat for a triple quoted string" 

197 " will it reformat to less than 70 characters for me?\"\"\"") 

198 result = ft.reformat_comment(test_string, 70, " ") 1g

199 expected = ( 1g

200 " \"\"\"this is a test of a reformat for a triple quoted string will it\n" 

201 " reformat to less than 70 characters for me?\"\"\"") 

202 Equal(result, expected) 1g

203 

204 test_comment = ( 1g

205 "# this is a test of a reformat for a triple quoted string will " 

206 "it reformat to less than 70 characters for me?") 

207 result = ft.reformat_comment(test_comment, 70, "#") 1g

208 expected = ( 1g

209 "# this is a test of a reformat for a triple quoted string will it\n" 

210 "# reformat to less than 70 characters for me?") 

211 Equal(result, expected) 1g

212 

213 

214class FormatClassTest(unittest.TestCase): 

215 def test_init_close(self): 

216 instance = ft.FormatParagraph('editor') 1j

217 self.assertEqual(instance.editwin, 'editor') 1j

218 instance.close() 1j

219 self.assertEqual(instance.editwin, None) 1j

220 

221 

222# For testing format_paragraph_event, Initialize FormatParagraph with 

223# a mock Editor with .text and .get_selection_indices. The text must 

224# be a Text wrapper that adds two methods 

225 

226# A real EditorWindow creates unneeded, time-consuming baggage and 

227# sometimes emits shutdown warnings like this: 

228# "warning: callback failed in WindowList <class '_tkinter.TclError'> 

229# : invalid command name ".55131368.windows". 

230# Calling EditorWindow._close in tearDownClass prevents this but causes 

231# other problems (windows left open). 

232 

233class TextWrapper: 

234 def __init__(self, master): 

235 self.text = Text(master=master) 

236 def __getattr__(self, name): 

237 return getattr(self.text, name) 

238 def undo_block_start(self): pass 238 ↛ exitline 238 didn't return from function 'undo_block_start'

239 def undo_block_stop(self): pass 239 ↛ exitline 239 didn't return from function 'undo_block_stop'

240 

241class Editor: 

242 def __init__(self, root): 

243 self.text = TextWrapper(root) 

244 get_selection_indices = EditorWindow. get_selection_indices 

245 

246class FormatEventTest(unittest.TestCase): 

247 """Test the formatting of text inside a Text widget. 

248 

249 This is done with FormatParagraph.format.paragraph_event, 

250 which calls functions in the module as appropriate. 

251 """ 

252 test_string = ( 

253 " '''this is a test of a reformat for a triple " 

254 "quoted string will it reformat to less than 70 " 

255 "characters for me?'''\n") 

256 multiline_test_string = ( 

257 " '''The first line is under the max width.\n" 

258 " The second line's length is way over the max width. It goes " 

259 "on and on until it is over 100 characters long.\n" 

260 " Same thing with the third line. It is also way over the max " 

261 "width, but FormatParagraph will fix it.\n" 

262 " '''\n") 

263 multiline_test_comment = ( 

264 "# The first line is under the max width.\n" 

265 "# The second line's length is way over the max width. It goes on " 

266 "and on until it is over 100 characters long.\n" 

267 "# Same thing with the third line. It is also way over the max " 

268 "width, but FormatParagraph will fix it.\n" 

269 "# The fourth line is short like the first line.") 

270 

271 @classmethod 

272 def setUpClass(cls): 

273 requires('gui') 

274 cls.root = Tk() 

275 cls.root.withdraw() 

276 editor = Editor(root=cls.root) 

277 cls.text = editor.text.text # Test code does not need the wrapper. 

278 cls.formatter = ft.FormatParagraph(editor).format_paragraph_event 

279 # Sets the insert mark just after the re-wrapped and inserted text. 

280 

281 @classmethod 

282 def tearDownClass(cls): 

283 del cls.text, cls.formatter 

284 cls.root.update_idletasks() 

285 cls.root.destroy() 

286 del cls.root 

287 

288 def test_short_line(self): 

289 self.text.insert('1.0', "Short line\n") 

290 self.formatter("Dummy") 

291 self.assertEqual(self.text.get('1.0', 'insert'), "Short line\n" ) 

292 self.text.delete('1.0', 'end') 

293 

294 def test_long_line(self): 

295 text = self.text 

296 

297 # Set cursor ('insert' mark) to '1.0', within text. 

298 text.insert('1.0', self.test_string) 

299 text.mark_set('insert', '1.0') 

300 self.formatter('ParameterDoesNothing', limit=70) 

301 result = text.get('1.0', 'insert') 

302 # find function includes \n 

303 expected = ( 

304" '''this is a test of a reformat for a triple quoted string will it\n" 

305" reformat to less than 70 characters for me?'''\n") # yes 

306 self.assertEqual(result, expected) 

307 text.delete('1.0', 'end') 

308 

309 # Select from 1.11 to line end. 

310 text.insert('1.0', self.test_string) 

311 text.tag_add('sel', '1.11', '1.end') 

312 self.formatter('ParameterDoesNothing', limit=70) 

313 result = text.get('1.0', 'insert') 

314 # selection excludes \n 

315 expected = ( 

316" '''this is a test of a reformat for a triple quoted string will it reformat\n" 

317" to less than 70 characters for me?'''") # no 

318 self.assertEqual(result, expected) 

319 text.delete('1.0', 'end') 

320 

321 def test_multiple_lines(self): 

322 text = self.text 

323 # Select 2 long lines. 

324 text.insert('1.0', self.multiline_test_string) 

325 text.tag_add('sel', '2.0', '4.0') 

326 self.formatter('ParameterDoesNothing', limit=70) 

327 result = text.get('2.0', 'insert') 

328 expected = ( 

329" The second line's length is way over the max width. It goes on and\n" 

330" on until it is over 100 characters long. Same thing with the third\n" 

331" line. It is also way over the max width, but FormatParagraph will\n" 

332" fix it.\n") 

333 self.assertEqual(result, expected) 

334 text.delete('1.0', 'end') 

335 

336 def test_comment_block(self): 

337 text = self.text 

338 

339 # Set cursor ('insert') to '1.0', within block. 

340 text.insert('1.0', self.multiline_test_comment) 

341 self.formatter('ParameterDoesNothing', limit=70) 

342 result = text.get('1.0', 'insert') 

343 expected = ( 

344"# The first line is under the max width. The second line's length is\n" 

345"# way over the max width. It goes on and on until it is over 100\n" 

346"# characters long. Same thing with the third line. It is also way over\n" 

347"# the max width, but FormatParagraph will fix it. The fourth line is\n" 

348"# short like the first line.\n") 

349 self.assertEqual(result, expected) 

350 text.delete('1.0', 'end') 

351 

352 # Select line 2, verify line 1 unaffected. 

353 text.insert('1.0', self.multiline_test_comment) 

354 text.tag_add('sel', '2.0', '3.0') 

355 self.formatter('ParameterDoesNothing', limit=70) 

356 result = text.get('1.0', 'insert') 

357 expected = ( 

358"# The first line is under the max width.\n" 

359"# The second line's length is way over the max width. It goes on and\n" 

360"# on until it is over 100 characters long.\n") 

361 self.assertEqual(result, expected) 

362 text.delete('1.0', 'end') 

363 

364# The following block worked with EditorWindow but fails with the mock. 

365# Lines 2 and 3 get pasted together even though the previous block left 

366# the previous line alone. More investigation is needed. 

367## # Select lines 3 and 4 

368## text.insert('1.0', self.multiline_test_comment) 

369## text.tag_add('sel', '3.0', '5.0') 

370## self.formatter('ParameterDoesNothing') 

371## result = text.get('3.0', 'insert') 

372## expected = ( 

373##"# Same thing with the third line. It is also way over the max width,\n" 

374##"# but FormatParagraph will fix it. The fourth line is short like the\n" 

375##"# first line.\n") 

376## self.assertEqual(result, expected) 

377## text.delete('1.0', 'end') 

378 

379 

380class DummyEditwin: 

381 def __init__(self, root, text): 

382 self.root = root 1df

383 self.text = text 1df

384 self.indentwidth = 4 1df

385 self.tabwidth = 4 1df

386 self.usetabs = False 1df

387 self.context_use_ps1 = True 1df

388 

389 _make_blanks = EditorWindow._make_blanks 

390 get_selection_indices = EditorWindow.get_selection_indices 

391 

392 

393class FormatRegionTest(unittest.TestCase): 

394 

395 @classmethod 

396 def setUpClass(cls): 

397 requires('gui') 

398 cls.root = Tk() 

399 cls.root.withdraw() 

400 cls.text = Text(cls.root) 

401 cls.text.undo_block_start = mock.Mock() 

402 cls.text.undo_block_stop = mock.Mock() 

403 cls.editor = DummyEditwin(cls.root, cls.text) 

404 cls.formatter = ft.FormatRegion(cls.editor) 

405 

406 @classmethod 

407 def tearDownClass(cls): 

408 del cls.text, cls.formatter, cls.editor 

409 cls.root.update_idletasks() 

410 cls.root.destroy() 

411 del cls.root 

412 

413 def setUp(self): 

414 self.text.insert('1.0', self.code_sample) 

415 

416 def tearDown(self): 

417 self.text.delete('1.0', 'end') 

418 

419 code_sample = """\ 

420# WS line needed for test. 

421class C1: 

422 # Class comment. 

423 def __init__(self, a, b): 

424 self.a = a 

425 self.b = b 

426 

427 def compare(self): 

428 if a > b: 

429 return a 

430 elif a < b: 

431 return b 

432 else: 

433 return None 

434""" 

435 

436 def test_get_region(self): 

437 get = self.formatter.get_region 

438 text = self.text 

439 eq = self.assertEqual 

440 

441 # Add selection. 

442 text.tag_add('sel', '7.0', '10.0') 

443 expected_lines = ['', 

444 ' def compare(self):', 

445 ' if a > b:', 

446 ''] 

447 eq(get(), ('7.0', '10.0', '\n'.join(expected_lines), expected_lines)) 

448 

449 # Remove selection. 

450 text.tag_remove('sel', '1.0', 'end') 

451 eq(get(), ('15.0', '16.0', '\n', ['', ''])) 

452 

453 def test_set_region(self): 

454 set_ = self.formatter.set_region 

455 text = self.text 

456 eq = self.assertEqual 

457 

458 save_bell = text.bell 

459 text.bell = mock.Mock() 

460 line6 = self.code_sample.splitlines()[5] 

461 line10 = self.code_sample.splitlines()[9] 

462 

463 text.tag_add('sel', '6.0', '11.0') 

464 head, tail, chars, lines = self.formatter.get_region() 

465 

466 # No changes. 

467 set_(head, tail, chars, lines) 

468 text.bell.assert_called_once() 

469 eq(text.get('6.0', '11.0'), chars) 

470 eq(text.get('sel.first', 'sel.last'), chars) 

471 text.tag_remove('sel', '1.0', 'end') 

472 

473 # Alter selected lines by changing lines and adding a newline. 

474 newstring = 'added line 1\n\n\n\n' 

475 newlines = newstring.split('\n') 

476 set_('7.0', '10.0', chars, newlines) 

477 # Selection changed. 

478 eq(text.get('sel.first', 'sel.last'), newstring) 

479 # Additional line added, so last index is changed. 

480 eq(text.get('7.0', '11.0'), newstring) 

481 # Before and after lines unchanged. 

482 eq(text.get('6.0', '7.0-1c'), line6) 

483 eq(text.get('11.0', '12.0-1c'), line10) 

484 text.tag_remove('sel', '1.0', 'end') 

485 

486 text.bell = save_bell 

487 

488 def test_indent_region_event(self): 

489 indent = self.formatter.indent_region_event 

490 text = self.text 

491 eq = self.assertEqual 

492 

493 text.tag_add('sel', '7.0', '10.0') 

494 indent() 

495 # Blank lines aren't affected by indent. 

496 eq(text.get('7.0', '10.0'), ('\n def compare(self):\n if a > b:\n')) 

497 

498 def test_dedent_region_event(self): 

499 dedent = self.formatter.dedent_region_event 

500 text = self.text 

501 eq = self.assertEqual 

502 

503 text.tag_add('sel', '7.0', '10.0') 

504 dedent() 

505 # Blank lines aren't affected by dedent. 

506 eq(text.get('7.0', '10.0'), ('\ndef compare(self):\n if a > b:\n')) 

507 

508 def test_comment_region_event(self): 

509 comment = self.formatter.comment_region_event 

510 text = self.text 

511 eq = self.assertEqual 

512 

513 text.tag_add('sel', '7.0', '10.0') 

514 comment() 

515 eq(text.get('7.0', '10.0'), ('##\n## def compare(self):\n## if a > b:\n')) 

516 

517 def test_uncomment_region_event(self): 

518 comment = self.formatter.comment_region_event 

519 uncomment = self.formatter.uncomment_region_event 

520 text = self.text 

521 eq = self.assertEqual 

522 

523 text.tag_add('sel', '7.0', '10.0') 

524 comment() 

525 uncomment() 

526 eq(text.get('7.0', '10.0'), ('\n def compare(self):\n if a > b:\n')) 

527 

528 # Only remove comments at the beginning of a line. 

529 text.tag_remove('sel', '1.0', 'end') 

530 text.tag_add('sel', '3.0', '4.0') 

531 uncomment() 

532 eq(text.get('3.0', '3.end'), (' # Class comment.')) 

533 

534 self.formatter.set_region('3.0', '4.0', '', ['# Class comment.', '']) 

535 uncomment() 

536 eq(text.get('3.0', '3.end'), (' Class comment.')) 

537 

538 @mock.patch.object(ft.FormatRegion, "_asktabwidth") 

539 def test_tabify_region_event(self, _asktabwidth): 

540 tabify = self.formatter.tabify_region_event 

541 text = self.text 

542 eq = self.assertEqual 

543 

544 text.tag_add('sel', '7.0', '10.0') 

545 # No tabwidth selected. 

546 _asktabwidth.return_value = None 

547 self.assertIsNone(tabify()) 

548 

549 _asktabwidth.return_value = 3 

550 self.assertIsNotNone(tabify()) 

551 eq(text.get('7.0', '10.0'), ('\n\t def compare(self):\n\t\t if a > b:\n')) 

552 

553 @mock.patch.object(ft.FormatRegion, "_asktabwidth") 

554 def test_untabify_region_event(self, _asktabwidth): 

555 untabify = self.formatter.untabify_region_event 

556 text = self.text 

557 eq = self.assertEqual 

558 

559 text.tag_add('sel', '7.0', '10.0') 

560 # No tabwidth selected. 

561 _asktabwidth.return_value = None 

562 self.assertIsNone(untabify()) 

563 

564 _asktabwidth.return_value = 2 

565 self.formatter.tabify_region_event() 

566 _asktabwidth.return_value = 3 

567 self.assertIsNotNone(untabify()) 

568 eq(text.get('7.0', '10.0'), ('\n def compare(self):\n if a > b:\n')) 

569 

570 @mock.patch.object(ft, "askinteger") 

571 def test_ask_tabwidth(self, askinteger): 

572 ask = self.formatter._asktabwidth 

573 askinteger.return_value = 10 

574 self.assertEqual(ask(), 10) 

575 

576 

577class IndentsTest(unittest.TestCase): 

578 

579 @mock.patch.object(ft, "askyesno") 

580 def test_toggle_tabs(self, askyesno): 

581 editor = DummyEditwin(None, None) # usetabs == False. 1f

582 indents = ft.Indents(editor) 1f

583 askyesno.return_value = True 1f

584 

585 indents.toggle_tabs_event(None) 1f

586 self.assertEqual(editor.usetabs, True) 1f

587 self.assertEqual(editor.indentwidth, 8) 1f

588 

589 indents.toggle_tabs_event(None) 1f

590 self.assertEqual(editor.usetabs, False) 1f

591 self.assertEqual(editor.indentwidth, 8) 1f

592 

593 @mock.patch.object(ft, "askinteger") 

594 def test_change_indentwidth(self, askinteger): 

595 editor = DummyEditwin(None, None) # indentwidth == 4. 1d

596 indents = ft.Indents(editor) 1d

597 

598 askinteger.return_value = None 1d

599 indents.change_indentwidth_event(None) 1d

600 self.assertEqual(editor.indentwidth, 4) 1d

601 

602 askinteger.return_value = 3 1d

603 indents.change_indentwidth_event(None) 1d

604 self.assertEqual(editor.indentwidth, 3) 1d

605 

606 askinteger.return_value = 5 1d

607 editor.usetabs = True 1d

608 indents.change_indentwidth_event(None) 1d

609 self.assertEqual(editor.indentwidth, 3) 1d

610 

611 

612class RstripTest(unittest.TestCase): 

613 

614 @classmethod 

615 def setUpClass(cls): 

616 requires('gui') 

617 cls.root = Tk() 

618 cls.root.withdraw() 

619 cls.text = Text(cls.root) 

620 cls.editor = MockEditor(text=cls.text) 

621 cls.do_rstrip = ft.Rstrip(cls.editor).do_rstrip 

622 

623 @classmethod 

624 def tearDownClass(cls): 

625 del cls.text, cls.do_rstrip, cls.editor 

626 cls.root.update_idletasks() 

627 cls.root.destroy() 

628 del cls.root 

629 

630 def tearDown(self): 

631 self.text.delete('1.0', 'end-1c') 

632 

633 def test_rstrip_lines(self): 

634 original = ( 

635 "Line with an ending tab \n" 

636 "Line ending in 5 spaces \n" 

637 "Linewithnospaces\n" 

638 " indented line\n" 

639 " indented line with trailing space \n" 

640 " \n") 

641 stripped = ( 

642 "Line with an ending tab\n" 

643 "Line ending in 5 spaces\n" 

644 "Linewithnospaces\n" 

645 " indented line\n" 

646 " indented line with trailing space\n") 

647 

648 self.text.insert('1.0', original) 

649 self.do_rstrip() 

650 self.assertEqual(self.text.get('1.0', 'insert'), stripped) 

651 

652 def test_rstrip_end(self): 

653 text = self.text 

654 for code in ('', '\n', '\n\n\n'): 

655 with self.subTest(code=code): 

656 text.insert('1.0', code) 

657 self.do_rstrip() 

658 self.assertEqual(text.get('1.0','end-1c'), '') 

659 for code in ('a\n', 'a\n\n', 'a\n\n\n'): 

660 with self.subTest(code=code): 

661 text.delete('1.0', 'end-1c') 

662 text.insert('1.0', code) 

663 self.do_rstrip() 

664 self.assertEqual(text.get('1.0','end-1c'), 'a\n') 

665 

666 

667if __name__ == '__main__': 667 ↛ 668line 667 didn't jump to line 668, because the condition on line 667 was never true

668 unittest.main(verbosity=2, exit=2)