Skip to content

Commit 53ca52d

Browse files
authored
pythongh-152728: IDLE - move 3 toplevel fix_xyz functions to idlelb.util (python#152729)
IDLE - move 3 toplevel fix_xyz functions to idlelb.util Move idlelib functions run.fix_scaling, editor.fixwordbreaks (as fix_word_breaks). All are used in at least 3 modules.
1 parent fdcee4f commit 53ca52d

9 files changed

Lines changed: 58 additions & 49 deletions

File tree

Lib/idlelib/News3.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ Released on 2026-10-01
44
=========================
55

66

7+
gh-152728: Move functions run.fix_scaling, editor.fixwordbreaks (as fix_word_breaks)
8+
and pyshell.fix_x11_paste to module util. Patch by Terry J. Reedy.
9+
710
gh-85320: IDLE now reads and writes its configuration files and the
811
breakpoints file using UTF-8 instead of the locale encoding.
912
Files with non-ASCII characters and non-UTF-8 encoding may need

Lib/idlelib/editor.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,19 +1704,10 @@ def get_accelerator(keydefs, eventname):
17041704
return s
17051705

17061706

1707-
def fixwordbreaks(root):
1708-
# On Windows, tcl/tk breaks 'words' only on spaces, as in Command Prompt.
1709-
# We want Motif style everywhere. See #21474, msg218992 and followup.
1710-
tk = root.tk
1711-
tk.call('tcl_wordBreakAfter', 'a b', 0) # make sure word.tcl is loaded
1712-
tk.call('set', 'tcl_wordchars', r'\w')
1713-
tk.call('set', 'tcl_nonwordchars', r'\W')
1714-
1715-
1716-
def _editor_window(parent): # htest #
1717-
# error if close master window first - timer event, after script
1718-
root = parent
1719-
fixwordbreaks(root)
1707+
def _editor_window(root): # htest #
1708+
# Error if close master window first - timer event, after script
1709+
from util import fix_word_breaks
1710+
fix_word_breaks(root)
17201711
if sys.argv[1:]:
17211712
filename = sys.argv[1]
17221713
else:

Lib/idlelib/filelist.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,12 @@ def canonize(self, filename):
112112

113113

114114
def _test(): # TODO check and convert to htest
115+
# Maybe redundant with test_filelist.FileListTest.test_new_empty.
115116
from tkinter import Tk
116-
from idlelib.editor import fixwordbreaks
117-
from idlelib.run import fix_scaling
117+
from idlelib.util import fix_scaling, fix_word_breaks
118118
root = Tk()
119119
fix_scaling(root)
120-
fixwordbreaks(root)
120+
fix_word_breaks(root)
121121
root.withdraw()
122122
flist = FileList(root)
123123
flist.new()

Lib/idlelib/idle_test/test_editmenu.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import tkinter as tk
88
from tkinter import ttk
99
import unittest
10-
from idlelib import pyshell
10+
from idlelib.util import fix_x11_paste
1111

1212
class PasteTest(unittest.TestCase):
1313
'''Test pasting into widgets that allow pasting.
@@ -18,7 +18,7 @@ class PasteTest(unittest.TestCase):
1818
def setUpClass(cls):
1919
cls.root = root = tk.Tk()
2020
cls.root.withdraw()
21-
pyshell.fix_x11_paste(root)
21+
fix_x11_paste(root)
2222
cls.text = tk.Text(root)
2323
cls.entry = tk.Entry(root)
2424
cls.tentry = ttk.Entry(root)

Lib/idlelib/idle_test/test_sidebar.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111
from idlelib.idle_test.tkinter_testing_utils import run_in_tk_mainloop
1212

1313
from idlelib.delegator import Delegator
14-
from idlelib.editor import fixwordbreaks
1514
from idlelib.percolator import Percolator
1615
import idlelib.pyshell
17-
from idlelib.pyshell import fix_x11_paste, PyShell, PyShellFileList
18-
from idlelib.run import fix_scaling
16+
from idlelib.pyshell import PyShell, PyShellFileList
17+
from idlelib.util import fix_scaling, fix_word_breaks, fix_x11_paste
1918
import idlelib.sidebar
2019
from idlelib.sidebar import get_end_linenumber, get_lineno
2120

@@ -403,7 +402,7 @@ def setUpClass(cls):
403402
root.withdraw()
404403

405404
fix_scaling(root)
406-
fixwordbreaks(root)
405+
fix_word_breaks(root)
407406
fix_x11_paste(root)
408407

409408
cls.flist = flist = PyShellFileList(root)

Lib/idlelib/pyshell.py

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@
3636
from idlelib.delegator import Delegator
3737
from idlelib import debugger
3838
from idlelib import debugger_r
39-
from idlelib.editor import EditorWindow, fixwordbreaks
39+
from idlelib.editor import EditorWindow
4040
from idlelib.filelist import FileList
4141
from idlelib.outwin import OutputWindow
4242
from idlelib import replace
4343
from idlelib import rpc
4444
from idlelib.run import idle_formatwarning, StdInputFile, StdOutputFile
4545
from idlelib.undo import UndoDelegator
46+
from idlelib.util import fix_word_breaks
4647

4748
# Default for testing; defaults to True in main() for running.
4849
use_subprocess = False
@@ -881,9 +882,9 @@ def __init__(self, flist=None):
881882
if ms[2][0] != "shell":
882883
ms.insert(2, ("shell", "She_ll"))
883884
self.interp = ModifiedInterpreter(self)
884-
if flist is None:
885+
if flist is None: # TODO possible? root and flist in main.
885886
root = Tk()
886-
fixwordbreaks(root)
887+
fix_word_breaks(root)
887888
root.withdraw()
888889
flist = PyShellFileList(root)
889890

@@ -1452,17 +1453,6 @@ def on_squeezed_expand(self, index, text, tags):
14521453
self.shell_sidebar.update_sidebar()
14531454

14541455

1455-
def fix_x11_paste(root):
1456-
"Make paste replace selection on x11. See issue #5124."
1457-
if root._windowingsystem == 'x11':
1458-
for cls in 'Text', 'Entry', 'Spinbox':
1459-
root.bind_class(
1460-
cls,
1461-
'<<Paste>>',
1462-
'catch {%W delete sel.first sel.last}\n' +
1463-
root.bind_class(cls, '<<Paste>>'))
1464-
1465-
14661456
usage_msg = """\
14671457
14681458
USAGE: idle [-deins] [-t title] [file]*
@@ -1522,6 +1512,7 @@ def main():
15221512
from platform import system
15231513
from idlelib import testing # bool value
15241514
from idlelib import macosx
1515+
from idlelib.util import fix_scaling, fix_x11_paste
15251516

15261517
global flist, root, use_subprocess
15271518

@@ -1607,7 +1598,6 @@ def main():
16071598
NoDefaultRoot()
16081599
root = Tk(className="Idle")
16091600
root.withdraw()
1610-
from idlelib.run import fix_scaling
16111601
fix_scaling(root)
16121602

16131603
# set application icon
@@ -1629,7 +1619,7 @@ def main():
16291619
root.wm_iconphoto(True, *icons)
16301620

16311621
# start editor and/or shell windows:
1632-
fixwordbreaks(root)
1622+
fix_word_breaks(root)
16331623
fix_x11_paste(root)
16341624
flist = PyShellFileList(root)
16351625
macosx.setupApp(root, flist)

Lib/idlelib/run.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from idlelib import iomenu # encoding
2626
from idlelib import rpc # multiple objects
2727
from idlelib import stackviewer # StackTreeItem
28+
from idlelib import util # fix_scaling
2829
import __main__
2930

3031
import tkinter # Use tcl and, if startup fails, messagebox.
@@ -216,7 +217,7 @@ def show_socket_error(err, address):
216217
import tkinter
217218
from tkinter.messagebox import showerror
218219
root = tkinter.Tk()
219-
fix_scaling(root)
220+
util.fix_scaling(root)
220221
root.withdraw()
221222
showerror(
222223
"Subprocess Connection Error",
@@ -389,16 +390,6 @@ def exit():
389390
sys.exit(0)
390391

391392

392-
def fix_scaling(root):
393-
"""Scale fonts on HiDPI displays."""
394-
import tkinter.font
395-
scaling = float(root.tk.call('tk', 'scaling'))
396-
if scaling > 1.4:
397-
for name in tkinter.font.names(root):
398-
font = tkinter.font.Font(root=root, name=name, exists=True)
399-
size = int(font['size'])
400-
if size < 0:
401-
font['size'] = round(-0.75*size)
402393

403394

404395
def fixdoc(fun, text):

Lib/idlelib/util.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@
1919
py_extensions = ('.py', '.pyw', '.pyi')
2020

2121

22+
# fix_x functions seem only needed once per process.
23+
24+
def fix_scaling(root): # Called in filelist _test, pyshell, and run.
25+
"""Scale fonts on HiDPI displays, once per process."""
26+
import tkinter.font
27+
scaling = float(root.tk.call('tk', 'scaling'))
28+
if scaling > 1.4:
29+
for name in tkinter.font.names(root):
30+
font = tkinter.font.Font(root=root, name=name, exists=True)
31+
size = int(font['size'])
32+
if size < 0:
33+
font['size'] = round(-0.75*size)
34+
35+
2236
# Fix for HiDPI screens on Windows. CALL BEFORE ANY TK OPERATIONS!
2337
# URL for arguments for the ...Awareness call below.
2438
# https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx
@@ -31,6 +45,25 @@ def fix_win_hidpi(): # Called in pyshell and turtledemo.
3145
except (ImportError, AttributeError, OSError):
3246
pass
3347

48+
def fix_word_breaks(root): # Called in editor htest, filelist _test, pyshell.
49+
# On Windows, tcl/tk breaks 'words' only on spaces, as in Command Prompt.
50+
# We want Motif style everywhere. See #21474, msg218992 and followup.
51+
tk = root.tk
52+
tk.call('tcl_wordBreakAfter', 'a b', 0) # make sure word.tcl is loaded
53+
tk.call('set', 'tcl_wordchars', r'\w')
54+
tk.call('set', 'tcl_nonwordchars', r'\W')
55+
56+
57+
def fix_x11_paste(root):
58+
"Make paste replace selection on x11. See issue #5124."
59+
if root._windowingsystem == 'x11':
60+
for cls in 'Text', 'Entry', 'Spinbox':
61+
root.bind_class(
62+
cls,
63+
'<<Paste>>',
64+
'catch {%W delete sel.first sel.last}\n' +
65+
root.bind_class(cls, '<<Paste>>'))
66+
3467

3568
if __name__ == '__main__':
3669
from unittest import main
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Move functions run.fix_scaling, editor.fixwordbreaks (as fix_word_breaks)
2+
and pyshell.fix_x11_paste to idlelib.util.

0 commit comments

Comments
 (0)