diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index a040d791bdeb528..915ce7c6295b08d 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -1118,7 +1118,13 @@ def _close(self): def last_mtime(self): file = self.io.filename - return os.path.getmtime(file) if file else 0 + if not file: + return 0 + try: + return os.path.getmtime(file) + except OSError: + # File gone or inaccessible: keep the last known mtime. + return self.mtime def focus_in_event(self, event): mtime = self.last_mtime() diff --git a/Lib/idlelib/idle_test/test_editor.py b/Lib/idlelib/idle_test/test_editor.py index e28ee549f180aa0..b6110ad06eeef8a 100644 --- a/Lib/idlelib/idle_test/test_editor.py +++ b/Lib/idlelib/idle_test/test_editor.py @@ -1,6 +1,9 @@ "Test editor, coverage 53%." from idlelib import editor +import os +import tempfile +import types import unittest from collections import namedtuple from test.support import requires @@ -237,5 +240,25 @@ def test_rclick(self): pass +class LastMtimeTest(unittest.TestCase): + # Exercise last_mtime as an unbound method on a stub; no GUI needed. + + def test_deleted_file_does_not_raise(self): + with tempfile.TemporaryDirectory() as d: + p = os.path.join(d, 'gone.py') + open(p, 'w').close() + mtime = os.path.getmtime(p) + os.remove(p) + stub = types.SimpleNamespace( + io=types.SimpleNamespace(filename=p), mtime=mtime) + # Must not raise; returns the last known mtime. + self.assertEqual(Editor.last_mtime(stub), mtime) + + def test_no_filename_returns_zero(self): + stub = types.SimpleNamespace( + io=types.SimpleNamespace(filename=None), mtime=123) + self.assertEqual(Editor.last_mtime(stub), 0) + + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Misc/NEWS.d/next/Library/2026-07-10-19-41-00.gh-issue-153480.EdMt1x.rst b/Misc/NEWS.d/next/Library/2026-07-10-19-41-00.gh-issue-153480.EdMt1x.rst new file mode 100644 index 000000000000000..0147c300b772644 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-10-19-41-00.gh-issue-153480.EdMt1x.rst @@ -0,0 +1,2 @@ +IDLE no longer crashes with a traceback when a file open in the editor is +deleted or renamed by another program and the editor window is refocused.