Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
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
25 changes: 25 additions & 0 deletions 25 Lib/tkinter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,31 @@ def _get_default_root(what=None):
return _default_root


def _get_temp_root():
global _support_default_root
if not _support_default_root:
raise RuntimeError("No master specified and tkinter is "
"configured to not support default root")
root = _default_root
if root is None:
assert _support_default_root
_support_default_root = False
root = Tk()
_support_default_root = True
assert _default_root is None
root.withdraw()
root._temporary = True
Comment thread
terryjreedy marked this conversation as resolved.
return root


def _destroy_temp_root(master):
if getattr(master, '_temporary', False):
try:
master.destroy()
except TclError:
pass


def _tkerror(err):
"""Internal function."""
pass
Expand Down
27 changes: 11 additions & 16 deletions 27 Lib/tkinter/commondialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

__all__ = ["Dialog"]

from tkinter import Frame
from tkinter import Frame, _get_temp_root, _destroy_temp_root


class Dialog:
Expand All @@ -37,22 +37,17 @@ def show(self, **options):

self._fixoptions()

# we need a dummy widget to properly process the options
# (at least as long as we use Tkinter 1.63)
w = Frame(self.master)

master = self.master
if master is None:
master = _get_temp_root()
try:

s = w.tk.call(self.command, *w._options(self.options))

s = self._fixresult(w, s)

self._test_callback(master) # The function below is replaced for some tests.
s = master.tk.call(self.command, *master._options(self.options))
s = self._fixresult(master, s)
finally:

try:
# get rid of the widget
w.destroy()
except:
pass
_destroy_temp_root(master)

return s

def _test_callback(self, master):
pass
6 changes: 4 additions & 2 deletions 6 Lib/tkinter/simpledialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"""

from tkinter import *
from tkinter import messagebox, _get_default_root
from tkinter import _get_temp_root, _destroy_temp_root
from tkinter import messagebox


class SimpleDialog:
Expand Down Expand Up @@ -100,7 +101,7 @@ def __init__(self, parent, title = None):
'''
master = parent
if master is None:
master = _get_default_root('create dialog window')
master = _get_temp_root()

Toplevel.__init__(self, master)

Expand Down Expand Up @@ -142,6 +143,7 @@ def destroy(self):
'''Destroy the window'''
self.initial_focus = None
Toplevel.destroy(self)
_destroy_temp_root(self.master)

#
# construction hooks
Expand Down
39 changes: 39 additions & 0 deletions 39 Lib/tkinter/test/test_tkinter/test_colorchooser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import unittest
import tkinter
from test.support import requires, run_unittest, swap_attr
from tkinter.test.support import AbstractDefaultRootTest
from tkinter.commondialog import Dialog
from tkinter.colorchooser import askcolor

requires('gui')


class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):

def test_askcolor(self):
def test_callback(dialog, master):
nonlocal ismapped
master.update()
ismapped = master.winfo_ismapped()
raise ZeroDivisionError

with swap_attr(Dialog, '_test_callback', test_callback):
ismapped = None
self.assertRaises(ZeroDivisionError, askcolor)
#askcolor()
self.assertEqual(ismapped, False)

root = tkinter.Tk()
ismapped = None
self.assertRaises(ZeroDivisionError, askcolor)
self.assertEqual(ismapped, True)
root.destroy()

tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, askcolor)


tests_gui = (DefaultRootTest,)

if __name__ == "__main__":
run_unittest(*tests_gui)
38 changes: 38 additions & 0 deletions 38 Lib/tkinter/test/test_tkinter/test_messagebox.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import unittest
import tkinter
from test.support import requires, run_unittest, swap_attr
from tkinter.test.support import AbstractDefaultRootTest
from tkinter.commondialog import Dialog
from tkinter.messagebox import showinfo

requires('gui')


class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):

def test_showinfo(self):
def test_callback(dialog, master):
nonlocal ismapped
master.update()
ismapped = master.winfo_ismapped()
raise ZeroDivisionError

with swap_attr(Dialog, '_test_callback', test_callback):
ismapped = None
self.assertRaises(ZeroDivisionError, showinfo, "Spam", "Egg Information")
self.assertEqual(ismapped, False)

root = tkinter.Tk()
ismapped = None
self.assertRaises(ZeroDivisionError, showinfo, "Spam", "Egg Information")
self.assertEqual(ismapped, True)
root.destroy()

tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, showinfo, "Spam", "Egg Information")


tests_gui = (DefaultRootTest,)

if __name__ == "__main__":
run_unittest(*tests_gui)
24 changes: 18 additions & 6 deletions 24 Lib/tkinter/test/test_tkinter/test_simpledialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,25 @@
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):

def test_askinteger(self):
self.assertRaises(RuntimeError, askinteger, "Go To Line", "Line number")
root = tkinter.Tk()
with swap_attr(Dialog, 'wait_window', lambda self, w: w.destroy()):
@staticmethod
def mock_wait_window(w):
nonlocal ismapped
ismapped = w.master.winfo_ismapped()
w.destroy()

with swap_attr(Dialog, 'wait_window', mock_wait_window):
ismapped = None
askinteger("Go To Line", "Line number")
self.assertEqual(ismapped, False)

root = tkinter.Tk()
ismapped = None
askinteger("Go To Line", "Line number")
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, askinteger, "Go To Line", "Line number")
self.assertEqual(ismapped, True)
root.destroy()

tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, askinteger, "Go To Line", "Line number")


tests_gui = (DefaultRootTest,)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
When simple query dialogs (:mod:`tkinter.simpledialog`), message boxes
(:mod:`tkinter.messagebox`) or color choose dialog
(:mod:`tkinter.colorchooser`) are created without arguments *master* and
*parent*, and the default root window is not yet created, and
:func:`~tkinter.NoDefaultRoot` was not called, a new temporal
hidden root window will be created automatically. It will not be set as the
default root window and will be destroyed right after closing the dialog
Comment thread
terryjreedy marked this conversation as resolved.
window. It will help to use these simple dialog windows in programs which
do not need other GUI.
Morty Proxy This is a proxified and sanitized view of the page, visit original site.