]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-43457: Tkinter: fix design flaws in wm_attributes() (GH-111404)
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 5 Feb 2024 16:24:54 +0000 (18:24 +0200)
committerGitHub <noreply@github.com>
Mon, 5 Feb 2024 16:24:54 +0000 (18:24 +0200)
* 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.

Doc/whatsnew/3.13.rst
Lib/test/test_tkinter/support.py
Lib/test/test_tkinter/test_misc.py
Lib/tkinter/__init__.py
Lib/tkinter/simpledialog.py
Misc/NEWS.d/next/Library/2023-10-27-19-24-58.gh-issue-43457.84lx9H.rst [new file with mode: 0644]

index 77f4fce6c321fee134fb9187fa47e57ed6469ff7..c25d41351c2f3cd96679d56ea9de134b901db108 100644 (file)
@@ -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`.
index a37705f0ae6febbf542b41c47bb4facd94cd92a5..ebb9e00ff91bf0ee97a8af9b1da175b3993267d2 100644 (file)
@@ -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
 
index 71553503005c48b19fbdaf712f4af3d76f2942e0..81a20b698a72eb4db00d31c4d09ec5245613dcc9 100644 (file)
@@ -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):
index a1567d332ae6efc0ed3c41ff09604ef572a5399e..2be9da2cfb92993da17ec30ee65ec3a1e0d02c10 100644 (file)
@@ -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
 
index 538bbfc318d704419884abdfe251872cf075ad33..0f0dc66460f7987c89e0a55e05e27da9fbe0b70b 100644 (file)
@@ -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 (file)
index 0000000..401a532
--- /dev/null
@@ -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.