mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-140481: Improve error message when trying to iterate a Tk widget, image or font (GH-140501)
This commit is contained in:
parent
ad0a3f733b
commit
09b1f10ef7
6 changed files with 59 additions and 22 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
import collections.abc
|
||||||
import unittest
|
import unittest
|
||||||
import tkinter
|
import tkinter
|
||||||
from tkinter import font
|
from tkinter import font
|
||||||
|
|
@ -118,6 +119,16 @@ def test_repr(self):
|
||||||
repr(self.font), f'<tkinter.font.Font object {fontname!r}>'
|
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):
|
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import collections.abc
|
||||||
import unittest
|
import unittest
|
||||||
import tkinter
|
import tkinter
|
||||||
from test import support
|
from test import support
|
||||||
|
|
@ -61,7 +62,33 @@ def test_image_create_photo(self):
|
||||||
self.assertRaises(RuntimeError, tkinter.PhotoImage)
|
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
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
|
@ -144,26 +171,15 @@ def test_configure_foreground(self):
|
||||||
self.assertEqual(image['foreground'],
|
self.assertEqual(image['foreground'],
|
||||||
'-foreground {} {} #000000 yellow')
|
'-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(BaseImageTest, AbstractTkTest, unittest.TestCase):
|
||||||
class PhotoImageTest(AbstractTkTest, unittest.TestCase):
|
image_class = tkinter.PhotoImage
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
AbstractTkTest.setUpClass.__func__(cls)
|
AbstractTkTest.setUpClass.__func__(cls)
|
||||||
cls.testfile = support.findfile('python.gif', subdir='tkinterdata')
|
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):
|
def colorlist(self, *args):
|
||||||
if tkinter.TkVersion >= 8.6 and self.wantobjects:
|
if tkinter.TkVersion >= 8.6 and self.wantobjects:
|
||||||
return args
|
return args
|
||||||
|
|
@ -282,14 +298,6 @@ def test_configure_palette(self):
|
||||||
image.configure(palette='3/4/2')
|
image.configure(palette='3/4/2')
|
||||||
self.assertEqual(image['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):
|
def test_blank(self):
|
||||||
image = self.create()
|
image = self.create()
|
||||||
image.blank()
|
image.blank()
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import collections.abc
|
||||||
import functools
|
import functools
|
||||||
import unittest
|
import unittest
|
||||||
import tkinter
|
import tkinter
|
||||||
|
|
@ -508,6 +509,17 @@ def test_embedded_null(self):
|
||||||
widget.selection_range(0, 'end')
|
widget.selection_range(0, 'end')
|
||||||
self.assertEqual(widget.selection_get(), '\u20ac\0abc\x00def')
|
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):
|
class WmTest(AbstractTkTest, unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1848,6 +1848,7 @@ def cget(self, key):
|
||||||
return self.tk.call(self._w, 'cget', '-' + key)
|
return self.tk.call(self._w, 'cget', '-' + key)
|
||||||
|
|
||||||
__getitem__ = cget
|
__getitem__ = cget
|
||||||
|
__iter__ = None # prevent using __getitem__ for iteration
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
self.configure({key: value})
|
self.configure({key: value})
|
||||||
|
|
@ -4280,6 +4281,8 @@ def __setitem__(self, key, value):
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return self.tk.call(self.name, 'configure', '-'+key)
|
return self.tk.call(self.name, 'configure', '-'+key)
|
||||||
|
|
||||||
|
__iter__ = None # prevent using __getitem__ for iteration
|
||||||
|
|
||||||
def configure(self, **kw):
|
def configure(self, **kw):
|
||||||
"""Configure the image."""
|
"""Configure the image."""
|
||||||
res = ()
|
res = ()
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,8 @@ def __getitem__(self, key):
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
self.configure(**{key: value})
|
self.configure(**{key: value})
|
||||||
|
|
||||||
|
__iter__ = None # prevent using __getitem__ for iteration
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
try:
|
try:
|
||||||
if self.delete_font:
|
if self.delete_font:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Improve error message when trying to iterate a Tk widget, image or font.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue