[Python-checkins] bpo-33289: Return RGB triplet of ints instead of floats from tkinter.colorchooser (GH-6578)

serhiy-storchaka webhook-mailer at python.org
Thu Jan 21 14:14:13 EST 2021


https://github.com/python/cpython/commit/6713e869c4989c04318158b406c30a147ea52904
commit: 6713e869c4989c04318158b406c30a147ea52904
branch: master
author: Cheryl Sabella <cheryl.sabella at gmail.com>
committer: serhiy-storchaka <storchaka at gmail.com>
date: 2021-01-21T21:14:04+02:00
summary:

bpo-33289: Return RGB triplet of ints instead of floats from tkinter.colorchooser (GH-6578)

files:
A Misc/NEWS.d/next/Library/2018-04-23-13-44-10.bpo-33289.anBnUr.rst
M Lib/tkinter/__init__.py
M Lib/tkinter/colorchooser.py
M Lib/tkinter/test/test_tkinter/test_colorchooser.py
M Lib/tkinter/test/test_tkinter/test_misc.py

diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 57ac3fb5cf6ef..01dce7eff25c5 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -1185,8 +1185,7 @@ def winfo_reqwidth(self):
             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 3cfc06f6f1fae..e2fb69dba9276 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
index 600c8cde67e76..41da86c2adef4 100644
--- a/Lib/tkinter/test/test_tkinter/test_colorchooser.py
+++ b/Lib/tkinter/test/test_tkinter/test_colorchooser.py
@@ -1,13 +1,44 @@
 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.test.support import AbstractDefaultRootTest, AbstractTkTest
+from tkinter import colorchooser
 from tkinter.colorchooser import askcolor
+from tkinter.commondialog import Dialog
 
 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'))
+
+
 class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
 
     def test_askcolor(self):
@@ -33,7 +64,7 @@ def test_callback(dialog, master):
             self.assertRaises(RuntimeError, askcolor)
 
 
-tests_gui = (DefaultRootTest,)
+tests_gui = (ChooserTest, DefaultRootTest,)
 
 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 585d81ddf9f2d..f6e5b4db1ae1f 100644
--- a/Lib/tkinter/test/test_tkinter/test_misc.py
+++ b/Lib/tkinter/test/test_tkinter/test_misc.py
@@ -192,6 +192,26 @@ def test_clipboard_astral(self):
         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 0000000000000..52d9ac9dd902c
--- /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.



More information about the Python-checkins mailing list