From 05863832be76ded4ff3c05eda1c2b07865087f4e Mon Sep 17 00:00:00 2001 From: landoskape Date: Wed, 15 Nov 2023 08:00:23 +0000 Subject: [PATCH 01/16] Update _has_alpha_channel --- lib/matplotlib/colors.py | 32 +++++++++++++++++++++++++++-- lib/matplotlib/tests/test_colors.py | 9 ++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 2ce27a810a43..ae32bc04e277 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -233,8 +233,36 @@ def is_color_like(c): def _has_alpha_channel(c): """Return whether *c* is a color with an alpha channel.""" - # 4-element sequences are interpreted as r, g, b, a - return not isinstance(c, str) and len(c) == 4 + # If c is not a color, it doesn't have an alpha channel + if not is_color_like(c): + return False + + # if c is a hex, it has an alpha channel when it has 4 (or 8) digits after '#' + if isinstance(c, str) and c[0] == '#' and (len(c) == 5 or len(c) == 9): + # example: '#fff8' or '#0f0f0f80' + return True + + # if c isn't a string, it can be an RGB(A) or a color-alpha tuple + if not isinstance(c, str): + # if it has length 4, it has an alpha channel + if len(c) == 4: + # example: [0.5, 0.5, 0.5, 0.5] + return True + + # if it has length 2, the 2nd element isn't None, and the 1st element has len=3 + if len(c) == 2 and (c[1] is not None or len(c[0]) == 4): + # example: ([0.5, 0.5, 0.5, 0.5], None) or ('r', 0.5) + return True + + # otherwise it doesn't have an alpha channel + return False + + +def _has_alpha_channel_array(cseq): + """Return whether each element in *cseq* is a color with an alpha channel""" + if is_color_like(cseq): + cseq = [cseq] # force it to be a sequence + return [_has_alpha_channel(c) for c in cseq] def _check_color_like(**kwargs): diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 139efbe17407..e4ed86b7db00 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -1231,10 +1231,19 @@ def test_colormap_reversing(name): def test_has_alpha_channel(): assert mcolors._has_alpha_channel((0, 0, 0, 0)) assert mcolors._has_alpha_channel([1, 1, 1, 1]) + assert mcolors._has_alpha_channel('#fff8') + assert mcolors._has_alpha_channel('#0f0f0f80') + assert mcolors._has_alpha_channel(('r', 0.5)) + assert mcolors._has_alpha_channel(([1, 1, 1, 1], None)) assert not mcolors._has_alpha_channel('blue') # 4-char string! assert not mcolors._has_alpha_channel('0.25') assert not mcolors._has_alpha_channel('r') assert not mcolors._has_alpha_channel((1, 0, 0)) + assert not mcolors._has_alpha_channel('#fff') + assert not mcolors._has_alpha_channel('#0f0f0f') + assert not mcolors._has_alpha_channel(('r', None)) + assert not mcolors._has_alpha_channel(([1, 1, 1], None)) + assert not mcolors._has_alpha_channel(1) # non-colors don't have alpha channels def test_cn(): From 9719b60eab52d36aaaa7c9562c4541f7c334d1e6 Mon Sep 17 00:00:00 2001 From: Andrew Landau Date: Wed, 15 Nov 2023 09:00:31 +0000 Subject: [PATCH 02/16] Update lib/matplotlib/colors.py Co-authored-by: Oscar Gustafsson --- lib/matplotlib/colors.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index ae32bc04e277..33f3687606df 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -238,12 +238,12 @@ def _has_alpha_channel(c): return False # if c is a hex, it has an alpha channel when it has 4 (or 8) digits after '#' - if isinstance(c, str) and c[0] == '#' and (len(c) == 5 or len(c) == 9): - # example: '#fff8' or '#0f0f0f80' - return True - - # if c isn't a string, it can be an RGB(A) or a color-alpha tuple - if not isinstance(c, str): + if isinstance(c, str): + if c[0] == '#' and (len(c) == 5 or len(c) == 9): + # example: '#fff8' or '#0f0f0f80' + return True + else: + # if c isn't a string, it can be an RGB(A) or a color-alpha tuple # if it has length 4, it has an alpha channel if len(c) == 4: # example: [0.5, 0.5, 0.5, 0.5] From 77e759f08e06b1de1d9e390d480f1d434aca203d Mon Sep 17 00:00:00 2001 From: landoskape Date: Wed, 15 Nov 2023 09:02:32 +0000 Subject: [PATCH 03/16] Clarify comment explanation --- lib/matplotlib/colors.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 33f3687606df..1d91293af5d2 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -249,7 +249,8 @@ def _has_alpha_channel(c): # example: [0.5, 0.5, 0.5, 0.5] return True - # if it has length 2, the 2nd element isn't None, and the 1st element has len=3 + # if it has length 2, it's a color/alpha tuple + # if the second element isn't None or the first element has length = 4 if len(c) == 2 and (c[1] is not None or len(c[0]) == 4): # example: ([0.5, 0.5, 0.5, 0.5], None) or ('r', 0.5) return True From 5d7edca6e9648880d3e0b95de3a3a133d2211572 Mon Sep 17 00:00:00 2001 From: landoskape Date: Tue, 21 Nov 2023 20:23:21 +0000 Subject: [PATCH 04/16] Remove unnecessary check about is_color_like --- lib/matplotlib/colors.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 1d91293af5d2..281238f902ba 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -232,11 +232,7 @@ def is_color_like(c): def _has_alpha_channel(c): - """Return whether *c* is a color with an alpha channel.""" - # If c is not a color, it doesn't have an alpha channel - if not is_color_like(c): - return False - + """Return whether *c* is a color with an alpha channel""" # if c is a hex, it has an alpha channel when it has 4 (or 8) digits after '#' if isinstance(c, str): if c[0] == '#' and (len(c) == 5 or len(c) == 9): From e7220c837113bfbc306208ed0f8786a63849b3d3 Mon Sep 17 00:00:00 2001 From: landoskape Date: Fri, 3 Jan 2025 09:32:34 +0000 Subject: [PATCH 05/16] update docstring for undefined case --- lib/matplotlib/colors.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 281238f902ba..c05ed93801da 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -232,7 +232,11 @@ def is_color_like(c): def _has_alpha_channel(c): - """Return whether *c* is a color with an alpha channel""" + """Return whether *c* is a color with an alpha channel. + + If *c* is not a valid color specifier, then the result is + undefined but will return False. + """ # if c is a hex, it has an alpha channel when it has 4 (or 8) digits after '#' if isinstance(c, str): if c[0] == '#' and (len(c) == 5 or len(c) == 9): @@ -251,7 +255,7 @@ def _has_alpha_channel(c): # example: ([0.5, 0.5, 0.5, 0.5], None) or ('r', 0.5) return True - # otherwise it doesn't have an alpha channel + # otherwise it doesn't have an alpha channel (or is not a valid color specifier) return False From 0cf36120aed0c11c9d1cab7ba90bcd05bf12ffbb Mon Sep 17 00:00:00 2001 From: landoskape Date: Fri, 3 Jan 2025 09:39:01 +0000 Subject: [PATCH 06/16] Deprecate unused method --- lib/matplotlib/colors.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index c05ed93801da..e0d1a103cd8f 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -259,6 +259,11 @@ def _has_alpha_channel(c): return False +@_api.deprecated( + '3.11', + removal='3.14', + alternative="``use matplotlib.colors._has_alpha_channel`` with list comprehension" + ) def _has_alpha_channel_array(cseq): """Return whether each element in *cseq* is a color with an alpha channel""" if is_color_like(cseq): From e2099e6ebc0183178e23f2bf4ffadd35cf813f27 Mon Sep 17 00:00:00 2001 From: landoskape Date: Sat, 4 Jan 2025 17:07:06 +0000 Subject: [PATCH 07/16] Remove unnecessary method --- lib/matplotlib/colors.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index e0d1a103cd8f..09c65e630650 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -259,18 +259,6 @@ def _has_alpha_channel(c): return False -@_api.deprecated( - '3.11', - removal='3.14', - alternative="``use matplotlib.colors._has_alpha_channel`` with list comprehension" - ) -def _has_alpha_channel_array(cseq): - """Return whether each element in *cseq* is a color with an alpha channel""" - if is_color_like(cseq): - cseq = [cseq] # force it to be a sequence - return [_has_alpha_channel(c) for c in cseq] - - def _check_color_like(**kwargs): """ For each *key, value* pair in *kwargs*, check that *value* is color-like. From 5ac2c0ffc7f06f7215bb6645326c9fb46458c33d Mon Sep 17 00:00:00 2001 From: Andrew Landau Date: Sat, 4 Jan 2025 17:12:47 +0000 Subject: [PATCH 08/16] Flake formatting update Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/colors.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 09c65e630650..9316812e29f8 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -232,7 +232,8 @@ def is_color_like(c): def _has_alpha_channel(c): - """Return whether *c* is a color with an alpha channel. + """ + Return whether *c* is a color with an alpha channel. If *c* is not a valid color specifier, then the result is undefined but will return False. From 212363eaee0e260c204b220bba27341086dba627 Mon Sep 17 00:00:00 2001 From: Andrew Landau Date: Sat, 4 Jan 2025 17:13:07 +0000 Subject: [PATCH 09/16] Don't specify what an undefined result does Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/colors.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 9316812e29f8..9086a6653422 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -235,8 +235,7 @@ def _has_alpha_channel(c): """ Return whether *c* is a color with an alpha channel. - If *c* is not a valid color specifier, then the result is - undefined but will return False. + If *c* is not a valid color specifier, then the result is undefined. """ # if c is a hex, it has an alpha channel when it has 4 (or 8) digits after '#' if isinstance(c, str): From 73127eb93de32d75025e8674ef98e5fcebf97a39 Mon Sep 17 00:00:00 2001 From: Andrew Landau Date: Sat, 4 Jan 2025 17:16:23 +0000 Subject: [PATCH 10/16] Recursive check which handles hex colors too Co-authored-by: Ruth Comer <10599679+rcomer@users.noreply.github.com> --- lib/matplotlib/colors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 9086a6653422..ef8785bdee88 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -251,7 +251,7 @@ def _has_alpha_channel(c): # if it has length 2, it's a color/alpha tuple # if the second element isn't None or the first element has length = 4 - if len(c) == 2 and (c[1] is not None or len(c[0]) == 4): + if len(c) == 2 and (c[1] is not None or _has_alpha_channel(c[0]): # example: ([0.5, 0.5, 0.5, 0.5], None) or ('r', 0.5) return True From c3cf8d41dd8ac52d2ec6f2f2588ed3c21518231e Mon Sep 17 00:00:00 2001 From: landoskape Date: Sat, 4 Jan 2025 17:19:45 +0000 Subject: [PATCH 11/16] Whitespace --- lib/matplotlib/colors.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index ef8785bdee88..afc89b591fce 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -237,6 +237,10 @@ def _has_alpha_channel(c): If *c* is not a valid color specifier, then the result is undefined. """ + # If c isn't a color, this is undefined. Return False instead of raising. + if not is_color_like(c): + return False + # if c is a hex, it has an alpha channel when it has 4 (or 8) digits after '#' if isinstance(c, str): if c[0] == '#' and (len(c) == 5 or len(c) == 9): @@ -251,7 +255,7 @@ def _has_alpha_channel(c): # if it has length 2, it's a color/alpha tuple # if the second element isn't None or the first element has length = 4 - if len(c) == 2 and (c[1] is not None or _has_alpha_channel(c[0]): + if len(c) == 2 and (c[1] is not None or _has_alpha_channel(c[0])): # example: ([0.5, 0.5, 0.5, 0.5], None) or ('r', 0.5) return True From b81786c90aab3635e6c386ef11595b087101cbff Mon Sep 17 00:00:00 2001 From: Andrew Landau Date: Sun, 5 Jan 2025 00:03:07 +0000 Subject: [PATCH 12/16] Remove is_color_like check and explain Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/colors.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index afc89b591fce..577c93cc0dd0 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -237,9 +237,9 @@ def _has_alpha_channel(c): If *c* is not a valid color specifier, then the result is undefined. """ - # If c isn't a color, this is undefined. Return False instead of raising. - if not is_color_like(c): - return False + # The following logic is build with the assumtion that c is a valid color spec. + # For speed and simplicity, we intentionally don't care about other inputs. + # Anything can happen with them. # if c is a hex, it has an alpha channel when it has 4 (or 8) digits after '#' if isinstance(c, str): From 80d422d2f6fc7ed7a038e2a35dc516d711059536 Mon Sep 17 00:00:00 2001 From: Andrew Landau Date: Sun, 5 Jan 2025 00:03:29 +0000 Subject: [PATCH 13/16] Don't discuss undefined results Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/colors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 577c93cc0dd0..b2d36851515a 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -259,7 +259,7 @@ def _has_alpha_channel(c): # example: ([0.5, 0.5, 0.5, 0.5], None) or ('r', 0.5) return True - # otherwise it doesn't have an alpha channel (or is not a valid color specifier) + # otherwise it doesn't have an alpha channel return False From bbe6fa2adcc3b74bc88e3cc8ae8e6e14c88f7fb4 Mon Sep 17 00:00:00 2001 From: Andrew Landau Date: Sun, 5 Jan 2025 00:03:54 +0000 Subject: [PATCH 14/16] Remove test of undefined result Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/tests/test_colors.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index e4ed86b7db00..a70b047d3dfc 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -1243,7 +1243,6 @@ def test_has_alpha_channel(): assert not mcolors._has_alpha_channel('#0f0f0f') assert not mcolors._has_alpha_channel(('r', None)) assert not mcolors._has_alpha_channel(([1, 1, 1], None)) - assert not mcolors._has_alpha_channel(1) # non-colors don't have alpha channels def test_cn(): From de5e42df15ab8a8e87a5a449614ab1d107bcc116 Mon Sep 17 00:00:00 2001 From: Andrew Landau Date: Mon, 6 Jan 2025 15:45:53 +0000 Subject: [PATCH 15/16] Spelling error Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/colors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index b2d36851515a..55456319596e 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -237,7 +237,7 @@ def _has_alpha_channel(c): If *c* is not a valid color specifier, then the result is undefined. """ - # The following logic is build with the assumtion that c is a valid color spec. + # The following logic is build with the assumption that c is a valid color spec. # For speed and simplicity, we intentionally don't care about other inputs. # Anything can happen with them. From 0813e130c580542626292498d7f4c7bed7e79475 Mon Sep 17 00:00:00 2001 From: Andrew Landau Date: Mon, 6 Jan 2025 15:46:43 +0000 Subject: [PATCH 16/16] improved grammar in comment --- lib/matplotlib/colors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 55456319596e..0d0186e9f770 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -237,7 +237,7 @@ def _has_alpha_channel(c): If *c* is not a valid color specifier, then the result is undefined. """ - # The following logic is build with the assumption that c is a valid color spec. + # The following logic uses the assumption that c is a valid color spec. # For speed and simplicity, we intentionally don't care about other inputs. # Anything can happen with them.