Compare commits

...

3 Commits

Author SHA1 Message Date
Serhiy Storchaka 3d569fd6dc
bpo-42630: Improve error reporting in Tkinter for absent default root (GH-23781)
* Tkinter functions and constructors which need a default root window
  raise now RuntimeError with descriptive message instead of obscure
  AttributeError or NameError if it is not created yet or cannot
  be created automatically.

* Add tests for all functions which use default root window.

* Fix import in the pynche script.
2020-12-19 12:17:08 +02:00
masklinn 1e27b57dbc
bpo-42470: Do not warn on sequences which are also sets in random.sample() (GH-23665) 2020-12-18 20:33:36 -08:00
Casper Smet e009612476
Fixed typo in itertools documentation (GH-23816) 2020-12-18 20:28:21 -08:00
23 changed files with 341 additions and 94 deletions

View File

@ -1061,8 +1061,10 @@ class PyShell(OutputWindow):
(sys.version, sys.platform, self.COPYRIGHT, nosub))
self.text.focus_force()
self.showprompt()
# User code should use separate default Tk root window
import tkinter
tkinter._default_root = None # 03Jan04 KBK What's this?
tkinter._support_default_root = True
tkinter._default_root = None
return True
def stop_readline(self):

View File

@ -424,13 +424,14 @@ class Random(_random.Random):
# too many calls to _randbelow(), making them slower and
# causing them to eat more entropy than necessary.
if isinstance(population, _Set):
_warn('Sampling from a set deprecated\n'
'since Python 3.9 and will be removed in a subsequent version.',
DeprecationWarning, 2)
population = tuple(population)
if not isinstance(population, _Sequence):
raise TypeError("Population must be a sequence. For dicts or sets, use sorted(d).")
if isinstance(population, _Set):
_warn('Sampling from a set deprecated\n'
'since Python 3.9 and will be removed in a subsequent version.',
DeprecationWarning, 2)
population = tuple(population)
else:
raise TypeError("Population must be a sequence. For dicts or sets, use sorted(d).")
n = len(population)
if counts is not None:
cum_counts = list(_accumulate(counts))

View File

@ -20,5 +20,5 @@ from idlelib.idle_test import load_tests
if __name__ == '__main__':
tk.NoDefaultRoot()
unittest.main(exit=False)
tk._support_default_root = 1
tk._support_default_root = True
tk._default_root = None

View File

@ -11,7 +11,7 @@ from functools import partial
from math import log, exp, pi, fsum, sin, factorial
from test import support
from fractions import Fraction
from collections import Counter
from collections import abc, Counter
class TestBasicOps:
# Superclass with tests common to all generators.
@ -163,6 +163,22 @@ class TestBasicOps:
population = {10, 20, 30, 40, 50, 60, 70}
self.gen.sample(population, k=5)
def test_sample_on_seqsets(self):
class SeqSet(abc.Sequence, abc.Set):
def __init__(self, items):
self._items = items
def __len__(self):
return len(self._items)
def __getitem__(self, index):
return self._items[index]
population = SeqSet([2, 4, 1, 3])
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
self.gen.sample(population, k=2)
def test_sample_with_counts(self):
sample = self.gen.sample

View File

@ -270,7 +270,7 @@ class Event:
)
_support_default_root = 1
_support_default_root = True
_default_root = None
@ -280,13 +280,26 @@ def NoDefaultRoot():
Call this function to inhibit that the first instance of
Tk is used for windows without an explicit parent window.
"""
global _support_default_root
_support_default_root = 0
global _default_root
global _support_default_root, _default_root
_support_default_root = False
# Delete, so any use of _default_root will immediately raise an exception.
# Rebind before deletion, so repeated calls will not fail.
_default_root = None
del _default_root
def _get_default_root(what=None):
if not _support_default_root:
raise RuntimeError("No master specified and tkinter is "
"configured to not support default root")
if not _default_root:
if what:
raise RuntimeError(f"Too early to {what}: no default root window")
root = Tk()
assert _default_root is root
return _default_root
def _tkerror(err):
"""Internal function."""
pass
@ -330,7 +343,7 @@ class Variable:
raise TypeError("name must be a string")
global _varnum
if not master:
master = _default_root
master = _get_default_root('create variable')
self._root = master._root()
self._tk = master.tk
if name:
@ -591,7 +604,7 @@ class BooleanVar(Variable):
def mainloop(n=0):
"""Run the main loop of Tcl."""
_default_root.tk.mainloop(n)
_get_default_root('run the main loop').tk.mainloop(n)
getint = int
@ -600,9 +613,9 @@ getdouble = float
def getboolean(s):
"""Convert true and false to integer values 1 and 0."""
"""Convert Tcl object to True or False."""
try:
return _default_root.tk.getboolean(s)
return _get_default_root('use getboolean()').tk.getboolean(s)
except TclError:
raise ValueError("invalid literal for getboolean()")
@ -2248,7 +2261,7 @@ class Tk(Misc, Wm):
is the name of the widget class."""
self.master = None
self.children = {}
self._tkloaded = 0
self._tkloaded = False
# to avoid recursions in the getattr code in case of failure, we
# ensure that self.tk is always _something_.
self.tk = None
@ -2272,7 +2285,7 @@ class Tk(Misc, Wm):
self._loadtk()
def _loadtk(self):
self._tkloaded = 1
self._tkloaded = True
global _default_root
# Version sanity checks
tk_version = self.tk.getvar('tk_version')
@ -2521,12 +2534,8 @@ class BaseWidget(Misc):
def _setup(self, master, cnf):
"""Internal function. Sets up information about children."""
if _support_default_root:
global _default_root
if not master:
if not _default_root:
_default_root = Tk()
master = _default_root
if not master:
master = _get_default_root()
self.master = master
self.tk = master.tk
name = None
@ -3990,9 +3999,7 @@ class Image:
def __init__(self, imgtype, name=None, cnf={}, master=None, **kw):
self.name = None
if not master:
master = _default_root
if not master:
raise RuntimeError('Too early to create image')
master = _get_default_root('create image')
self.tk = getattr(master, 'tk', master)
if not name:
Image._last_id += 1
@ -4146,11 +4153,13 @@ class BitmapImage(Image):
def image_names():
return _default_root.tk.splitlist(_default_root.tk.call('image', 'names'))
tk = _get_default_root('use image_names()').tk
return tk.splitlist(tk.call('image', 'names'))
def image_types():
return _default_root.tk.splitlist(_default_root.tk.call('image', 'types'))
tk = _get_default_root('use image_types()').tk
return tk.splitlist(tk.call('image', 'types'))
class Spinbox(Widget, XView):

View File

@ -18,10 +18,10 @@ class Dialog:
command = None
def __init__(self, master=None, **options):
if not master:
master = options.get('parent')
self.master = master
self.options = options
if not master and options.get('parent'):
self.master = options['parent']
def _fixoptions(self):
pass # hook

View File

@ -69,7 +69,7 @@ class Font:
def __init__(self, root=None, font=None, name=None, exists=False,
**options):
if not root:
root = tkinter._default_root
root = tkinter._get_default_root('use font')
tk = getattr(root, 'tk', root)
if font:
# get actual settings corresponding to the given font
@ -184,7 +184,7 @@ class Font:
def families(root=None, displayof=None):
"Get font families (as a tuple)"
if not root:
root = tkinter._default_root
root = tkinter._get_default_root('use font.families()')
args = ()
if displayof:
args = ('-displayof', displayof)
@ -194,7 +194,7 @@ def families(root=None, displayof=None):
def names(root=None):
"Get names of defined fonts (as a tuple)"
if not root:
root = tkinter._default_root
root = tkinter._get_default_root('use font.names()')
return root.tk.splitlist(root.tk.call("font", "names"))

View File

@ -24,9 +24,7 @@ askstring -- get a string from the user
"""
from tkinter import *
from tkinter import messagebox
import tkinter # used at _QueryDialog for tkinter._default_root
from tkinter import messagebox, _get_default_root
class SimpleDialog:
@ -128,13 +126,17 @@ class Dialog(Toplevel):
title -- the dialog title
'''
Toplevel.__init__(self, parent)
master = parent
if not master:
master = _get_default_root('create dialog window')
Toplevel.__init__(self, master)
self.withdraw() # remain invisible for now
# If the master is not viewable, don't
# If the parent is not viewable, don't
# make the child transient, or else it
# would be opened withdrawn
if parent.winfo_viewable():
if parent is not None and parent.winfo_viewable():
self.transient(parent)
if title:
@ -155,7 +157,7 @@ class Dialog(Toplevel):
self.protocol("WM_DELETE_WINDOW", self.cancel)
if self.parent is not None:
if parent is not None:
self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
parent.winfo_rooty()+50))
@ -259,9 +261,6 @@ class _QueryDialog(Dialog):
minvalue = None, maxvalue = None,
parent = None):
if not parent:
parent = tkinter._default_root
self.prompt = prompt
self.minvalue = minvalue
self.maxvalue = maxvalue

View File

@ -36,6 +36,33 @@ class AbstractTkTest:
w.destroy()
self.root.withdraw()
class AbstractDefaultRootTest:
def setUp(self):
self._old_support_default_root = tkinter._support_default_root
destroy_default_root()
tkinter._support_default_root = True
self.wantobjects = tkinter.wantobjects
def tearDown(self):
destroy_default_root()
tkinter._default_root = None
tkinter._support_default_root = self._old_support_default_root
def _test_widget(self, constructor):
# no master passing
x = constructor()
self.assertIsNotNone(tkinter._default_root)
self.assertIs(x.master, tkinter._default_root)
self.assertIs(x.tk, tkinter._default_root.tk)
x.destroy()
destroy_default_root()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, constructor)
self.assertFalse(hasattr(tkinter, '_default_root'))
def destroy_default_root():
if getattr(tkinter, '_default_root', None):
tkinter._default_root.update_idletasks()

View File

@ -2,7 +2,7 @@ import unittest
import tkinter
from tkinter import font
from test.support import requires, run_unittest, gc_collect, ALWAYS_EQ
from tkinter.test.support import AbstractTkTest
from tkinter.test.support import AbstractTkTest, AbstractDefaultRootTest
requires('gui')
@ -107,7 +107,37 @@ class FontTest(AbstractTkTest, unittest.TestCase):
)
tests_gui = (FontTest, )
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
def test_families(self):
self.assertRaises(RuntimeError, font.families)
root = tkinter.Tk()
families = font.families()
self.assertIsInstance(families, tuple)
self.assertTrue(families)
for family in families:
self.assertIsInstance(family, str)
self.assertTrue(family)
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, font.families)
def test_names(self):
self.assertRaises(RuntimeError, font.names)
root = tkinter.Tk()
names = font.names()
self.assertIsInstance(names, tuple)
self.assertTrue(names)
for name in names:
self.assertIsInstance(name, str)
self.assertTrue(name)
self.assertIn(fontname, names)
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, font.names)
tests_gui = (FontTest, DefaultRootTest)
if __name__ == "__main__":
run_unittest(*tests_gui)

View File

@ -2,7 +2,7 @@ import unittest
import tkinter
from test import support
from test.support import os_helper
from tkinter.test.support import AbstractTkTest, requires_tcl
from tkinter.test.support import AbstractTkTest, AbstractDefaultRootTest, requires_tcl
support.requires('gui')
@ -20,6 +20,47 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
self.assertIsInstance(image_names, tuple)
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
def test_image_types(self):
self.assertRaises(RuntimeError, tkinter.image_types)
root = tkinter.Tk()
image_types = tkinter.image_types()
self.assertIsInstance(image_types, tuple)
self.assertIn('photo', image_types)
self.assertIn('bitmap', image_types)
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, tkinter.image_types)
def test_image_names(self):
self.assertRaises(RuntimeError, tkinter.image_names)
root = tkinter.Tk()
image_names = tkinter.image_names()
self.assertIsInstance(image_names, tuple)
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, tkinter.image_names)
def test_image_create_bitmap(self):
self.assertRaises(RuntimeError, tkinter.BitmapImage)
root = tkinter.Tk()
image = tkinter.BitmapImage()
self.assertIn(image.name, tkinter.image_names())
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, tkinter.BitmapImage)
def test_image_create_photo(self):
self.assertRaises(RuntimeError, tkinter.PhotoImage)
root = tkinter.Tk()
image = tkinter.PhotoImage()
self.assertIn(image.name, tkinter.image_names())
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, tkinter.PhotoImage)
class BitmapImageTest(AbstractTkTest, unittest.TestCase):
@classmethod
@ -331,7 +372,7 @@ class PhotoImageTest(AbstractTkTest, unittest.TestCase):
self.assertEqual(image.transparency_get(4, 6), False)
tests_gui = (MiscTest, BitmapImageTest, PhotoImageTest,)
tests_gui = (MiscTest, DefaultRootTest, BitmapImageTest, PhotoImageTest,)
if __name__ == "__main__":
support.run_unittest(*tests_gui)

View File

@ -1,7 +1,7 @@
import unittest
import tkinter
from test import support
from tkinter.test.support import AbstractTkTest
from tkinter.test.support import AbstractTkTest, AbstractDefaultRootTest
support.requires('gui')
@ -241,7 +241,85 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
" num=3 delta=-1 focus=True"
" x=10 y=20 width=300 height=200>")
tests_gui = (MiscTest, )
def test_getboolean(self):
for v in 'true', 'yes', 'on', '1', 't', 'y', 1, True:
self.assertIs(self.root.getboolean(v), True)
for v in 'false', 'no', 'off', '0', 'f', 'n', 0, False:
self.assertIs(self.root.getboolean(v), False)
self.assertRaises(ValueError, self.root.getboolean, 'yea')
self.assertRaises(ValueError, self.root.getboolean, '')
self.assertRaises(TypeError, self.root.getboolean, None)
self.assertRaises(TypeError, self.root.getboolean, ())
def test_mainloop(self):
log = []
def callback():
log.append(1)
self.root.after(100, self.root.quit)
self.root.after(100, callback)
self.root.mainloop(1)
self.assertEqual(log, [])
self.root.mainloop(0)
self.assertEqual(log, [1])
self.assertTrue(self.root.winfo_exists())
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
def test_default_root(self):
self.assertIs(tkinter._support_default_root, True)
self.assertIsNone(tkinter._default_root)
root = tkinter.Tk()
root2 = tkinter.Tk()
root3 = tkinter.Tk()
self.assertIs(tkinter._default_root, root)
root2.destroy()
self.assertIs(tkinter._default_root, root)
root.destroy()
self.assertIsNone(tkinter._default_root)
root3.destroy()
self.assertIsNone(tkinter._default_root)
def test_no_default_root(self):
self.assertIs(tkinter._support_default_root, True)
self.assertIsNone(tkinter._default_root)
root = tkinter.Tk()
self.assertIs(tkinter._default_root, root)
tkinter.NoDefaultRoot()
self.assertIs(tkinter._support_default_root, False)
self.assertFalse(hasattr(tkinter, '_default_root'))
# repeated call is no-op
tkinter.NoDefaultRoot()
self.assertIs(tkinter._support_default_root, False)
self.assertFalse(hasattr(tkinter, '_default_root'))
root.destroy()
self.assertIs(tkinter._support_default_root, False)
self.assertFalse(hasattr(tkinter, '_default_root'))
root = tkinter.Tk()
self.assertIs(tkinter._support_default_root, False)
self.assertFalse(hasattr(tkinter, '_default_root'))
root.destroy()
def test_getboolean(self):
self.assertRaises(RuntimeError, tkinter.getboolean, '1')
root = tkinter.Tk()
self.assertIs(tkinter.getboolean('1'), True)
self.assertRaises(ValueError, tkinter.getboolean, 'yea')
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, tkinter.getboolean, '1')
def test_mainloop(self):
self.assertRaises(RuntimeError, tkinter.mainloop)
root = tkinter.Tk()
root.after_idle(root.quit)
tkinter.mainloop()
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, tkinter.mainloop)
tests_gui = (MiscTest, DefaultRootTest)
if __name__ == "__main__":
support.run_unittest(*tests_gui)

View File

@ -0,0 +1,25 @@
import unittest
import tkinter
from test.support import requires, run_unittest, swap_attr
from tkinter.test.support import AbstractDefaultRootTest
from tkinter.simpledialog import Dialog, askinteger
requires('gui')
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()):
askinteger("Go To Line", "Line number")
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, askinteger, "Go To Line", "Line number")
tests_gui = (DefaultRootTest,)
if __name__ == "__main__":
run_unittest(*tests_gui)

View File

@ -1,8 +1,10 @@
import unittest
import gc
import tkinter
from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl,
TclError)
from test.support import ALWAYS_EQ
from tkinter.test.support import AbstractDefaultRootTest
class Var(Variable):
@ -308,8 +310,21 @@ class TestBooleanVar(TestBase):
v.get()
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
def test_variable(self):
self.assertRaises(RuntimeError, Variable)
root = tkinter.Tk()
v = Variable()
v.set("value")
self.assertEqual(v.get(), "value")
root.destroy()
tkinter.NoDefaultRoot()
self.assertRaises(RuntimeError, Variable)
tests_gui = (TestVariable, TestStringVar, TestIntVar,
TestDoubleVar, TestBooleanVar)
TestDoubleVar, TestBooleanVar, DefaultRootTest)
if __name__ == "__main__":

View File

@ -5,7 +5,8 @@ import os
from test.support import requires
from tkinter.test.support import (tcl_version, requires_tcl,
get_tk_patchlevel, widget_eq)
get_tk_patchlevel, widget_eq,
AbstractDefaultRootTest)
from tkinter.test.widget_tests import (
add_standard_options, noconv, pixels_round,
AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests,
@ -1295,12 +1296,21 @@ class MessageTest(AbstractWidgetTest, unittest.TestCase):
self.checkIntegerParam(widget, 'aspect', 250, 0, -300)
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
def test_frame(self):
self._test_widget(tkinter.Frame)
def test_label(self):
self._test_widget(tkinter.Label)
tests_gui = (
ButtonTest, CanvasTest, CheckbuttonTest, EntryTest,
FrameTest, LabelFrameTest,LabelTest, ListboxTest,
MenubuttonTest, MenuTest, MessageTest, OptionMenuTest,
PanedWindowTest, RadiobuttonTest, ScaleTest, ScrollbarTest,
SpinboxTest, TextTest, ToplevelTest,
SpinboxTest, TextTest, ToplevelTest, DefaultRootTest,
)
if __name__ == '__main__':

View File

@ -2,8 +2,8 @@ import sys
import unittest
import tkinter
from tkinter import ttk
from test.support import requires, run_unittest, swap_attr
from tkinter.test.support import AbstractTkTest, destroy_default_root
from test.support import requires, run_unittest
from tkinter.test.support import AbstractTkTest, AbstractDefaultRootTest
requires('gui')
@ -46,20 +46,6 @@ class LabeledScaleTest(AbstractTkTest, unittest.TestCase):
if hasattr(sys, 'last_type'):
self.assertNotEqual(sys.last_type, tkinter.TclError)
def test_initialization_no_master(self):
# no master passing
with swap_attr(tkinter, '_default_root', None), \
swap_attr(tkinter, '_support_default_root', True):
try:
x = ttk.LabeledScale()
self.assertIsNotNone(tkinter._default_root)
self.assertEqual(x.master, tkinter._default_root)
self.assertEqual(x.tk, tkinter._default_root.tk)
x.destroy()
finally:
destroy_default_root()
def test_initialization(self):
# master passing
master = tkinter.Frame(self.root)
@ -311,7 +297,13 @@ class OptionMenuTest(AbstractTkTest, unittest.TestCase):
optmenu2.destroy()
tests_gui = (LabeledScaleTest, OptionMenuTest)
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
def test_labeledscale(self):
self._test_widget(ttk.LabeledScale)
tests_gui = (LabeledScaleTest, OptionMenuTest, DefaultRootTest)
if __name__ == "__main__":
run_unittest(*tests_gui)

View File

@ -6,7 +6,7 @@ import sys
from tkinter.test.test_ttk.test_functions import MockTclObj
from tkinter.test.support import (AbstractTkTest, tcl_version, get_tk_patchlevel,
simulate_mouse_click)
simulate_mouse_click, AbstractDefaultRootTest)
from tkinter.test.widget_tests import (add_standard_options, noconv,
AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests,
setUpModule)
@ -1860,12 +1860,22 @@ class SizegripTest(AbstractWidgetTest, unittest.TestCase):
def create(self, **kwargs):
return ttk.Sizegrip(self.root, **kwargs)
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
def test_frame(self):
self._test_widget(ttk.Frame)
def test_label(self):
self._test_widget(ttk.Label)
tests_gui = (
ButtonTest, CheckbuttonTest, ComboboxTest, EntryTest,
FrameTest, LabelFrameTest, LabelTest, MenubuttonTest,
NotebookTest, PanedWindowTest, ProgressbarTest,
RadiobuttonTest, ScaleTest, ScrollbarTest, SeparatorTest,
SizegripTest, SpinboxTest, TreeviewTest, WidgetTest,
SizegripTest, SpinboxTest, TreeviewTest, WidgetTest, DefaultRootTest,
)
if __name__ == "__main__":

View File

@ -387,9 +387,7 @@ class TixWidget(tkinter.Widget):
# These are missing from Tkinter
def image_create(self, imgtype, cnf={}, master=None, **kw):
if not master:
master = tkinter._default_root
if not master:
raise RuntimeError('Too early to create image')
master = self
if kw and cnf: cnf = _cnfmerge((cnf, kw))
elif kw: cnf = kw
options = ()
@ -475,10 +473,7 @@ class DisplayStyle:
elif 'refwindow' in cnf:
master = cnf['refwindow']
else:
master = tkinter._default_root
if not master:
raise RuntimeError("Too early to create display style: "
"no root window")
master = tkinter._get_default_root('create display style')
self.tk = master.tk
self.stylename = self.tk.call('tixDisplayStyle', itemtype,
*self._options(cnf,kw) )

View File

@ -349,12 +349,7 @@ def setup_master(master=None):
If it is not allowed to use the default root and master is None,
RuntimeError is raised."""
if master is None:
if tkinter._support_default_root:
master = tkinter._default_root or tkinter.Tk()
else:
raise RuntimeError(
"No master specified and tkinter is "
"configured to not support default root")
master = tkinter._get_default_root()
return master

View File

@ -1624,6 +1624,7 @@ Ville Skyttä
Michael Sloan
Nick Sloan
Václav Šmilauer
Casper W. Smet
Allen W. Smith
Christopher Smith
Eric V. Smith

View File

@ -0,0 +1 @@
:func:`random.sample` no longer warns on a sequence which is also a set.

View File

@ -0,0 +1,4 @@
:mod:`tkinter` functions and constructors which need a default root window
raise now :exc:`RuntimeError` with descriptive message instead of obscure
:exc:`AttributeError` or :exc:`NameError` if it is not created yet or cannot
be created automatically.

View File

@ -36,15 +36,11 @@ class PyncheWidget:
else:
# Is there already a default root for Tk, say because we're
# running under Guido's IDE? :-) Two conditions say no, either the
# import fails or _default_root is None.
tkroot = None
try:
from Tkinter import _default_root
tkroot = self.__tkroot = _default_root
except ImportError:
pass
# _default_root is None or it is unset.
tkroot = getattr(tkinter, '_default_root', None)
if not tkroot:
tkroot = self.__tkroot = Tk(className='Pynche')
tkroot = Tk(className='Pynche')
self.__tkroot = tkroot
# but this isn't our top level widget, so make it invisible
tkroot.withdraw()
# create the menubar