Extra newlines are removed at the end of non-shell files. If the file only has newlines after stripping other trailing whitespace, all are removed, as is done by patchcheck.py.
Strip trailing whitespace
Remove trailing space and other whitespace characters after the last
non-whitespace character of a line by applying str.rstrip to each line,
- including lines within multiline strings.
+ including lines within multiline strings. Except for Shell windows,
+ remove extra newlines at the end of the file.
.. index::
single: Run script
======================================
+bpo-38862: 'Strip Trailing Whitespace' on the Format menu removes extra
+newlines at the end of non-shell files.
+
bpo-38636: Fix IDLE Format menu tab toggle and file indent width. These
functions (default shortcuts Alt-T and Alt-U) were mistakenly disabled
in 3.7.5 and 3.8.0.
if cut < raw:
text.delete('%i.%i' % (cur, cut), '%i.end' % cur)
+ if (text.get('end-2c') == '\n' # File ends with at least 1 newline;
+ and not hasattr(self.editwin, 'interp')): # & is not Shell.
+ # Delete extra user endlines.
+ while (text.index('end-1c') > '1.0' # Stop if file empty.
+ and text.get('end-3c') == '\n'):
+ text.delete('end-3c')
+ # Because tk indexes are slice indexes and never raise,
+ # a file with only newlines will be emptied.
+ # patchcheck.py does the same.
+
undo.undo_block_stop()
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
- <title>IDLE — Python 3.9.0a0 documentation</title>
+ <title>IDLE — Python 3.9.0a1 documentation</title>
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript" src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
- title="Search within Python 3.9.0a0 documentation"
+ title="Search within Python 3.9.0a1 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="Other Graphical User Interface Packages" href="othergui.html" />
- <link rel="prev" title="tkinter.scrolledtext — Scrolled Text Widget" href="tkinter.scrolledtext.html" />
+ <link rel="prev" title="tkinter.tix — Extension widgets for Tk" href="tkinter.tix.html" />
<link rel="canonical" href="https://docs.python.org/3/library/idle.html" />
<a href="othergui.html" title="Other Graphical User Interface Packages"
accesskey="N">next</a> |</li>
<li class="right" >
- <a href="tkinter.scrolledtext.html" title="tkinter.scrolledtext — Scrolled Text Widget"
+ <a href="tkinter.tix.html" title="tkinter.tix — Extension widgets for Tk"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.png" alt=""
<li>
- <a href="../index.html">3.9.0a0 Documentation</a> »
+ <a href="../index.html">3.9.0a1 Documentation</a> »
</li>
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
</dd>
<dt>Strip trailing whitespace</dt><dd><p>Remove trailing space and other whitespace characters after the last
non-whitespace character of a line by applying str.rstrip to each line,
-including lines within multiline strings.</p>
+including lines within multiline strings. Except for Shell windows,
+remove extra newlines at the end of the file.</p>
</dd>
</dl>
</div>
</ul>
<h4>Previous topic</h4>
- <p class="topless"><a href="tkinter.scrolledtext.html"
- title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter.scrolledtext</span></code> — Scrolled Text Widget</a></p>
+ <p class="topless"><a href="tkinter.tix.html"
+ title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter.tix</span></code> — Extension widgets for Tk</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="othergui.html"
title="next chapter">Other Graphical User Interface Packages</a></p>
<a href="othergui.html" title="Other Graphical User Interface Packages"
>next</a> |</li>
<li class="right" >
- <a href="tkinter.scrolledtext.html" title="tkinter.scrolledtext — Scrolled Text Widget"
+ <a href="tkinter.tix.html" title="tkinter.tix — Extension widgets for Tk"
>previous</a> |</li>
<li><img src="../_static/py.png" alt=""
<li>
- <a href="../index.html">3.9.0a0 Documentation</a> »
+ <a href="../index.html">3.9.0a1 Documentation</a> »
</li>
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
<br />
<br />
- Last updated on Sep 01, 2019.
+ Last updated on Nov 24, 2019.
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
<br />
- Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 2.1.2.
+ Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 2.1.1.
</div>
</body>
class Editor:
'''Minimally imitate editor.EditorWindow class.
'''
- def __init__(self, flist=None, filename=None, key=None, root=None):
- self.text = Text()
+ def __init__(self, flist=None, filename=None, key=None, root=None,
+ text=None): # Allow real Text with mock Editor.
+ self.text = text or Text()
self.undo = UndoDelegator()
def get_selection_indices(self):
class RstripTest(unittest.TestCase):
- def test_rstrip_line(self):
- editor = MockEditor()
- text = editor.text
- do_rstrip = ft.Rstrip(editor).do_rstrip
- eq = self.assertEqual
+ @classmethod
+ def setUpClass(cls):
+ requires('gui')
+ cls.root = Tk()
+ cls.root.withdraw()
+ cls.text = Text(cls.root)
+ cls.editor = MockEditor(text=cls.text)
+ cls.do_rstrip = ft.Rstrip(cls.editor).do_rstrip
+
+ @classmethod
+ def tearDownClass(cls):
+ del cls.text, cls.do_rstrip, cls.editor
+ cls.root.update_idletasks()
+ cls.root.destroy()
+ del cls.root
- do_rstrip()
- eq(text.get('1.0', 'insert'), '')
- text.insert('1.0', ' ')
- do_rstrip()
- eq(text.get('1.0', 'insert'), '')
- text.insert('1.0', ' \n')
- do_rstrip()
- eq(text.get('1.0', 'insert'), '\n')
-
- def test_rstrip_multiple(self):
- editor = MockEditor()
- # Comment above, uncomment 3 below to test with real Editor & Text.
- #from idlelib.editor import EditorWindow as Editor
- #from tkinter import Tk
- #editor = Editor(root=Tk())
- text = editor.text
- do_rstrip = ft.Rstrip(editor).do_rstrip
+ def tearDown(self):
+ self.text.delete('1.0', 'end-1c')
+ def test_rstrip_lines(self):
original = (
"Line with an ending tab \n"
"Line ending in 5 spaces \n"
"Linewithnospaces\n"
" indented line\n"
" indented line with trailing space \n"
- " ")
+ " \n")
stripped = (
"Line with an ending tab\n"
"Line ending in 5 spaces\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)
+ self.text.insert('1.0', original)
+ self.do_rstrip()
+ self.assertEqual(self.text.get('1.0', 'insert'), stripped)
+
+ def test_rstrip_end(self):
+ text = self.text
+ for code in ('', '\n', '\n\n\n'):
+ with self.subTest(code=code):
+ text.insert('1.0', code)
+ self.do_rstrip()
+ self.assertEqual(text.get('1.0','end-1c'), '')
+ for code in ('a\n', 'a\n\n', 'a\n\n\n'):
+ with self.subTest(code=code):
+ text.delete('1.0', 'end-1c')
+ text.insert('1.0', code)
+ self.do_rstrip()
+ self.assertEqual(text.get('1.0','end-1c'), 'a\n')
if __name__ == '__main__':
--- /dev/null
+'Strip Trailing Whitespace' on the Format menu removes extra newlines
+at the end of non-shell files.