Skip to content

Commit c9062f1

Browse files
committed
Merge branch 'main' of github.com:plotly/plotly.py into refactor/autoshapes-use-shape-label
Merge branch 'main' into refactor/autoshapes-use-shape-label# the commit.
2 parents 515b4e4 + b009b25 commit c9062f1

File tree

393 files changed

+102588
-100628
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

393 files changed

+102588
-100628
lines changed

.github/pull_request_template.md

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,30 @@
11
<!--
2-
Please uncomment this block and fill in this checklist if your PR makes substantial changes to documentation in the `doc` directory.
3-
Not all boxes must be checked for every PR:
4-
check those that apply to your PR and leave the rest unchecked to discuss with your reviewer.
5-
6-
If your PR modifies code of the `plotly` package, we have a different checklist below.
7-
8-
## Documentation PR
9-
10-
- [ ] I have seen the [`doc/README.md`](https://github.com/plotly/plotly.py/blob/main/doc/README.md) file.
11-
- [ ] This change runs in the current version of Plotly on PyPI and targets the `doc-prod` branch OR it targets the `main` branch.
12-
- [ ] If this PR modifies the first example in a page or adds a new one, it is a `px` example if at all possible.
13-
- [ ] Every new/modified example has a descriptive title and motivating sentence or paragraph.
14-
- [ ] Every new/modified example is independently runnable.
15-
- [ ] Every new/modified example is optimized for short line count and focuses on the Plotly/visualization-related aspects of the example rather than the computation required to produce the data being visualized.
16-
- [ ] Meaningful/relatable datasets are used for all new examples instead of randomly-generated data where possible.
17-
- [ ] The random seed is set if using randomly-generated data.
18-
- [ ] New/modified remote datasets are loaded from https://plotly.github.io/datasets and added to https://github.com/plotly/datasets.
19-
- [ ] Large computations are avoided in the new/modified examples in favour of loading remote datasets that represent the output of such computations.
20-
- [ ] Imports are `plotly.graph_objects as go`, `plotly.express as px`, and/or `plotly.io as pio`.
21-
- [ ] Data frames are always called `df`.
22-
- [ ] `fig = <something>` is called high up in each new/modified example (either `px.<something>` or `make_subplots` or `go.Figure`).
23-
- [ ] Liberal use is made of `fig.add_*` and `fig.update_*` rather than `go.Figure(data=..., layout=...)`.
24-
- [ ] Specific adders and updaters like `fig.add_shape` and `fig.update_xaxes` are used instead of big `fig.update_layout` calls.
25-
- [ ] `fig.show()` is at the end of each example.
26-
- [ ] `plotly.plot()` and `plotly.iplot()` are not used in any example.
27-
- [ ] Named colors are used instead of hex codes wherever possible.
28-
- [ ] Code blocks are marked with `&#96;&#96;&#96;python`.
29-
30-
## Code PR
31-
32-
- [ ] I have read through the [contributing notes](https://github.com/plotly/plotly.py/blob/main/CONTRIBUTING.md) and understand the structure of the package. In particular, if my PR modifies code of `plotly.graph_objects`, my modifications concern the code generator and *not* the generated files.
33-
- [ ] I have added tests or modified existing tests.
34-
- [ ] For a new feature, I have added documentation examples (please see the doc checklist as well).
35-
- [ ] I have added a CHANGELOG entry if changing anything substantial.
36-
- [ ] For a new feature or a change in behavior, I have updated the relevant docstrings in the code.
2+
Thank you for your contribution to plotly.py!
373
4+
Please complete each section below.
385
-->
6+
7+
### Link to issue
8+
<!-- Link to the issue closed by this PR. If the issue doesn't exist yet, create it. -->
9+
10+
Closes #(issue number)
11+
12+
### Description of change
13+
<!-- Provide a clear 1-2 sentence description of what this PR does. -->
14+
15+
### Demo
16+
17+
<!-- Include screenshots or screen recordings of this PR in action. -->
18+
19+
### Testing strategy
20+
21+
<!-- Provide 1-2 sentences explaining tests added or changed by this PR. If testing changes are not needed, explain why. -->
22+
23+
### Additional information (optional)
24+
25+
<!-- Include any additional context, background, or explanation which doesn't fit in the previous sections. -->
26+
27+
### Guidelines
28+
29+
- [ ] I have reviewed the [pull request guidelines](https://github.com/plotly/plotly.py/blob/main/CONTRIBUTING.md#opening-a-pull-request) and the [Code of Conduct](https://github.com/plotly/plotly.py/blob/main/CODE_OF_CONDUCT.md) and confirm that this PR follows them.
30+
- [ ] I have added an entry to the [changelog](https://github.com/plotly/plotly.py/blob/main/CHANGELOG.md) if needed (not required for documentation PRs).

CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,38 @@ This project adheres to [Semantic Versioning](http://semver.org/).
44

55
## Unreleased
66

7+
### Fixed
8+
- Update `numpy.percentile` syntax to stop using deprecated alias [[5483](https://github.com/plotly/plotly.py/pull/5483)], with thanks to @Mr-Neutr0n for the contribution!
9+
- `numpy` with a version less than 1.22 is no longer supported.
10+
11+
## [6.6.0] - 2026-03-02
12+
13+
### Fixed
14+
- Remove unneeded `type="text/javascript"` attribute from `<style>` tag [[#5454](https://github.com/plotly/plotly.py/pull/5454)], with thanks to @hannob for the contribution!
15+
- Remove global warning format side effect [[#5481](https://github.com/plotly/plotly.py/pull/5481)], with thanks to @emmanuel-ferdman for the contribution!
16+
- Fix spurious engine deprecation warning in write_image [[#5517](https://github.com/plotly/plotly.py/pull/5517)], with thanks to @mosh3eb for the contribution!
17+
18+
### Updated
19+
- Update plotly.js from version 3.3.1 to version 3.4.0. See the plotly.js [release notes](https://github.com/plotly/plotly.js/releases/tag/v3.4.0) for more information. [[#5527](https://github.com/plotly/plotly.py/pull/5527)]. Notable changes include:
20+
- Add support for clicking legend titles to toggle visibility of all traces in legend [[#7698](https://github.com/plotly/plotly.js/pull/7698)]
21+
- Add support for shapes to reference multiple axes [[#7666](https://github.com/plotly/plotly.js/pull/7666)]
22+
- Add support for dashed marker lines in scatter plots [[#7673](https://github.com/plotly/plotly.js/pull/7673)]
23+
- Increase axis autorange when bar charts have outside text labels, to avoid labels being clipped [[#7675](https://github.com/plotly/plotly.js/pull/7675)]
24+
25+
## [6.5.2] - 2026-01-14
26+
27+
### Fixed
28+
- Fix issue where pie trace `legend`, `showlegend` attributes don't accept array values [[#5464](https://github.com/plotly/plotly.py/pull/5464) and [#5465](https://github.com/plotly/plotly.py/pull/5465)], with thanks to @my-tien for the contribution!
29+
30+
## [6.5.1] - 2026-01-07
31+
32+
### Fixed
33+
- Fix issue where Plotly Express ignored trace-specific color sequences defined in templates via `template.data.<trace_type>` [[#5437](https://github.com/plotly/plotly.py/pull/5437)], with thanks to @antonymilne for the contribution!
34+
735
### Updated
836
- Speed up `validate_gantt` function [[#5386](https://github.com/plotly/plotly.py/pull/5386)], with thanks to @misrasaurabh1 for the contribution!
37+
- Update plotly.js from version 3.3.0 to version 3.3.1. See the plotly.js [release notes](https://github.com/plotly/plotly.js/releases/tag/v3.3.1) for more information. [[#5456](https://github.com/plotly/plotly.py/pull/5456)]. Notable changes include:
38+
- Add support for arrays for the pie properties `showlegend` and `legend`, so that these can be configured per slice. [[#7580](https://github.com/plotly/plotly.js/pull/7580)]
939

1040
## [6.5.0] - 2025-11-17
1141

CITATION.cff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ authors:
99
- family-names: "Parmer"
1010
given-names: "Chris"
1111
title: "An interactive, open-source, and browser-based graphing library for Python"
12-
version: 6.5.0
12+
version: 6.6.0
1313
doi: 10.5281/zenodo.14503524
14-
date-released: 2025-11-17
14+
date-released: 2026-03-02
1515
url: "https://github.com/plotly/plotly.py"

CONTRIBUTING.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ npm run build
137137
These commands also create an *editable install* of plotly.py
138138
so that you can test your changes iteratively without having to rebuild the plotly.py package explicitly;
139139
for more information please see
140-
[the `pip` documentation on editable installs](https://pip.pypa.io/en/stable/reference/pip_install/#install-editable)
140+
[the `pip` documentation on editable installs](https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs)
141141
Please note that the single quotes are needed to escape the `[]` characters.
142142

143143
### Formatting
@@ -171,6 +171,42 @@ and create your pull request.
171171
> Please do _not_ commit changes to `uv.lock`
172172
> unless you have added, removed, or changed dependencies in `pyproject.toml`.
173173
174+
## Opening a pull request
175+
176+
When creating your pull request, please follow the guidelines below.
177+
178+
### Code pull request
179+
180+
- *Make sure you have reviewed the full [contributing notes (this file)](https://github.com/plotly/plotly.py/blob/main/CONTRIBUTING.md) and understand the structure of the package.*
181+
- If your PR modifies code of `plotly.graph_objects`, the modifications should be made to the the code generator, *not* the generated files.
182+
- You have added tests or modified existing tests, as needed.
183+
- For a new feature, you have added documentation examples (please see the doc checklist as well).
184+
- You have added a CHANGELOG entry if changing anything substantial.
185+
- For a new feature or a change in behavior, you have updated the relevant docstrings in the code.
186+
187+
### Documentation pull request
188+
189+
- *Make sure you have reviewed the [`doc/README.md`](https://github.com/plotly/plotly.py/blob/main/doc/README.md) file.*
190+
- This change runs in the current version of Plotly on PyPI and targets the `doc-prod` branch OR it targets the `main` branch.
191+
- If this PR modifies the first example in a page or adds a new one, it is a `px` example if at all possible.
192+
- Every new/modified example has a descriptive title and motivating sentence or paragraph.
193+
- Every new/modified example is independently runnable.
194+
- Every new/modified example is optimized for short line count and focuses on the Plotly/visualization-related aspects of the example rather than the computation required to produce the data being visualized.
195+
- Meaningful/relatable datasets are used for all new examples instead of randomly-generated data where possible.
196+
- The random seed is set if using randomly-generated data.
197+
- New/modified remote datasets are loaded from https://plotly.github.io/datasets and added to https://github.com/plotly/datasets.
198+
- Large computations are avoided in the new/modified examples in favour of loading remote datasets that represent the output of such computations.
199+
- Imports are `plotly.graph_objects as go`, `plotly.express as px`, and/or `plotly.io as pio`.
200+
- Data frames are always called `df`.
201+
- `fig = <something>` is called high up in each new/modified example (either `px.<something>` or `make_subplots` or `go.Figure`).
202+
- Liberal use is made of `fig.add_*` and `fig.update_*` rather than `go.Figure(data=..., layout=...)`.
203+
- Specific adders and updaters like `fig.add_shape` and `fig.update_xaxes` are used instead of big `fig.update_layout` calls.
204+
- `fig.show()` is at the end of each example.
205+
- `plotly.plot()` and `plotly.iplot()` are not used in any example.
206+
- Named colors are used instead of hex codes wherever possible.
207+
- Code blocks are marked with `&#96;&#96;&#96;python`.
208+
209+
174210
### Testing
175211

176212
We use [pytest](https://docs.pytest.org/) for managing and running tests.

_plotly_utils/basevalidators.py

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -632,24 +632,35 @@ class BooleanValidator(BaseValidator):
632632
"description": "A boolean (true/false) value.",
633633
"requiredOpts": [],
634634
"otherOpts": [
635+
"arrayOk",
635636
"dflt"
636637
]
637638
},
638639
"""
639640

640-
def __init__(self, plotly_name, parent_name, **kwargs):
641+
def __init__(self, plotly_name, parent_name, array_ok=False, **kwargs):
641642
super(BooleanValidator, self).__init__(
642643
plotly_name=plotly_name, parent_name=parent_name, **kwargs
643644
)
645+
self.array_ok = array_ok
644646

645647
def description(self):
646-
return """\
647-
The '{plotly_name}' property must be specified as a bool
648-
(either True, or False)""".format(plotly_name=self.plotly_name)
648+
desc = """\
649+
The '{plotly_name}' property is a boolean and must be specified as:
650+
- A boolean value: True or False""".format(plotly_name=self.plotly_name)
651+
if self.array_ok:
652+
desc += """
653+
- A tuple or list of the above"""
654+
return desc
649655

650656
def validate_coerce(self, v):
651657
if is_none_or_typed_array_spec(v):
652658
pass
659+
elif self.array_ok and is_simple_array(v):
660+
invalid_els = [e for e in v if not isinstance(e, bool)]
661+
if invalid_els:
662+
self.raise_invalid_elements(invalid_els[:10])
663+
v = to_scalar_or_list(v)
653664
elif not isinstance(v, bool):
654665
self.raise_invalid_val(v)
655666

@@ -1735,12 +1746,15 @@ class SubplotidValidator(BaseValidator):
17351746
"dflt"
17361747
],
17371748
"otherOpts": [
1749+
"arrayOk",
17381750
"regex"
17391751
]
17401752
}
17411753
"""
17421754

1743-
def __init__(self, plotly_name, parent_name, dflt=None, regex=None, **kwargs):
1755+
def __init__(
1756+
self, plotly_name, parent_name, dflt=None, regex=None, array_ok=False, **kwargs
1757+
):
17441758
if dflt is None and regex is None:
17451759
raise ValueError("One or both of regex and deflt must be specified")
17461760

@@ -1755,40 +1769,55 @@ def __init__(self, plotly_name, parent_name, dflt=None, regex=None, **kwargs):
17551769
self.base = re.match(r"/\^(\w+)", regex).group(1)
17561770

17571771
self.regex = self.base + r"(\d*)"
1772+
self.array_ok = array_ok
17581773

17591774
def description(self):
17601775
desc = """\
17611776
The '{plotly_name}' property is an identifier of a particular
1762-
subplot, of type '{base}', that may be specified as the string '{base}'
1763-
optionally followed by an integer >= 1
1764-
(e.g. '{base}', '{base}1', '{base}2', '{base}3', etc.)
1765-
""".format(plotly_name=self.plotly_name, base=self.base)
1777+
subplot, of type '{base}', that may be specified as:
1778+
- the string '{base}' optionally followed by an integer >= 1
1779+
(e.g. '{base}', '{base}1', '{base}2', '{base}3', etc.)""".format(
1780+
plotly_name=self.plotly_name, base=self.base
1781+
)
1782+
if self.array_ok:
1783+
desc += """
1784+
- A tuple or list of the above"""
17661785
return desc
17671786

17681787
def validate_coerce(self, v):
1769-
if v is None:
1770-
pass
1771-
elif not isinstance(v, str):
1772-
self.raise_invalid_val(v)
1773-
else:
1774-
# match = re.fullmatch(self.regex, v)
1775-
match = fullmatch(self.regex, v)
1788+
def coerce(value):
1789+
if not isinstance(value, str):
1790+
return value, False
1791+
match = fullmatch(self.regex, value)
17761792
if not match:
1777-
is_valid = False
1793+
return value, False
17781794
else:
17791795
digit_str = match.group(1)
17801796
if len(digit_str) > 0 and int(digit_str) == 0:
1781-
is_valid = False
1797+
return value, False
17821798
elif len(digit_str) > 0 and int(digit_str) == 1:
1783-
# Remove 1 suffix (e.g. x1 -> x)
1784-
v = self.base
1785-
is_valid = True
1799+
return self.base, True
17861800
else:
1787-
is_valid = True
1801+
return value, True
17881802

1789-
if not is_valid:
1790-
self.raise_invalid_val(v)
1791-
return v
1803+
if v is None:
1804+
pass
1805+
elif self.array_ok and is_simple_array(v):
1806+
values = []
1807+
invalid_els = []
1808+
for e in v:
1809+
coerced_e, success = coerce(e)
1810+
values.append(coerced_e)
1811+
if not success:
1812+
invalid_els.append(coerced_e)
1813+
if len(invalid_els) > 0:
1814+
self.raise_invalid_elements(invalid_els[:10])
1815+
return values
1816+
else:
1817+
v, success = coerce(v)
1818+
if not success:
1819+
self.raise_invalid_val(self.base)
1820+
return v
17921821

17931822

17941823
class FlaglistValidator(BaseValidator):

_plotly_utils/colors/_swatches.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def _swatches(module_names, module_contents, template=None):
1515
from plotly.express._core import apply_default_cascade
1616

1717
args = dict(template=template)
18-
apply_default_cascade(args)
18+
apply_default_cascade(args, constructor=None)
1919

2020
sequences = [
2121
(k, v)
@@ -66,7 +66,7 @@ def _swatches_continuous(module_names, module_contents, template=None):
6666
from plotly.express._core import apply_default_cascade
6767

6868
args = dict(template=template)
69-
apply_default_cascade(args)
69+
apply_default_cascade(args, constructor=None)
7070

7171
sequences = [
7272
(k, v)
@@ -122,7 +122,7 @@ def _swatches_cyclical(module_names, module_contents, template=None):
122122
from plotly.express._core import apply_default_cascade
123123

124124
args = dict(template=template)
125-
apply_default_cascade(args)
125+
apply_default_cascade(args, constructor=None)
126126

127127
rows = 2
128128
cols = 4

0 commit comments

Comments
 (0)