summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2024-02-05 16:24:54 (GMT)
committerGitHub <noreply@github.com>2024-02-05 16:24:54 (GMT)
commitb4ba0f73d6eef3da321bb96aafd09dfbc572e95d (patch)
treeb7e4d26504fe8fcb7dcddc469508eab22afda319
parent992446dd5bd3fff92ea0f8064fb19eebfe105cef (diff)
downloadcpython-b4ba0f73d6eef3da321bb96aafd09dfbc572e95d.zip
cpython-b4ba0f73d6eef3da321bb96aafd09dfbc572e95d.tar.gz
cpython-b4ba0f73d6eef3da321bb96aafd09dfbc572e95d.tar.bz2
gh-43457: Tkinter: fix design flaws in wm_attributes() (GH-111404)
* 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. * w.wm_attributes(return_python_dict=True) returns a dict instead of a tuple (it will be the default in future). * Setting wantobjects to 0 no longer affects the result.
-rw-r--r--Doc/whatsnew/3.13.rst9
-rw-r--r--Lib/test/test_tkinter/support.py2
-rw-r--r--Lib/test/test_tkinter/test_misc.py55
-rw-r--r--Lib/tkinter/__init__.py51
-rw-r--r--Lib/tkinter/simpledialog.py2
-rw-r--r--Misc/NEWS.d/next/Library/2023-10-27-19-24-58.gh-issue-43457.84lx9H.rst8
6 files changed, 106 insertions, 21 deletions
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 77f4fce..c25d413 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -421,6 +421,15 @@ 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)``.
+ Add new optional keyword-only parameter *return_python_dict*: calling
+ ``w.wm_attributes(return_python_dict=True)`` returns the attributes as
+ a dict instead of a tuple.
+ (Contributed by Serhiy Storchaka in :gh:`43457`.)
+
* Add support of the "vsapi" element type in
the :meth:`~tkinter.ttk.Style.element_create` method of
:class:`tkinter.ttk.Style`.
diff --git a/Lib/test/test_tkinter/support.py b/Lib/test/test_tkinter/support.py
index a37705f..ebb9e00 100644
--- a/Lib/test/test_tkinter/support.py
+++ b/Lib/test/test_tkinter/support.py
@@ -14,7 +14,7 @@ class AbstractTkTest:
# 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
diff --git a/Lib/test/test_tkinter/test_misc.py b/Lib/test/test_tkinter/test_misc.py
index 7155350..81a20b6 100644
--- a/Lib/test/test_tkinter/test_misc.py
+++ b/Lib/test/test_tkinter/test_misc.py
@@ -437,6 +437,61 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
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(return_python_dict=True)
+ self.assertIsInstance(attributes, dict)
+ attributes2 = w.wm_attributes()
+ self.assertIsInstance(attributes2, tuple)
+ self.assertEqual(attributes2[::2],
+ tuple('-' + k for k in attributes))
+ self.assertEqual(attributes2[1::2], tuple(attributes.values()))
+ # silently deprecated
+ attributes3 = w.wm_attributes(None)
+ if self.wantobjects:
+ self.assertEqual(attributes3, attributes2)
+ else:
+ self.assertIsInstance(attributes3, str)
+
+ 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):
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index a1567d3..2be9da2 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -2108,26 +2108,39 @@ class Wm:
aspect = wm_aspect
- def wm_attributes(self, *args):
- """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.
+ def wm_attributes(self, *args, return_python_dict=False, **kwargs):
+ """Return or sets platform specific attributes.
+
+ When called with a single argument return_python_dict=True,
+ return a dict of the platform specific attributes and their values.
+ When called without arguments or with a single argument
+ return_python_dict=False, return a tuple containing intermixed
+ attribute names with the minus prefix 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:
+ res = self.tk.call('wm', 'attributes', self._w)
+ if return_python_dict:
+ return _splitdict(self.tk, res)
+ else:
+ return self.tk.splitlist(res)
+ 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
diff --git a/Lib/tkinter/simpledialog.py b/Lib/tkinter/simpledialog.py
index 538bbfc..0f0dc66 100644
--- a/Lib/tkinter/simpledialog.py
+++ b/Lib/tkinter/simpledialog.py
@@ -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
diff --git a/Misc/NEWS.d/next/Library/2023-10-27-19-24-58.gh-issue-43457.84lx9H.rst b/Misc/NEWS.d/next/Library/2023-10-27-19-24-58.gh-issue-43457.84lx9H.rst
new file mode 100644
index 0000000..401a532
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-10-27-19-24-58.gh-issue-43457.84lx9H.rst
@@ -0,0 +1,8 @@
+Fix the :mod:`tkinter` widget method :meth:`!wm_attributes`. 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.
+Add new optional keyword argument *return_python_dict*: calling
+``w.wm_attributes(return_python_dict=True)`` returns the attributes as
+a dict instead of a tuple.
+Calling ``w.wm_attributes()`` now returns a tuple instead of string if
+*wantobjects* was set to 0.