gh-140481: Improve error message when trying to iterate a Tk widget, image or font (GH-140501)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import collections.abc
|
||||
import unittest
|
||||
import tkinter
|
||||
from tkinter import font
|
||||
@@ -118,6 +119,16 @@ class FontTest(AbstractTkTest, unittest.TestCase):
|
||||
repr(self.font), f'<tkinter.font.Font object {fontname!r}>'
|
||||
)
|
||||
|
||||
def test_iterable_protocol(self):
|
||||
self.assertNotIsSubclass(font.Font, collections.abc.Iterable)
|
||||
self.assertNotIsSubclass(font.Font, collections.abc.Container)
|
||||
self.assertNotIsInstance(self.font, collections.abc.Iterable)
|
||||
self.assertNotIsInstance(self.font, collections.abc.Container)
|
||||
with self.assertRaisesRegex(TypeError, 'is not iterable'):
|
||||
iter(self.font)
|
||||
with self.assertRaisesRegex(TypeError, 'is not a container or iterable'):
|
||||
self.font in self.font
|
||||
|
||||
|
||||
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import collections.abc
|
||||
import unittest
|
||||
import tkinter
|
||||
from test import support
|
||||
@@ -61,7 +62,33 @@ class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
|
||||
self.assertRaises(RuntimeError, tkinter.PhotoImage)
|
||||
|
||||
|
||||
class BitmapImageTest(AbstractTkTest, unittest.TestCase):
|
||||
class BaseImageTest:
|
||||
def create(self):
|
||||
return self.image_class('::img::test', master=self.root,
|
||||
file=self.testfile)
|
||||
|
||||
def test_bug_100814(self):
|
||||
# gh-100814: Passing a callable option value causes AttributeError.
|
||||
with self.assertRaises(tkinter.TclError):
|
||||
self.image_class('::img::test', master=self.root, spam=print)
|
||||
image = self.image_class('::img::test', master=self.root)
|
||||
with self.assertRaises(tkinter.TclError):
|
||||
image.configure(spam=print)
|
||||
|
||||
def test_iterable_protocol(self):
|
||||
image = self.create()
|
||||
self.assertNotIsSubclass(self.image_class, collections.abc.Iterable)
|
||||
self.assertNotIsSubclass(self.image_class, collections.abc.Container)
|
||||
self.assertNotIsInstance(image, collections.abc.Iterable)
|
||||
self.assertNotIsInstance(image, collections.abc.Container)
|
||||
with self.assertRaisesRegex(TypeError, 'is not iterable'):
|
||||
iter(image)
|
||||
with self.assertRaisesRegex(TypeError, 'is not a container or iterable'):
|
||||
image in image
|
||||
|
||||
|
||||
class BitmapImageTest(BaseImageTest, AbstractTkTest, unittest.TestCase):
|
||||
image_class = tkinter.BitmapImage
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@@ -144,26 +171,15 @@ class BitmapImageTest(AbstractTkTest, unittest.TestCase):
|
||||
self.assertEqual(image['foreground'],
|
||||
'-foreground {} {} #000000 yellow')
|
||||
|
||||
def test_bug_100814(self):
|
||||
# gh-100814: Passing a callable option value causes AttributeError.
|
||||
with self.assertRaises(tkinter.TclError):
|
||||
tkinter.BitmapImage('::img::test', master=self.root, spam=print)
|
||||
image = tkinter.BitmapImage('::img::test', master=self.root)
|
||||
with self.assertRaises(tkinter.TclError):
|
||||
image.configure(spam=print)
|
||||
|
||||
|
||||
class PhotoImageTest(AbstractTkTest, unittest.TestCase):
|
||||
class PhotoImageTest(BaseImageTest, AbstractTkTest, unittest.TestCase):
|
||||
image_class = tkinter.PhotoImage
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
AbstractTkTest.setUpClass.__func__(cls)
|
||||
cls.testfile = support.findfile('python.gif', subdir='tkinterdata')
|
||||
|
||||
def create(self):
|
||||
return tkinter.PhotoImage('::img::test', master=self.root,
|
||||
file=self.testfile)
|
||||
|
||||
def colorlist(self, *args):
|
||||
if tkinter.TkVersion >= 8.6 and self.wantobjects:
|
||||
return args
|
||||
@@ -282,14 +298,6 @@ class PhotoImageTest(AbstractTkTest, unittest.TestCase):
|
||||
image.configure(palette='3/4/2')
|
||||
self.assertEqual(image['palette'], '3/4/2')
|
||||
|
||||
def test_bug_100814(self):
|
||||
# gh-100814: Passing a callable option value causes AttributeError.
|
||||
with self.assertRaises(tkinter.TclError):
|
||||
tkinter.PhotoImage('::img::test', master=self.root, spam=print)
|
||||
image = tkinter.PhotoImage('::img::test', master=self.root)
|
||||
with self.assertRaises(tkinter.TclError):
|
||||
image.configure(spam=print)
|
||||
|
||||
def test_blank(self):
|
||||
image = self.create()
|
||||
image.blank()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import collections.abc
|
||||
import functools
|
||||
import unittest
|
||||
import tkinter
|
||||
@@ -508,6 +509,17 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
|
||||
widget.selection_range(0, 'end')
|
||||
self.assertEqual(widget.selection_get(), '\u20ac\0abc\x00def')
|
||||
|
||||
def test_iterable_protocol(self):
|
||||
widget = tkinter.Entry(self.root)
|
||||
self.assertNotIsSubclass(tkinter.Entry, collections.abc.Iterable)
|
||||
self.assertNotIsSubclass(tkinter.Entry, collections.abc.Container)
|
||||
self.assertNotIsInstance(widget, collections.abc.Iterable)
|
||||
self.assertNotIsInstance(widget, collections.abc.Container)
|
||||
with self.assertRaisesRegex(TypeError, 'is not iterable'):
|
||||
iter(widget)
|
||||
with self.assertRaisesRegex(TypeError, 'is not a container or iterable'):
|
||||
widget in widget
|
||||
|
||||
|
||||
class WmTest(AbstractTkTest, unittest.TestCase):
|
||||
|
||||
|
||||
@@ -1848,6 +1848,7 @@ class Misc:
|
||||
return self.tk.call(self._w, 'cget', '-' + key)
|
||||
|
||||
__getitem__ = cget
|
||||
__iter__ = None # prevent using __getitem__ for iteration
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.configure({key: value})
|
||||
@@ -4280,6 +4281,8 @@ class Image:
|
||||
def __getitem__(self, key):
|
||||
return self.tk.call(self.name, 'configure', '-'+key)
|
||||
|
||||
__iter__ = None # prevent using __getitem__ for iteration
|
||||
|
||||
def configure(self, **kw):
|
||||
"""Configure the image."""
|
||||
res = ()
|
||||
|
||||
@@ -114,6 +114,8 @@ class Font:
|
||||
def __setitem__(self, key, value):
|
||||
self.configure(**{key: value})
|
||||
|
||||
__iter__ = None # prevent using __getitem__ for iteration
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
if self.delete_font:
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Improve error message when trying to iterate a Tk widget, image or font.
|
||||
Reference in New Issue
Block a user