Skip to content

Commit

Permalink
pythongh-43457: Tkinter: fix design flaws in wm_attributes()
Browse files Browse the repository at this point in the history
* w.wm_attributes() without arguments returns a dict instead of a tuple
  or a str.
* When called with a single argument to get a value, it allow to omit
  the minus prefix.
* It can be called with keyword arguments to set attributes.
  • Loading branch information
serhiy-storchaka committed Oct 27, 2023
1 parent 74f0772 commit 6cbe488
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 19 deletions.
12 changes: 12 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ tkinter
:meth:`!tk_busy_current`, and :meth:`!tk_busy_status`.
(Contributed by Miguel, klappnase and Serhiy Storchaka in :gh:`72684`.)

* The :mod:`tkinter` widget method :meth:`!wm_attributes` now accepts
the attribute name without the minus prefix to get window attributes,
e.g. ``w.wm_attributes('alpha')`` and allows to specify attributes and
values to set as keyword arguments, e.g. ``w.wm_attributes(alpha=0.5)``.
(Contributed by Serhiy Storchaka in :gh:`43457`.)

traceback
---------

Expand Down Expand Up @@ -953,6 +959,12 @@ Changes in the Python API
The result is now the same if ``wantobjects`` is set to ``0``.
(Contributed by Serhiy Storchaka in :gh:`97928`.)

* The :mod:`tkinter` widget method :meth:`!wm_attributes` called without
arguments now returns a dict instead of a tuple or a str.
E.g. ``{'alpha': 1.0, 'topmost': 0, 'zoomed': 0, 'fullscreen': 0, 'type': ''}``
instead of ``('-alpha', 1.0, '-topmost', 0, '-zoomed', 0, '-fullscreen', 0, '-type', '')``.
(Contributed by Serhiy Storchaka in :gh:`43457`.)


Build Changes
=============
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_tkinter/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def setUpClass(cls):
# Some window managers can maximize new windows.
cls.root.wm_state('normal')
try:
cls.root.wm_attributes('-zoomed', False)
cls.root.wm_attributes(zoomed=False)
except tkinter.TclError:
pass

Expand Down
51 changes: 51 additions & 0 deletions Lib/test/test_tkinter/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,57 @@ def test_info_patchlevel(self):
self.assertTrue(str(vi).startswith(f'{vi.major}.{vi.minor}'))


class WmTest(AbstractTkTest, unittest.TestCase):

def test_wm_attribute(self):
w = self.root
attributes = w.wm_attributes()
self.assertIsInstance(attributes, dict)
# silently deprecated
attributes2 = w.wm_attributes(None)
self.assertIsInstance(attributes2, tuple if self.wantobjects else str)
if self.wantobjects:
self.assertEqual(attributes2[::2],
tuple('-' + k for k in attributes))
self.assertEqual(attributes2[1::2], tuple(attributes.values()))

for name in attributes:
self.assertEqual(w.wm_attributes(name), attributes[name])
# silently deprecated
for name in attributes:
self.assertEqual(w.wm_attributes('-' + name), attributes[name])

self.assertIn('alpha', attributes)
self.assertIn('fullscreen', attributes)
self.assertIn('topmost', attributes)
if w._windowingsystem == "win32":
self.assertIn('disabled', attributes)
self.assertIn('toolwindow', attributes)
self.assertIn('transparentcolor', attributes)
if w._windowingsystem == "aqua":
self.assertIn('modified', attributes)
self.assertIn('notify', attributes)
self.assertIn('titlepath', attributes)
self.assertIn('transparent', attributes)
if w._windowingsystem == "x11":
self.assertIn('type', attributes)
self.assertIn('zoomed', attributes)

w.wm_attributes(alpha=0.5)
self.assertEqual(w.wm_attributes('alpha'),
0.5 if self.wantobjects else '0.5')
w.wm_attributes(alpha=1.0)
self.assertEqual(w.wm_attributes('alpha'),
1.0 if self.wantobjects else '1.0')
# silently deprecated
w.wm_attributes('-alpha', 0.5)
self.assertEqual(w.wm_attributes('alpha'),
0.5 if self.wantobjects else '0.5')
w.wm_attributes(alpha=1.0)
self.assertEqual(w.wm_attributes('alpha'),
1.0 if self.wantobjects else '1.0')


class BindTest(AbstractTkTest, unittest.TestCase):

def setUp(self):
Expand Down
39 changes: 22 additions & 17 deletions Lib/tkinter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2089,26 +2089,31 @@ def wm_aspect(self,

aspect = wm_aspect

def wm_attributes(self, *args):
def wm_attributes(self, *args, **kwargs):
"""This subcommand returns or sets platform specific attributes
The first form returns a list of the platform specific flags and
their values. The second form returns the value for the specific
option. The third form sets one or more of the values. The values
are as follows:
On Windows, -disabled gets or sets whether the window is in a
disabled state. -toolwindow gets or sets the style of the window
to toolwindow (as defined in the MSDN). -topmost gets or sets
whether this is a topmost window (displays above all other
windows).
On Macintosh, XXXXX
On Unix, there are currently no special attribute values.
When called without arguments, return a dict of the platform
specific attributes and their values. When called with a single
string value, return the value for the specific option. When
called with keyword arguments, set the corresponding attributes.
"""
args = ('wm', 'attributes', self._w) + args
return self.tk.call(args)
if not kwargs:
if not args:
return _splitdict(self.tk,
self.tk.call('wm', 'attributes', self._w))
if len(args) == 1 and args[0] is not None:
option = args[0]
if option[0] == '-':
# TODO: deprecate
option = option[1:]
return self.tk.call('wm', 'attributes', self._w, '-' + option)
# TODO: deprecate
return self.tk.call('wm', 'attributes', self._w, *args)
elif args:
raise TypeError('wm_attribute() options have been specified as '
'positional and keyword arguments')
else:
self.tk.call('wm', 'attributes', self._w, *self._options(kwargs))

attributes = wm_attributes

Expand Down
2 changes: 1 addition & 1 deletion Lib/tkinter/simpledialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ def _setup_dialog(w):
w.tk.call("::tk::unsupported::MacWindowStyle", "style",
w, "moveableModal", "")
elif w._windowingsystem == "x11":
w.wm_attributes("-type", "dialog")
w.wm_attributes(type="dialog")

# --------------------------------------------------------------------
# convenience dialogues
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix the :mod:`tkinter` widget method :meth:`!wm_attributes`. When called
without arguments, it now returns a dict instead of a tuple or a str. It now
accepts the attribute name without the minus prefix to get window attributes
and allows to specify attributes and values to set as keyword arguments.

0 comments on commit 6cbe488

Please sign in to comment.