[Python-checkins] gh-73588: Fix generation of the default name of tkinter.Checkbutton. (GH-97547)
miss-islington
webhook-mailer at python.org
Tue Sep 27 07:34:30 EDT 2022
https://github.com/python/cpython/commit/04aa15f5e79819ad5d0c135136844efd641935c1
commit: 04aa15f5e79819ad5d0c135136844efd641935c1
branch: 3.11
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: miss-islington <31488909+miss-islington at users.noreply.github.com>
date: 2022年09月27日T04:34:24-07:00
summary:
gh-73588: Fix generation of the default name of tkinter.Checkbutton. (GH-97547)
Previously, checkbuttons in different parent widgets could have the same
short name and share the same state if arguments "name" and "variable" are
not specified. Now they are globally unique.
(cherry picked from commit adbed2d542a815b8175db965742211856b19b52f)
Co-authored-by: Serhiy Storchaka <storchaka at gmail.com>
files:
A Misc/NEWS.d/next/Library/2022-09-25-20-42-33.gh-issue-73588.uVtjEA.rst
M Lib/tkinter/__init__.py
M Lib/tkinter/dialog.py
M Lib/tkinter/test/test_tkinter/test_widgets.py
M Lib/tkinter/test/test_ttk/test_widgets.py
M Lib/tkinter/tix.py
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 296320235afd..356446911e0a 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -2619,7 +2619,7 @@ def __init__(self, master, widgetName, cnf={}, kw={}, extra=()):
if kw:
cnf = _cnfmerge((cnf, kw))
self.widgetName = widgetName
- BaseWidget._setup(self, master, cnf)
+ self._setup(master, cnf)
if self._tclCommands is None:
self._tclCommands = []
classes = [(k, v) for k, v in cnf.items() if isinstance(k, type)]
@@ -3038,6 +3038,8 @@ def type(self, tagOrId):
return self.tk.call(self._w, 'type', tagOrId) or None
+_checkbutton_count = 0
+
class Checkbutton(Widget):
"""Checkbutton widget which is either in on- or off-state."""
@@ -3053,6 +3055,14 @@ def __init__(self, master=None, cnf={}, **kw):
underline, variable, width, wraplength."""
Widget.__init__(self, master, 'checkbutton', cnf, kw)
+ def _setup(self, master, cnf):
+ if not cnf.get('name'):
+ global _checkbutton_count
+ name = self.__class__.__name__.lower()
+ _checkbutton_count += 1
+ cnf['name'] = f'!{name}{_checkbutton_count}'
+ super()._setup(master, cnf)
+
def deselect(self):
"""Put the button in off-state."""
self.tk.call(self._w, 'deselect')
diff --git a/Lib/tkinter/dialog.py b/Lib/tkinter/dialog.py
index 8ae214011727..36ae6c277cb6 100644
--- a/Lib/tkinter/dialog.py
+++ b/Lib/tkinter/dialog.py
@@ -11,7 +11,7 @@ class Dialog(Widget):
def __init__(self, master=None, cnf={}, **kw):
cnf = _cnfmerge((cnf, kw))
self.widgetName = '__dialog__'
- Widget._setup(self, master, cnf)
+ self._setup(master, cnf)
self.num = self.tk.getint(
self.tk.call(
'tk_dialog', self._w,
diff --git a/Lib/tkinter/test/test_tkinter/test_widgets.py b/Lib/tkinter/test/test_tkinter/test_widgets.py
index fe8ecfeb3265..995bed2ecf60 100644
--- a/Lib/tkinter/test/test_tkinter/test_widgets.py
+++ b/Lib/tkinter/test/test_tkinter/test_widgets.py
@@ -212,6 +212,32 @@ def test_configure_onvalue(self):
widget = self.create()
self.checkParams(widget, 'onvalue', 1, 2.3, '', 'any string')
+ def test_unique_variables(self):
+ frames = []
+ buttons = []
+ for i in range(2):
+ f = tkinter.Frame(self.root)
+ f.pack()
+ frames.append(f)
+ for j in 'AB':
+ b = tkinter.Checkbutton(f, text=j)
+ b.pack()
+ buttons.append(b)
+ variables = [str(b['variable']) for b in buttons]
+ self.assertEqual(len(set(variables)), 4, variables)
+
+ def test_same_name(self):
+ f1 = tkinter.Frame(self.root)
+ f2 = tkinter.Frame(self.root)
+ b1 = tkinter.Checkbutton(f1, name='test', text='Test1')
+ b2 = tkinter.Checkbutton(f2, name='test', text='Test2')
+
+ v = tkinter.IntVar(self.root, name='test')
+ b1.select()
+ self.assertEqual(v.get(), 1)
+ b2.deselect()
+ self.assertEqual(v.get(), 0)
+
@add_standard_options(StandardOptionsTests)
class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py
index c14c321ca268..96d2afcf90ea 100644
--- a/Lib/tkinter/test/test_ttk/test_widgets.py
+++ b/Lib/tkinter/test/test_ttk/test_widgets.py
@@ -275,6 +275,21 @@ def cb_test():
self.assertEqual(cbtn['offvalue'],
cbtn.tk.globalgetvar(cbtn['variable']))
+ def test_unique_variables(self):
+ frames = []
+ buttons = []
+ for i in range(2):
+ f = ttk.Frame(self.root)
+ f.pack()
+ frames.append(f)
+ for j in 'AB':
+ b = ttk.Checkbutton(f, text=j)
+ b.pack()
+ buttons.append(b)
+ variables = [str(b['variable']) for b in buttons]
+ print(variables)
+ self.assertEqual(len(set(variables)), 4, variables)
+
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
class EntryTest(AbstractWidgetTest, unittest.TestCase):
diff --git a/Lib/tkinter/tix.py b/Lib/tkinter/tix.py
index 44ecae1a3268..ce218265d4a8 100644
--- a/Lib/tkinter/tix.py
+++ b/Lib/tkinter/tix.py
@@ -310,7 +310,7 @@ def __init__ (self, master=None, widgetName=None,
del cnf[k]
self.widgetName = widgetName
- Widget._setup(self, master, cnf)
+ self._setup(master, cnf)
# If widgetName is None, this is a dummy creation call where the
# corresponding Tk widget has already been created by Tix
diff --git a/Misc/NEWS.d/next/Library/2022-09-25-20-42-33.gh-issue-73588.uVtjEA.rst b/Misc/NEWS.d/next/Library/2022-09-25-20-42-33.gh-issue-73588.uVtjEA.rst
new file mode 100644
index 000000000000..d8a0e690e291
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-09-25-20-42-33.gh-issue-73588.uVtjEA.rst
@@ -0,0 +1,4 @@
+Fix generation of the default name of :class:`tkinter.Checkbutton`.
+Previously, checkbuttons in different parent widgets could have the same
+short name and share the same state if arguments "name" and "variable" are
+not specified. Now they are globally unique.
More information about the Python-checkins
mailing list