Skip to content

Commit 5dcd0c7

Browse files
committed
Merge branch main into px-category-order-3198
Keep main's new Unreleased changelog entries and place the Plotly Express x-axis entry at the end of the Fixed list.
2 parents a911810 + 84498cc commit 5dcd0c7

3 files changed

Lines changed: 45 additions & 3 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1616
- Fix `mpl_to_plotly` dropping matplotlib stairs plots by rendering `StepPatch` artists as step lines or filled step areas from their path vertices and edge style [[#5698](https://github.com/plotly/plotly.py/pull/5698)], with thanks to @robertoffmoura for the contribution!
1717
- Fix `mpl_to_plotly` showing unwanted legends with placeholder or internal label entries (`_nolegend_`, `_childN`) by defaulting `layout.showlegend=False` unless the matplotlib figure explicitly defines a legend [[#5699](https://github.com/plotly/plotly.py/pull/5699)], with thanks to @robertoffmoura for the contribution!
1818
- Fix `mpl_to_plotly` crashing on figures with fully transparent or alpha-carrying colors, such as boxplot outlier markers (`facecolor="none"`), rgba line colors, and `color="none"` text and axis labels; all matplotlib colors are now exported through a single helper that maps `"none"` to transparent rgba and keeps or overrides alpha as matplotlib does [[#5700](https://github.com/plotly/plotly.py/pull/5700)], with thanks to @robertoffmoura for the contribution!
19+
- Fix serialization of box/lasso select data for figures with multiple subplots [[#5710](https://github.com/plotly/plotly.py/pull/5710)], with thanks to @flpi-sun for the contribution!
1920
- Export tick label colors to the plotly tickfont in `mpl_to_plotly` [[#5716](https://github.com/plotly/plotly.py/pull/5716)], with thanks to @robertoffmoura for the contribution!
20-
- Fix Plotly Express mutating lists passed to the `x` or `y` arguments in wide mode [[#5727](https://github.com/plotly/plotly.py/pull/5727)], with thanks to @cpruijsen for the contribution!
2121
- Fix `convert_dash` mapping dotted lines (`linestyle=':'`) to invalid `'circle'` in Plotly, correctly converting them to `'dot'` and preserving custom dash patterns as pixel lists, [[#5719](https://github.com/plotly/plotly.py/pull/5719)] with thanks to @robertoffmoura for the contribution!
22+
- Fix Plotly Express mutating lists passed to the `x` or `y` arguments in wide mode [[#5727](https://github.com/plotly/plotly.py/pull/5727)], with thanks to @cpruijsen for the contribution!
2223
- Fix `px.sunburst`, `px.treemap` and `px.icicle` listing sectors in a different order on every run when `path` is used with a Polars DataFrame; sectors now follow their order of first appearance for all dataframe backends [[#5766](https://github.com/plotly/plotly.py/pull/5766)], with thanks to @Irahan2 for the contribution!
2324
- Fix `mpl_to_plotly` conversion of matplotlib contour lines and line collections: close contour rings ending with `Z` codes, support dash styles, convert date x-axes, separate disjoint subpaths with `None` separators, hide line collection traces from the legend by default, and group consecutive same-style lines into single traces [[#5770](https://github.com/plotly/plotly.py/pull/5770)], with thanks to @robertoffmoura for the contribution!
24-
- Fix serialization of box/lasso select data for figures with multiple subplots [[#5710](https://github.com/plotly/plotly.py/pull/5710)], with thanks to @flpi-sun for the contribution!
2525
- Fix `plotly.io.write_images` ignoring `layout.width`/`layout.height` (and the template's) and exporting every figure at the default 700x500 size; it now uses the same width/height priority as `write_image` and `to_image` [[#5784](https://github.com/plotly/plotly.py/pull/5784)], with thanks to @breken-ai for the contribution!
26+
- Fix color utilities mutating the list of colors passed to them [[#5836](https://github.com/plotly/plotly.py/pull/5836)], with thanks to @Enesuygurs for the contribution!
2627
- Fix Plotly Express scrambling the order of the categorical x-axis when the data is split into several traces (e.g. by `color`); the x-axis now follows the order of first appearance in the underlying data, on single-subplot figures, on each facet of faceted figures and in 3D figures, while marginal axes spanning the y dimension are left alone [[#3198](https://github.com/plotly/plotly.py/issues/3198), [#3291](https://github.com/plotly/plotly.py/issues/3291)]
2728

2829
## [7.1.0] - 2026-09-15

‎_plotly_utils/colors/__init__.py‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ def validate_colors(colors, colortype="tuple"):
338338
else:
339339
colors = list(colors)
340340

341+
else:
342+
# copy the list so that neither the caller's list nor
343+
# DEFAULT_PLOTLY_COLORS is modified in place below
344+
colors = list(colors)
345+
341346
# convert color elements in list to tuple color
342347
for j, each_color in enumerate(colors):
343348
if "rgb" in each_color:
@@ -377,6 +382,9 @@ def validate_colors_dict(colors, colortype="tuple"):
377382
"""
378383
Validates dictionary of color(s)
379384
"""
385+
# copy the dict so that the caller's dict is not modified in place below
386+
colors = dict(colors)
387+
380388
# validate each color element in the dictionary
381389
for key in colors:
382390
if "rgb" in colors[key]:
@@ -454,7 +462,7 @@ def convert_colors_to_same_type(
454462
colors_list = list(colors)
455463

456464
elif isinstance(colors, list):
457-
colors_list = colors
465+
colors_list = list(colors)
458466

459467
# validate scale
460468
if scale is not None:
@@ -498,6 +506,9 @@ def convert_dict_colors_to_same_type(colors_dict, colortype="rgb"):
498506
499507
:param (dict) colors_dict: a dictionary whose values are single colors
500508
"""
509+
# copy the dict so that the caller's dict is not modified in place below
510+
colors_dict = dict(colors_dict)
511+
501512
for key in colors_dict:
502513
if "#" in colors_dict[key]:
503514
colors_dict[key] = color_parser(colors_dict[key], hex_to_rgb)
@@ -818,6 +829,10 @@ def convert_colorscale_to_rgb(colorscale):
818829
converting a colorscale with tuple colors (each coordinate between 0
819830
and 1) into a colorscale with the colors transformed into rgb colors
820831
"""
832+
# copy the colorscale and its [scale, color] pairs so that the caller's
833+
# colorscale is not modified in place below
834+
colorscale = [list(color) for color in colorscale]
835+
821836
for color in colorscale:
822837
color[1] = convert_to_RGB_255(color[1])
823838

‎tests/test_core/test_colors/test_colors.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,32 @@ def test_convert_colors_to_same_type(self):
5959
colortype,
6060
)
6161

62+
def test_color_conversions_do_not_modify_input(self):
63+
default_colors = list(colors.DEFAULT_PLOTLY_COLORS)
64+
65+
colors.validate_colors(None)
66+
self.assertEqual(colors.DEFAULT_PLOTLY_COLORS, default_colors)
67+
68+
color_list = ["rgb(255, 0, 0)", "#0000ff"]
69+
colors.validate_colors(color_list)
70+
self.assertEqual(color_list, ["rgb(255, 0, 0)", "#0000ff"])
71+
72+
colors.convert_colors_to_same_type(color_list, colortype="tuple")
73+
self.assertEqual(color_list, ["rgb(255, 0, 0)", "#0000ff"])
74+
75+
color_dict = {"a": "rgb(255, 0, 0)", "b": "#0000ff", "c": (0.5, 0.5, 0.5)}
76+
expected_dict = dict(color_dict)
77+
78+
colors.validate_colors_dict(color_dict, colortype="rgb")
79+
self.assertEqual(color_dict, expected_dict)
80+
81+
colors.convert_dict_colors_to_same_type(color_dict, colortype="tuple")
82+
self.assertEqual(color_dict, expected_dict)
83+
84+
colorscale = [[0, (0.0, 0.0, 0.0)], [1, (1.0, 1.0, 1.0)]]
85+
colors.convert_colorscale_to_rgb(colorscale)
86+
self.assertEqual(colorscale, [[0, (0.0, 0.0, 0.0)], [1, (1.0, 1.0, 1.0)]])
87+
6288
def test_convert_dict_colors_to_same_type(self):
6389
# test colortype
6490
color_dict = dict(apple="rgb(1, 1, 1)")

0 commit comments

Comments
 (0)