8000 gh-43457: Tkinter: fix design flaws in wm_attributes() by serhiy-storchaka · Pull Request #111404 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-43457: Tkinter: fix design flaws in wm_attributes() #111404

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
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
55 changes: 55 additions & 0 deletions Lib/test/test_tkinter/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,61 @@ 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(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):
Expand Down
51 changes: 32 additions & 19 deletions Lib/tkinter/__init__.py
10000
Original file line number Diff line number Diff line change
Expand Up @@ -2108,26 +2108,39 @@ def wm_aspect(self,

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

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,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.
0