This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: IDLE: update code, mostly by cleanups of 2.x or 2to3 artifacts
Type: enhancement Stage:
Components: IDLE Versions: Python 3.10, Python 3.9, Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: terry.reedy Nosy List: Anthony Sottile, miss-islington, taleinat, terry.reedy
Priority: normal Keywords: patch

Created on 2021-01-23 21:20 by terry.reedy, last changed 2022-04-11 14:59 by admin.

Pull Requests
URL Status Linked Edit
PR 24315 merged terry.reedy, 2021-01-24 18:38
PR 24316 closed miss-islington, 2021-01-24 19:09
PR 24317 merged miss-islington, 2021-01-24 19:09
PR 24319 merged miss-islington, 2021-01-24 23:13
PR 24326 merged terry.reedy, 2021-01-25 11:08
PR 24327 merged miss-islington, 2021-01-25 11:33
PR 24328 merged miss-islington, 2021-01-25 11:33
Messages (14)
msg385564 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-01-23 21:20
Tal, just so you know in case you see a resulting merge conflict.  I've been waiting for years to do these until most PRs were closed.  Has not happened, and annoyances continue.

Since there is no search option I can find to search for PRs with a merge conflict, I assume that they are not discovered until a PR is accessed.  So when some of these are done, I will search with 'idle in:title', open, scroll down, and fix.

1. 9 leftover 'object's from 2.x "class C(object):" headers.

2. 6 unneeded 'list's added by 2to3 to make 'for item in list(iterable):'.

3. import 3.x-tkinter name as 2.x-tkinter; needs some care but fixes will be easy to verify.

4. builtin names like 'object', 'dict', and 'type' used as parameter names; I am open to opinion of adding '_' versus abbreviating versus alternative.  

5. ??
msg385570 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-01-24 04:23
5. Extraneous () after class name in class header: 'class name():'.  Never done in idlelib itself, 27 in test files, mostly in 1 file.
msg385587 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-01-24 18:29
Delete 2. 'list' is needed if for-suite mutates the dict all 6 either directly or maybe indirectly do so.  Not worth checking unless otherwise editing the function.

6. N unneeded .keys() (out of 13 occurrences) when iterating dict.  Low priority.

First patch does 1. and 5.
msg385588 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-01-24 19:09
New changeset 8dfe15625e6ea4357a13fec7989a0e6ba2bf1359 by Terry Jan Reedy in branch 'master':
 bpo-43013: Update idlelib code to 3.x  (GH-24315)
https://github.com/python/cpython/commit/8dfe15625e6ea4357a13fec7989a0e6ba2bf1359
msg385593 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-01-24 22:16
New changeset 63ebba0d9430a0bc18fd8551ad27b9b25709a4be by Miss Islington (bot) in branch '3.8':
bpo-43013: Update idlelib code to 3.x  (GH-24315) (#24317)
https://github.com/python/cpython/commit/63ebba0d9430a0bc18fd8551ad27b9b25709a4be
msg385595 - (view) Author: miss-islington (miss-islington) Date: 2021-01-24 23:36
New changeset ff06957710aa849f3402b082a7ddd34b0325d6de by Miss Islington (bot) in branch '3.9':
bpo-43013: Update idlelib code to 3.x  (GH-24315)
https://github.com/python/cpython/commit/ff06957710aa849f3402b082a7ddd34b0325d6de
msg385601 - (view) Author: Anthony Sottile (Anthony Sottile) * Date: 2021-01-25 04:31
just noticed this PR -- you might be interested in pyupgrade which automates some of these things -- here's (for example) `git ls-files -- Lib/idlelib | grep '\.py$' | xargs pyupgrade --py36-plus

```diff
diff --git a/Lib/idlelib/calltip_w.py b/Lib/idlelib/calltip_w.py
index 1e0404aa49..278546064a 100644
--- a/Lib/idlelib/calltip_w.py
+++ b/Lib/idlelib/calltip_w.py
@@ -25,7 +25,7 @@ def __init__(self, text_widget):
         text_widget: a Text widget with code for which call-tips are desired
         """
         # Note: The Text widget will be accessible as self.anchor_widget
-        super(CalltipWindow, self).__init__(text_widget)
+        super().__init__(text_widget)
 
         self.label = self.text = None
         self.parenline = self.parencol = self.lastline = None
@@ -54,7 +54,7 @@ def position_window(self):
             return
         self.lastline = curline
         self.anchor_widget.see("insert")
-        super(CalltipWindow, self).position_window()
+        super().position_window()
 
     def showtip(self, text, parenleft, parenright):
         """Show the call-tip, bind events which will close it and reposition it.
@@ -73,7 +73,7 @@ def showtip(self, text, parenleft, parenright):
         self.parenline, self.parencol = map(
             int, self.anchor_widget.index(parenleft).split("."))
 
-        super(CalltipWindow, self).showtip()
+        super().showtip()
 
         self._bind_events()
 
@@ -143,7 +143,7 @@ def hidetip(self):
             # ValueError may be raised by MultiCall
             pass
 
-        super(CalltipWindow, self).hidetip()
+        super().hidetip()
 
     def _bind_events(self):
         """Bind event handlers."""
diff --git a/Lib/idlelib/debugger.py b/Lib/idlelib/debugger.py
index ccd03e46e1..53dba376af 100644
--- a/Lib/idlelib/debugger.py
+++ b/Lib/idlelib/debugger.py
@@ -49,9 +49,9 @@ def __frame2message(self, frame):
         filename = code.co_filename
         lineno = frame.f_lineno
         basename = os.path.basename(filename)
-        message = "%s:%s" % (basename, lineno)
+        message = f"{basename}:{lineno}"
         if code.co_name != "?":
-            message = "%s: %s()" % (message, code.co_name)
+            message = f"{message}: {code.co_name}()"
         return message
 
 
@@ -213,7 +213,7 @@ def interaction(self, message, frame, info=None):
                 m1 = "%s" % str(type)
             if value is not None:
                 try:
-                    m1 = "%s: %s" % (m1, str(value))
+                    m1 = "{}: {}".format(m1, str(value))
                 except:
                     pass
             bg = "yellow"
diff --git a/Lib/idlelib/debugobj.py b/Lib/idlelib/debugobj.py
index 5a4c997884..71d01c7070 100644
--- a/Lib/idlelib/debugobj.py
+++ b/Lib/idlelib/debugobj.py
@@ -87,7 +87,7 @@ def GetSubList(self):
                 continue
             def setfunction(value, key=key, object=self.object):
                 object[key] = value
-            item = make_objecttreeitem("%r:" % (key,), value, setfunction)
+            item = make_objecttreeitem(f"{key!r}:", value, setfunction)
             sublist.append(item)
         return sublist
 
diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py
index a4d0c95362..5faebb5742 100644
--- a/Lib/idlelib/editor.py
+++ b/Lib/idlelib/editor.py
@@ -37,12 +37,12 @@
 def _sphinx_version():
     "Format sys.version_info to produce the Sphinx version string used to install the chm docs"
     major, minor, micro, level, serial = sys.version_info
-    release = '%s%s' % (major, minor)
-    release += '%s' % (micro,)
+    release = f'{major}{minor}'
+    release += f'{micro}'
     if level == 'candidate':
-        release += 'rc%s' % (serial,)
+        release += f'rc{serial}'
     elif level != 'final':
-        release += '%s%s' % (level[0], serial)
+        release += '{}{}'.format(level[0], serial)
     return release
 
 
@@ -939,7 +939,7 @@ def update_recent_files_list(self, new_file=None):
         rf_list = []
         file_path = self.recent_files_path
         if file_path and os.path.exists(file_path):
-            with open(file_path, 'r',
+            with open(file_path,
                       encoding='utf_8', errors='replace') as rf_list_file:
                 rf_list = rf_list_file.readlines()
         if new_file:
@@ -1446,7 +1446,7 @@ def newline_and_indent_event(self, event):
                     else:
                         self.reindent_to(y.compute_backslash_indent())
                 else:
-                    assert 0, "bogus continuation type %r" % (c,)
+                    assert 0, f"bogus continuation type {c!r}"
                 return "break"
 
             # This line starts a brand new statement; indent relative to
diff --git a/Lib/idlelib/filelist.py b/Lib/idlelib/filelist.py
index 0d200854ef..9b863698a0 100644
--- a/Lib/idlelib/filelist.py
+++ b/Lib/idlelib/filelist.py
@@ -22,7 +22,7 @@ def open(self, filename, action=None):
             # This can happen when bad filename is passed on command line:
             tkMessageBox.showerror(
                 "File Error",
-                "%r is a directory." % (filename,),
+                f"{filename!r} is a directory.",
                 master=self.root)
             return None
         key = os.path.normcase(filename)
@@ -90,7 +90,7 @@ def filename_changed_edit(self, edit):
             self.inversedict[conflict] = None
             tkMessageBox.showerror(
                 "Name Conflict",
-                "You now have multiple edit windows open for %r" % (filename,),
+                f"You now have multiple edit windows open for {filename!r}",
                 master=self.root)
         self.dict[newkey] = edit
         self.inversedict[edit] = newkey
diff --git a/Lib/idlelib/idle_test/test_config.py b/Lib/idlelib/idle_test/test_config.py
index 697fda5279..08ed76fe28 100644
--- a/Lib/idlelib/idle_test/test_config.py
+++ b/Lib/idlelib/idle_test/test_config.py
@@ -191,7 +191,7 @@ def setUpClass(cls):
             idle_dir = os.path.abspath(sys.path[0])
         for ctype in conf.config_types:
             config_path = os.path.join(idle_dir, '../config-%s.def' % ctype)
-            with open(config_path, 'r') as f:
+            with open(config_path) as f:
                 cls.config_string[ctype] = f.read()
 
         cls.orig_warn = config._warn
diff --git a/Lib/idlelib/idle_test/test_text.py b/Lib/idlelib/idle_test/test_text.py
index 0f31179e04..43a9ba02c3 100644
--- a/Lib/idlelib/idle_test/test_text.py
+++ b/Lib/idlelib/idle_test/test_text.py
@@ -6,7 +6,7 @@
 from test.support import requires
 from _tkinter import TclError
 
-class TextTest(object):
+class TextTest:
     "Define items common to both sets of tests."
 
     hw = 'hello\nworld'  # Several tests insert this after initialization.
diff --git a/Lib/idlelib/macosx.py b/Lib/idlelib/macosx.py
index eeaab59ae8..fbc6499faa 100644
--- a/Lib/idlelib/macosx.py
+++ b/Lib/idlelib/macosx.py
@@ -81,7 +81,7 @@ def tkVersionWarning(root):
         patchlevel = root.tk.call('info', 'patchlevel')
         if patchlevel not in ('8.5.7', '8.5.9'):
             return False
-        return ("WARNING: The version of Tcl/Tk ({0}) in use may"
+        return ("WARNING: The version of Tcl/Tk ({}) in use may"
                 " be unstable.\n"
                 "Visit http://www.python.org/download/mac/tcltk/"
                 " for current information.".format(patchlevel))
diff --git a/Lib/idlelib/multicall.py b/Lib/idlelib/multicall.py
index dc02001292..0200f445cc 100644
--- a/Lib/idlelib/multicall.py
+++ b/Lib/idlelib/multicall.py
@@ -52,9 +52,9 @@
     _modifier_masks = (MC_CONTROL, MC_ALT, MC_SHIFT, MC_META)
 
 # a dictionary to map a modifier name into its number
-_modifier_names = dict([(name, number)
+_modifier_names = {name: number
                          for number in range(len(_modifiers))
-                         for name in _modifiers[number]])
+                         for name in _modifiers[number]}
 
 # In 3.4, if no shell window is ever open, the underlying Tk widget is
 # destroyed before .__del__ methods here are called.  The following
@@ -134,7 +134,7 @@ def nbits(n):
         return nb
     statelist = []
     for state in states:
-        substates = list(set(state & x for x in states))
+        substates = list({state & x for x in states})
         substates.sort(key=nbits, reverse=True)
         statelist.append(substates)
     return statelist
@@ -258,9 +258,9 @@ def __del__(self):
 _binder_classes = (_ComplexBinder,) * 4 + (_SimpleBinder,) * (len(_types)-4)
 
 # A dictionary to map a type name into its number
-_type_names = dict([(name, number)
+_type_names = {name: number
                      for number in range(len(_types))
-                     for name in _types[number]])
+                     for name in _types[number]}
 
 _keysym_re = re.compile(r"^\w+$")
 _button_re = re.compile(r"^[1-5]$")
diff --git a/Lib/idlelib/outwin.py b/Lib/idlelib/outwin.py
index 5ab08bbaf4..ac67c904ab 100644
--- a/Lib/idlelib/outwin.py
+++ b/Lib/idlelib/outwin.py
@@ -42,7 +42,7 @@ def file_line_helper(line):
         if match:
             filename, lineno = match.group(1, 2)
             try:
-                f = open(filename, "r")
+                f = open(filename)
                 f.close()
                 break
             except OSError:
diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py
index abe8a85952..6cae951698 100755
--- a/Lib/idlelib/pyshell.py
+++ b/Lib/idlelib/pyshell.py
@@ -245,7 +245,7 @@ def store_file_breaks(self):
         breaks = self.breakpoints
         filename = self.io.filename
         try:
-            with open(self.breakpointPath, "r") as fp:
+            with open(self.breakpointPath) as fp:
                 lines = fp.readlines()
         except OSError:
             lines = []
@@ -275,7 +275,7 @@ def restore_file_breaks(self):
         if filename is None:
             return
         if os.path.isfile(self.breakpointPath):
-            with open(self.breakpointPath, "r") as fp:
+            with open(self.breakpointPath) as fp:
                 lines = fp.readlines()
             for line in lines:
                 if line.startswith(filename + '='):
@@ -431,7 +431,7 @@ def build_subprocess_arglist(self):
         # run from the IDLE source directory.
         del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
                                        default=False, type='bool')
-        command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
+        command = f"__import__('idlelib.run').run.main({del_exitf!r})"
         return [sys.executable] + w + ["-c", command, str(self.port)]
 
     def start_subprocess(self):
@@ -564,9 +564,9 @@ def transfer_path(self, with_cwd=False):
 
         self.runcommand("""if 1:
         import sys as _sys
-        _sys.path = %r
+        _sys.path = {!r}
         del _sys
-        \n""" % (path,))
+        \n""".format(path))
 
     active_seq = None
 
@@ -693,14 +693,14 @@ def stuffsource(self, source):
     def prepend_syspath(self, filename):
         "Prepend sys.path with file's directory if not already included"
         self.runcommand("""if 1:
-            _filename = %r
+            _filename = {!r}
             import sys as _sys
             from os.path import dirname as _dirname
             _dir = _dirname(_filename)
             if not _dir in _sys.path:
                 _sys.path.insert(0, _dir)
             del _filename, _sys, _dirname, _dir
-            \n""" % (filename,))
+            \n""".format(filename))
 
     def showsyntaxerror(self, filename=None):
         """Override Interactive Interpreter method: Use Colorizing
@@ -1407,7 +1407,7 @@ def main():
     try:
         opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
     except getopt.error as msg:
-        print("Error: %s\n%s" % (msg, usage_msg), file=sys.stderr)
+        print(f"Error: {msg}\n{usage_msg}", file=sys.stderr)
         sys.exit(2)
     for o, a in opts:
         if o == '-c':
@@ -1539,9 +1539,9 @@ def main():
     if cmd or script:
         shell.interp.runcommand("""if 1:
             import sys as _sys
-            _sys.argv = %r
+            _sys.argv = {!r}
             del _sys
-            \n""" % (sys.argv,))
+            \n""".format(sys.argv))
         if cmd:
             shell.interp.execsource(cmd)
         elif script:
diff --git a/Lib/idlelib/redirector.py b/Lib/idlelib/redirector.py
index 9ab34c5acf..9891d256f7 100644
--- a/Lib/idlelib/redirector.py
+++ b/Lib/idlelib/redirector.py
@@ -47,7 +47,7 @@ def __init__(self, widget):
         tk.createcommand(w, self.dispatch)
 
     def __repr__(self):
-        return "%s(%s<%s>)" % (self.__class__.__name__,
+        return "{}({}<{}>)".format(self.__class__.__name__,
                                self.widget.__class__.__name__,
                                self.widget._w)
 
@@ -143,7 +143,7 @@ def __init__(self, redir, operation):
         self.orig_and_operation = (redir.orig, operation)
 
     def __repr__(self):
-        return "%s(%r, %r)" % (self.__class__.__name__,
+        return "{}({!r}, {!r})".format(self.__class__.__name__,
                                self.redir, self.operation)
 
     def __call__(self, *args):
diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py
index 8efcf048fa..062e2502de 100644
--- a/Lib/idlelib/rpc.py
+++ b/Lib/idlelib/rpc.py
@@ -174,7 +174,7 @@ def localcall(self, seq, request):
         except TypeError:
             return ("ERROR", "Bad request format")
         if oid not in self.objtable:
-            return ("ERROR", "Unknown object id: %r" % (oid,))
+            return ("ERROR", f"Unknown object id: {oid!r}")
         obj = self.objtable[oid]
         if methodname == "__methods__":
             methods = {}
@@ -185,7 +185,7 @@ def localcall(self, seq, request):
             _getattributes(obj, attributes)
             return ("OK", attributes)
         if not hasattr(obj, methodname):
-            return ("ERROR", "Unsupported method name: %r" % (methodname,))
+            return ("ERROR", f"Unsupported method name: {methodname!r}")
         method = getattr(obj, methodname)
         try:
             if how == 'CALL':
diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py
index ec575c3d48..099240d56b 100644
--- a/Lib/idlelib/run.py
+++ b/Lib/idlelib/run.py
@@ -43,13 +43,13 @@ def idle_formatwarning(message, category, filename, lineno, line=None):
     """Format warnings the IDLE way."""
 
     s = "\nWarning (from warnings module):\n"
-    s += '  File \"%s\", line %s\n' % (filename, lineno)
+    s += f'  File \"{filename}\", line {lineno}\n'
     if line is None:
         line = linecache.getline(filename, lineno)
     line = line.strip()
     if line:
         s += "    %s\n" % line
-    s += "%s: %s\n" % (category.__name__, message)
+    s += f"{category.__name__}: {message}\n"
     return s
 
 def idle_showwarning_subproc(
diff --git a/Lib/idlelib/textview.py b/Lib/idlelib/textview.py
index a66c1a4309..23f0f4cb50 100644
--- a/Lib/idlelib/textview.py
+++ b/Lib/idlelib/textview.py
@@ -169,7 +169,7 @@ def view_file(parent, title, filename, encoding, modal=True, wrap='word',
     with contents of the file.
     """
     try:
-        with open(filename, 'r', encoding=encoding) as file:
+        with open(filename, encoding=encoding) as file:
             contents = file.read()
     except OSError:
         showerror(title='File Load Error',
diff --git a/Lib/idlelib/tooltip.py b/Lib/idlelib/tooltip.py
index d714318dae..3983690dd4 100644
--- a/Lib/idlelib/tooltip.py
+++ b/Lib/idlelib/tooltip.py
@@ -92,7 +92,7 @@ def __init__(self, anchor_widget, hover_delay=1000):
         e.g. after hovering over the anchor widget with the mouse for enough
         time.
         """
-        super(OnHoverTooltipBase, self).__init__(anchor_widget)
+        super().__init__(anchor_widget)
         self.hover_delay = hover_delay
 
         self._after_id = None
@@ -107,7 +107,7 @@ def __del__(self):
             self.anchor_widget.unbind("<Button>", self._id3) # pragma: no cover
         except TclError:
             pass
-        super(OnHoverTooltipBase, self).__del__()
+        super().__del__()
 
     def _show_event(self, event=None):
         """event handler to display the tooltip"""
@@ -139,7 +139,7 @@ def hidetip(self):
             self.unschedule()
         except TclError:  # pragma: no cover
             pass
-        super(OnHoverTooltipBase, self).hidetip()
+        super().hidetip()
 
 
 class Hovertip(OnHoverTooltipBase):
@@ -154,7 +154,7 @@ def __init__(self, anchor_widget, text, hover_delay=1000):
         e.g. after hovering over the anchor widget with the mouse for enough
         time.
         """
-        super(Hovertip, self).__init__(anchor_widget, hover_delay=hover_delay)
+        super().__init__(anchor_widget, hover_delay=hover_delay)
         self.text = text
 
     def showcontents(self):
diff --git a/Lib/idlelib/tree.py b/Lib/idlelib/tree.py
index 5947268f5c..5f30f0f609 100644
--- a/Lib/idlelib/tree.py
+++ b/Lib/idlelib/tree.py
@@ -32,7 +32,7 @@
 if os.path.isdir(_icondir):
     ICONDIR = _icondir
 elif not os.path.isdir(ICONDIR):
-    raise RuntimeError("can't find icon directory (%r)" % (ICONDIR,))
+    raise RuntimeError(f"can't find icon directory ({ICONDIR!r})")
 
 def listicons(icondir=ICONDIR):
     """Utility to display the available icons."""
diff --git a/Lib/idlelib/undo.py b/Lib/idlelib/undo.py
index 85ecffecb4..5f10c0f05c 100644
--- a/Lib/idlelib/undo.py
+++ b/Lib/idlelib/undo.py
@@ -309,7 +309,7 @@ def __repr__(self):
         s = self.__class__.__name__
         strs = []
         for cmd in self.cmds:
-            strs.append("    %r" % (cmd,))
+            strs.append(f"    {cmd!r}")
         return s + "(\n" + ",\n".join(strs) + "\n)"
 
     def __len__(self):
```
msg385604 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-01-25 07:03
Interesting.  I would prefer to make fewer changes per pre-PR branch commit, but I see from the doc that I could split changes into at least 4 batches from the existing options.  Has this been run/tested on projects better tested than IDLE?  Anyway

7. Run pyupgrade.  On Windows, use pyupgrade-directories or try git bash to run on idlelib and recurse.
msg385618 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-01-25 11:33
New changeset 879986d8a932c4524cb6ff822afc9537de16e28d by Terry Jan Reedy in branch 'master':
bpo-43013: Fix old tkinter module names in idlelib (GH-24326)
https://github.com/python/cpython/commit/879986d8a932c4524cb6ff822afc9537de16e28d
msg385619 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-01-25 11:39
PR for 3. For 2.x, tkinter comprised several modules that became tkinter submodules. For 3.0, 'import tkOld' was replaced by 'import tkinter.new as tkOld', where 'new' is lowercase version of 'Old'.  Fix remaining instances of tkColorChooser, tkFileDialog, tkSimpleDialog, and tkMessageBox by replacing 'tkOld' with 'new' and import with 'from tkinter import new'.  Replace 'tkFont' with 'tkfont' instead of 'font' since 'font' is already used and leave import in 'as' form.  There are no remaining instances of SimpleDialog or tkCommonDialog.
msg385620 - (view) Author: miss-islington (miss-islington) Date: 2021-01-25 11:51
New changeset 7370be30017f81d2f41f1b4b2abf31dd9a3f8fb1 by Miss Islington (bot) in branch '3.8':
bpo-43013: Fix old tkinter module names in idlelib (GH-24326)
https://github.com/python/cpython/commit/7370be30017f81d2f41f1b4b2abf31dd9a3f8fb1
msg385627 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-01-25 13:25
New changeset 26af2fae189629d22a87aaf01b92d6f4de92b958 by Miss Islington (bot) in branch '3.9':
bpo-43013: Fix old tkinter module names in idlelib (GH-24326)
https://github.com/python/cpython/commit/26af2fae189629d22a87aaf01b92d6f4de92b958
msg385629 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-01-25 13:56
There are about 40 open PRs with 'idle' or 'idlelib' in title.  I only found 2 or 3 with merge conflicts related to this issue -- and they are easy to fix.  There are more conflicts from other patches (some fixed).  These are usually more difficult to fix as when a PR adds code where another patch later adds code and both additions need to be kept, in the proper order.

TODO: 4 built-in name parameters, 6 .keys(), 7 pyupgrade.  The latter found fixups in about 15 idlelib files and a few test files.  I may do these for individual files that are well tested or are being worked on.
---

Anthony: removing 'set' from 'list(set(interable))' is wrong if 'set' were added to remove duplicates.
msg385639 - (view) Author: Anthony Sottile (Anthony Sottile) * Date: 2021-01-25 16:29
> Anthony: removing 'set' from 'list(set(interable))' is wrong if 'set' were added to remove duplicates.

It's not removed, it's changed to a set comprehension (which was added in 2.7 and 3.0)

pyupgrade is very battle tested, having been run on pip, pytest, and many open source projects
History
Date User Action Args
2022-04-11 14:59:40adminsetgithub: 87179
2021-01-25 16:29:29Anthony Sottilesetmessages: + msg385639
2021-01-25 13:56:00terry.reedysetmessages: + msg385629
2021-01-25 13:25:44terry.reedysetmessages: + msg385627
2021-01-25 11:51:55miss-islingtonsetmessages: + msg385620
2021-01-25 11:39:06terry.reedysetmessages: + msg385619
stage: patch review ->
2021-01-25 11:33:54terry.reedysetmessages: + msg385618
2021-01-25 11:33:39miss-islingtonsetpull_requests: + pull_request23147
2021-01-25 11:33:30miss-islingtonsetpull_requests: + pull_request23146
2021-01-25 11:08:45terry.reedysetstage: patch review
pull_requests: + pull_request23145
2021-01-25 07:03:43terry.reedysetmessages: + msg385604
stage: patch review -> (no value)
2021-01-25 04:31:03Anthony Sottilesetnosy: + Anthony Sottile
messages: + msg385601
2021-01-24 23:36:36miss-islingtonsetmessages: + msg385595
2021-01-24 23:13:30miss-islingtonsetpull_requests: + pull_request23138
2021-01-24 22:16:32terry.reedysetmessages: + msg385593
2021-01-24 19:09:24miss-islingtonsetpull_requests: + pull_request23136
2021-01-24 19:09:18miss-islingtonsetnosy: + miss-islington
pull_requests: + pull_request23135
2021-01-24 19:09:13terry.reedysetmessages: + msg385588
2021-01-24 18:38:58terry.reedysetkeywords: + patch
stage: patch review
pull_requests: + pull_request23134
2021-01-24 18:29:17terry.reedysetmessages: + msg385587
2021-01-24 04:23:13terry.reedysetmessages: + msg385570
2021-01-23 21:20:31terry.reedycreate