Skip to content

Commit 76b6451

Browse files
Flavian Hautboisterryjreedy
authored andcommitted
bpo-29446: tkinter 'import *' only imports what it should (GH-14864)
Add __all__ to tkinter.__init__ and submodules. Replace 'import *' with explicit imports in some submodules.
1 parent c4cda43 commit 76b6451

File tree

12 files changed

+52
-15
lines changed

12 files changed

+52
-15
lines changed

Lib/tkinter/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@
3232

3333
import enum
3434
import sys
35+
import types
3536

3637
import _tkinter # If this fails your Python may not be configured for Tk
3738
TclError = _tkinter.TclError
3839
from tkinter.constants import *
3940
import re
4041

41-
4242
wantobjects = 1
4343

4444
TkVersion = float(_tkinter.TK_VERSION)
@@ -4569,5 +4569,9 @@ def _test():
45694569
root.mainloop()
45704570

45714571

4572+
__all__ = [name for name, obj in globals().items()
4573+
if not name.startswith('_') and not isinstance(obj, types.ModuleType)
4574+
and name not in {'wantobjects'}]
4575+
45724576
if __name__ == '__main__':
45734577
_test()

Lib/tkinter/colorchooser.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
from tkinter.commondialog import Dialog
2323

24+
__all__ = ["Chooser", "askcolor"]
25+
2426

2527
#
2628
# color chooser class

Lib/tkinter/commondialog.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@
88
# written by Fredrik Lundh, May 1997
99
#
1010

11-
from tkinter import *
11+
__all__ = ["Dialog"]
12+
13+
from tkinter import Frame
1214

1315

1416
class Dialog:
1517

16-
command = None
18+
command = None
1719

1820
def __init__(self, master=None, **options):
19-
self.master = master
21+
self.master = master
2022
self.options = options
2123
if not master and options.get('parent'):
2224
self.master = options['parent']

Lib/tkinter/dialog.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# dialog.py -- Tkinter interface to the tk_dialog script.
22

3-
from tkinter import *
4-
from tkinter import _cnfmerge
3+
from tkinter import _cnfmerge, Widget, TclError, Button, Pack
4+
5+
__all__ = ["Dialog"]
56

67
DIALOG_ICON = 'questhead'
78

Lib/tkinter/dnd.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,10 @@
9999
100100
"""
101101

102-
103102
import tkinter
104103

104+
__all__ = ["dnd_start", "DndHandler"]
105+
105106

106107
# The factory function
107108

Lib/tkinter/filedialog.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,20 @@
1111
directory dialogue available in Tk 8.3 and newer.
1212
These interfaces were written by Fredrik Lundh, May 1997.
1313
"""
14+
__all__ = ["FileDialog", "LoadFileDialog", "SaveFileDialog",
15+
"Open", "SaveAs", "Directory",
16+
"askopenfilename", "asksaveasfilename", "askopenfilenames",
17+
"askopenfile", "askopenfiles", "asksaveasfile", "askdirectory"]
1418

15-
from tkinter import *
19+
import fnmatch
20+
import os
21+
from tkinter import (
22+
Frame, LEFT, YES, BOTTOM, Entry, TOP, Button, Tk, X,
23+
Toplevel, RIGHT, Y, END, Listbox, BOTH, Scrollbar,
24+
)
1625
from tkinter.dialog import Dialog
1726
from tkinter import commondialog
1827

19-
import os
20-
import fnmatch
21-
2228

2329
dialogstates = {}
2430

Lib/tkinter/font.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
# written by Fredrik Lundh, February 1998
44
#
55

6-
__version__ = "0.9"
7-
86
import itertools
97
import tkinter
108

9+
__version__ = "0.9"
10+
__all__ = ["NORMAL", "ROMAN", "BOLD", "ITALIC",
11+
"nametofont", "Font", "families", "names"]
1112

1213
# weight/slant
1314
NORMAL = "normal"

Lib/tkinter/messagebox.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424

2525
from tkinter.commondialog import Dialog
2626

27+
__all__ = ["showinfo", "showwarning", "showerror",
28+
"askquestion", "askokcancel", "askyesno",
29+
"askyesnocancel", "askretrycancel"]
30+
2731
#
2832
# constants
2933

Lib/tkinter/scrolledtext.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
Place methods are redirected to the Frame widget however.
1212
"""
1313

14-
__all__ = ['ScrolledText']
15-
1614
from tkinter import Frame, Text, Scrollbar, Pack, Grid, Place
1715
from tkinter.constants import RIGHT, LEFT, Y, BOTH
1816

17+
__all__ = ['ScrolledText']
18+
1919

2020
class ScrolledText(Text):
2121
def __init__(self, master=None, **kw):

Lib/tkinter/test/test_tkinter/test_misc.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@
77

88
class MiscTest(AbstractTkTest, unittest.TestCase):
99

10+
def test_all(self):
11+
self.assertIn("Widget", tkinter.__all__)
12+
# Check that variables from tkinter.constants are also in tkinter.__all__
13+
self.assertIn("CASCADE", tkinter.__all__)
14+
self.assertIsNotNone(tkinter.CASCADE)
15+
# Check that sys, re, and constants are not in tkinter.__all__
16+
self.assertNotIn("re", tkinter.__all__)
17+
self.assertNotIn("sys", tkinter.__all__)
18+
self.assertNotIn("constants", tkinter.__all__)
19+
# Check that an underscored functions is not in tkinter.__all__
20+
self.assertNotIn("_tkerror", tkinter.__all__)
21+
# Check that wantobjects is not in tkinter.__all__
22+
self.assertNotIn("wantobjects", tkinter.__all__)
23+
1024
def test_repr(self):
1125
t = tkinter.Toplevel(self.root, name='top')
1226
f = tkinter.Frame(t, name='child')

0 commit comments

Comments
 (0)