From 4f133e2e98930463219f363a60824f989e256fbb Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sat, 13 Jul 2013 02:34:43 -0400 Subject: [PATCH] Issue #18279: Add tests for idlelib/RstripExtension.py. Original patch by Phil Webster. With that available, modify RstripExtension.py to stop deleting null slices, which caused a file to be marked as changed when it was not. --- Lib/idlelib/RstripExtension.py | 20 +++++++----- Lib/idlelib/idle_test/mock_idle.py | 27 +++++++++++++++ Lib/idlelib/idle_test/test_rstrip.py | 49 ++++++++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 5 +++ 5 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 Lib/idlelib/idle_test/mock_idle.py create mode 100644 Lib/idlelib/idle_test/test_rstrip.py diff --git a/Lib/idlelib/RstripExtension.py b/Lib/idlelib/RstripExtension.py index 19e35d4d481..2ce3c7eafe5 100644 --- a/Lib/idlelib/RstripExtension.py +++ b/Lib/idlelib/RstripExtension.py @@ -1,13 +1,9 @@ 'Provides "Strip trailing whitespace" under the "Format" menu.' -__author__ = "Roger D. Serwy " - class RstripExtension: menudefs = [ - ('format', [None, - ('Strip trailing whitespace', '<>'), - ]),] + ('format', [None, ('Strip trailing whitespace', '<>'), ] ), ] def __init__(self, editwin): self.editwin = editwin @@ -20,10 +16,18 @@ class RstripExtension: undo.undo_block_start() - end_line = int(float(text.index('end'))) + 1 + end_line = int(float(text.index('end'))) for cur in range(1, end_line): - txt = text.get('%i.0' % cur, '%i.0 lineend' % cur) + txt = text.get('%i.0' % cur, '%i.end' % cur) + raw = len(txt) cut = len(txt.rstrip()) - text.delete('%i.%i' % (cur, cut), '%i.0 lineend' % cur) + # Since text.delete() marks file as changed, even if not, + # only call it when needed to actually delete something. + if cut < raw: + text.delete('%i.%i' % (cur, cut), '%i.end' % cur) undo.undo_block_stop() + +if __name__ == "__main__": + import unittest + unittest.main('idlelib.idle_test.test_rstrip', verbosity=2, exit=False) diff --git a/Lib/idlelib/idle_test/mock_idle.py b/Lib/idlelib/idle_test/mock_idle.py new file mode 100644 index 00000000000..c364a24dacb --- /dev/null +++ b/Lib/idlelib/idle_test/mock_idle.py @@ -0,0 +1,27 @@ +'''Mock classes that imitate idlelib modules or classes. + +Attributes and methods will be added as needed for tests. +''' + +from idlelib.idle_test.mock_tk import Text + +class Editor: + '''Minimally imitate EditorWindow.EditorWindow class. + ''' + def __init__(self, flist=None, filename=None, key=None, root=None): + self.text = Text() + self.undo = UndoDelegator() + + def get_selection_indices(self): + first = self.text.index('1.0') + last = self.text.index('end') + return first, last + +class UndoDelegator: + '''Minimally imitate UndoDelegator,UndoDelegator class. + ''' + # A real undo block is only needed for user interaction. + def undo_block_start(*args): + pass + def undo_block_stop(*args): + pass diff --git a/Lib/idlelib/idle_test/test_rstrip.py b/Lib/idlelib/idle_test/test_rstrip.py new file mode 100644 index 00000000000..1c90b93d216 --- /dev/null +++ b/Lib/idlelib/idle_test/test_rstrip.py @@ -0,0 +1,49 @@ +import unittest +import idlelib.RstripExtension as rs +from idlelib.idle_test.mock_idle import Editor + +class rstripTest(unittest.TestCase): + + def test_rstrip_line(self): + editor = Editor() + text = editor.text + do_rstrip = rs.RstripExtension(editor).do_rstrip + + do_rstrip() + self.assertEqual(text.get('1.0', 'insert'), '') + text.insert('1.0', ' ') + do_rstrip() + self.assertEqual(text.get('1.0', 'insert'), '') + text.insert('1.0', ' \n') + do_rstrip() + self.assertEqual(text.get('1.0', 'insert'), '\n') + + def test_rstrip_multiple(self): + editor = Editor() + # Uncomment following to verify that test passes with real widgets. +## from idlelib.EditorWindow import EditorWindow as Editor +## from tkinter import Tk +## editor = Editor(root=Tk()) + text = editor.text + do_rstrip = rs.RstripExtension(editor).do_rstrip + + original = ( + "Line with an ending tab \n" + "Line ending in 5 spaces \n" + "Linewithnospaces\n" + " indented line\n" + " indented line with trailing space \n" + " ") + stripped = ( + "Line with an ending tab\n" + "Line ending in 5 spaces\n" + "Linewithnospaces\n" + " indented line\n" + " indented line with trailing space\n") + + text.insert('1.0', original) + do_rstrip() + self.assertEqual(text.get('1.0', 'insert'), stripped) + +if __name__ == '__main__': + unittest.main(verbosity=2, exit=False) diff --git a/Misc/ACKS b/Misc/ACKS index 087db243ce7..b568eec64fd 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1303,6 +1303,7 @@ Aaron Watters Henrik Weber Corran Webster Glyn Webster +Phil Webster Stefan Wehr Zack Weinberg Bob Weiner diff --git a/Misc/NEWS b/Misc/NEWS index 65e60f4b781..4f90cae3a3b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -160,6 +160,10 @@ C API IDLE ---- +- Issue #18279: Format - Strip trailing whitespace no longer marks a file as + changed when it has not been changed. This fix followed the addition of a + test file originally written by Phil Webster (the issue's main goal). + - Issue #7136: In the Idle File menu, "New Window" is renamed "New File". Patch by Tal Einat, Roget Serwy, and Todd Rovito. @@ -176,6 +180,7 @@ IDLE - Issue #15392: Create a unittest framework for IDLE. Initial patch by Rajagopalasarma Jayakrishnan. + See Lib/idlelib/idle_test/README.txt for how to run Idle tests. - Issue #14146: Highlight source line while debugging on Windows.