Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

### Fixed
- Fix `hex_to_rgb` parsing of 3-digit shorthand hexadecimal colors such as `#FFF` [[#5662](https://github.com/plotly/plotly.py/pull/5662)], with thanks to @genrichez for the contribution!


## [6.9.0] - 2026-07-09

Expand Down
11 changes: 10 additions & 1 deletion _plotly_utils/colors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -752,11 +752,20 @@ def hex_to_rgb(value):
"""
Calculates rgb values from a hex color code.
:param (string) value: Hex color string
:param (string) value: Hex color string. May be a full 6-character code
or a 3-character shorthand code.
:rtype (tuple) (r_value, g_value, b_value): tuple of rgb values
Example:
'#FFFFFF' --> (255, 255, 255)
'#FFF' --> (255, 255, 255)
"""
value = value.lstrip("#")
if len(value) == 3:
value = "".join(c * 2 for c in value)
hex_total_length = len(value)
rgb_section_length = hex_total_length // 3
return tuple(
Expand Down
19 changes: 2 additions & 17 deletions plotly/matplotlylib/mpltools.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import warnings
import matplotlib.dates

from _plotly_utils.colors import hex_to_rgb


def check_bar_match(old_bar, new_bar):
"""Check if two bars belong in the same collection (bar chart).
Expand Down Expand Up @@ -104,23 +106,6 @@ def convert_symbol(mpl_symbol):
return "circle" # default


def hex_to_rgb(value):
"""
Change a hex color to an rgb tuple

:param (str|unicode) value: The hex string we want to convert.
:return: (int, int, int) The red, green, blue int-tuple.

Example:

'#FFFFFF' --> (255, 255, 255)

"""
value = value.lstrip("#")
lv = len(value)
return tuple(int(value[i : i + lv // 3], 16) for i in range(0, lv, lv // 3))


def merge_color_and_opacity(color, opacity):
"""
Merge hex color with an alpha (opacity) to get an rgba tuple.
Expand Down
9 changes: 9 additions & 0 deletions tests/test_plotly_utils/colors/test_color_conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ def test_hex_to_rgb_basic_values():
assert hex_to_rgb("#aabbcc") == (170, 187, 204)


def test_hex_to_rgb_shorthand_3_digit():
assert hex_to_rgb("#fff") == (255, 255, 255)
assert hex_to_rgb("#000") == (0, 0, 0)
assert hex_to_rgb("#abc") == (170, 187, 204)
assert hex_to_rgb("#f00") == (255, 0, 0)
assert hex_to_rgb("#0f0") == (0, 255, 0)
assert hex_to_rgb("#00f") == (0, 0, 255)


def test_label_rgb_formats_tuple():
assert label_rgb((255, 0, 0)) == "rgb(255, 0, 0)"
assert label_rgb((1, 2, 3)) == "rgb(1, 2, 3)"
Expand Down