aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2021-01-25 11:45:30 +0200
committerGitHub <noreply@github.com>2021-01-25 11:45:30 +0200
commit3d5434d5cbc945c58be663e3dbd5ef4875677b7a (patch)
tree50bb94cc884cc7f084c43afd815e45b08bfaebb5
parentbpo-43013: Update idlelib code to 3.x (GH-24315) (diff)
downloadcpython-3d5434d5cbc945c58be663e3dbd5ef4875677b7a.tar.gz
cpython-3d5434d5cbc945c58be663e3dbd5ef4875677b7a.tar.bz2
cpython-3d5434d5cbc945c58be663e3dbd5ef4875677b7a.zip
[3.9] bpo-33289: Return RGB triplet of ints instead of floats from tkinter.colorchooser (GH-6578). (GH-24318)
(cherry picked from commit 6713e869c4989c04318158b406c30a147ea52904) Co-authored-by: Cheryl Sabella <cheryl.sabella@gmail.com>
-rw-r--r--Lib/tkinter/__init__.py3
-rw-r--r--Lib/tkinter/colorchooser.py60
-rw-r--r--Lib/tkinter/test/test_tkinter/test_colorchooser.py43
-rw-r--r--Lib/tkinter/test/test_tkinter/test_misc.py20
-rw-r--r--Misc/NEWS.d/next/Library/2018-04-23-13-44-10.bpo-33289.anBnUr.rst2
5 files changed, 102 insertions, 26 deletions
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 98e95ad448..f15f6c5e57 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -1160,8 +1160,7 @@ class Misc:
self.tk.call('winfo', 'reqwidth', self._w))
def winfo_rgb(self, color):
- """Return tuple of decimal values for red, green, blue for
- COLOR in this widget."""
+ """Return a tuple of integer RGB values in range(65536) for color in this widget."""
return self._getints(
self.tk.call('winfo', 'rgb', self._w, color))
diff --git a/Lib/tkinter/colorchooser.py b/Lib/tkinter/colorchooser.py
index 3cfc06f6f1..e2fb69dba9 100644
--- a/Lib/tkinter/colorchooser.py
+++ b/Lib/tkinter/colorchooser.py
@@ -8,57 +8,69 @@
# fixed initialcolor handling in August 1998
#
-#
-# options (all have default values):
-#
-# - initialcolor: color to mark as selected when dialog is displayed
-# (given as an RGB triplet or a Tk color string)
-#
-# - parent: which window to place the dialog on top of
-#
-# - title: dialog title
-#
from tkinter.commondialog import Dialog
__all__ = ["Chooser", "askcolor"]
-#
-# color chooser class
-
class Chooser(Dialog):
- "Ask for a color"
+ """Create a dialog for the tk_chooseColor command.
+
+ Args:
+ master: The master widget for this dialog. If not provided,
+ defaults to options['parent'] (if defined).
+ options: Dictionary of options for the tk_chooseColor call.
+ initialcolor: Specifies the selected color when the
+ dialog is first displayed. This can be a tk color
+ string or a 3-tuple of ints in the range (0, 255)
+ for an RGB triplet.
+ parent: The parent window of the color dialog. The
+ color dialog is displayed on top of this.
+ title: A string for the title of the dialog box.
+ """
command = "tk_chooseColor"
def _fixoptions(self):
+ """Ensure initialcolor is a tk color string.
+
+ Convert initialcolor from a RGB triplet to a color string.
+ """
try:
- # make sure initialcolor is a tk color string
color = self.options["initialcolor"]
if isinstance(color, tuple):
- # assume an RGB triplet
+ # Assume an RGB triplet.
self.options["initialcolor"] = "#%02x%02x%02x" % color
except KeyError:
pass
def _fixresult(self, widget, result):
- # result can be somethings: an empty tuple, an empty string or
- # a Tcl_Obj, so this somewhat weird check handles that
+ """Adjust result returned from call to tk_chooseColor.
+
+ Return both an RGB tuple of ints in the range (0, 255) and the
+ tk color string in the form #rrggbb.
+ """
+ # Result can be many things: an empty tuple, an empty string, or
+ # a _tkinter.Tcl_Obj, so this somewhat weird check handles that.
if not result or not str(result):
- return None, None # canceled
+ return None, None # canceled
- # to simplify application code, the color chooser returns
- # an RGB tuple together with the Tk color string
+ # To simplify application code, the color chooser returns
+ # an RGB tuple together with the Tk color string.
r, g, b = widget.winfo_rgb(result)
- return (r/256, g/256, b/256), str(result)
+ return (r//256, g//256, b//256), str(result)
#
# convenience stuff
-def askcolor(color = None, **options):
- "Ask for a color"
+def askcolor(color=None, **options):
+ """Display dialog window for selection of a color.
+
+ Convenience wrapper for the Chooser class. Displays the color
+ chooser dialog with color as the initial value.
+ """
if color:
options = options.copy()
diff --git a/Lib/tkinter/test/test_tkinter/test_colorchooser.py b/Lib/tkinter/test/test_tkinter/test_colorchooser.py
new file mode 100644
index 0000000000..4798bc9c26
--- /dev/null
+++ b/Lib/tkinter/test/test_tkinter/test_colorchooser.py
@@ -0,0 +1,43 @@
+import unittest
+import tkinter
+from test.support import requires, run_unittest, swap_attr
+from tkinter.test.support import AbstractTkTest
+from tkinter import colorchooser
+
+requires('gui')
+
+
+class ChooserTest(AbstractTkTest, unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ AbstractTkTest.setUpClass.__func__(cls)
+ cls.cc = colorchooser.Chooser(initialcolor='dark blue slate')
+
+ def test_fixoptions(self):
+ cc = self.cc
+ cc._fixoptions()
+ self.assertEqual(cc.options['initialcolor'], 'dark blue slate')
+
+ cc.options['initialcolor'] = '#D2D269691E1E'
+ cc._fixoptions()
+ self.assertEqual(cc.options['initialcolor'], '#D2D269691E1E')
+
+ cc.options['initialcolor'] = (210, 105, 30)
+ cc._fixoptions()
+ self.assertEqual(cc.options['initialcolor'], '#d2691e')
+
+ def test_fixresult(self):
+ cc = self.cc
+ self.assertEqual(cc._fixresult(self.root, ()), (None, None))
+ self.assertEqual(cc._fixresult(self.root, ''), (None, None))
+ self.assertEqual(cc._fixresult(self.root, 'chocolate'),
+ ((210, 105, 30), 'chocolate'))
+ self.assertEqual(cc._fixresult(self.root, '#4a3c8c'),
+ ((74, 60, 140), '#4a3c8c'))
+
+
+tests_gui = (ChooserTest,)
+
+if __name__ == "__main__":
+ run_unittest(*tests_gui)
diff --git a/Lib/tkinter/test/test_tkinter/test_misc.py b/Lib/tkinter/test/test_tkinter/test_misc.py
index 585d81ddf9..f6e5b4db1a 100644
--- a/Lib/tkinter/test/test_tkinter/test_misc.py
+++ b/Lib/tkinter/test/test_tkinter/test_misc.py
@@ -192,6 +192,26 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
with self.assertRaises(tkinter.TclError):
root.clipboard_get()
+ def test_winfo_rgb(self):
+ root = self.root
+ rgb = root.winfo_rgb
+
+ # Color name.
+ self.assertEqual(rgb('red'), (65535, 0, 0))
+ self.assertEqual(rgb('dark slate blue'), (18504, 15677, 35723))
+ # #RGB - extends each 4-bit hex value to be 16-bit.
+ self.assertEqual(rgb('#F0F'), (0xFFFF, 0x0000, 0xFFFF))
+ # #RRGGBB - extends each 8-bit hex value to be 16-bit.
+ self.assertEqual(rgb('#4a3c8c'), (0x4a4a, 0x3c3c, 0x8c8c))
+ # #RRRRGGGGBBBB
+ self.assertEqual(rgb('#dede14143939'), (0xdede, 0x1414, 0x3939))
+ # Invalid string.
+ with self.assertRaises(tkinter.TclError):
+ rgb('#123456789a')
+ # RGB triplet is invalid input.
+ with self.assertRaises(tkinter.TclError):
+ rgb((111, 78, 55))
+
def test_event_repr_defaults(self):
e = tkinter.Event()
e.serial = 12345
diff --git a/Misc/NEWS.d/next/Library/2018-04-23-13-44-10.bpo-33289.anBnUr.rst b/Misc/NEWS.d/next/Library/2018-04-23-13-44-10.bpo-33289.anBnUr.rst
new file mode 100644
index 0000000000..52d9ac9dd9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-04-23-13-44-10.bpo-33289.anBnUr.rst
@@ -0,0 +1,2 @@
+Correct call to :mod:`tkinter.colorchooser` to return RGB triplet of ints
+instead of floats. Patch by Cheryl Sabella.