Skip to content

Commit 97dd016

Browse files
authoredMay 5, 2023
Merge branch 'master' into LiamConnors-patch-1
·
v6.2.0v5.15.0
2 parents 458ce89 + 59ffd90 commit 97dd016

File tree

18 files changed

+1342
-1013
lines changed

18 files changed

+1342
-1013
lines changed
 

‎.circleci/config.yml

Lines changed: 157 additions & 58 deletions
Large diffs are not rendered by default.

‎.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,6 @@ doc/check-or-enforce-order.py
5252
packages/javascript/jupyterlab-plotly/lib/
5353
packages/python/plotly/jupyterlab_plotly/labextension/
5454
packages/python/plotly/jupyterlab_plotly/nbextension/index.js*
55+
56+
test/percy/*.html
57+
test/percy/pandas2/*.html

‎CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5+
## [UNRELEASED]
6+
7+
### Fixed
8+
- Fixed another compatibility issue with Pandas 2.0, just affecting `px.*(line_close=True)` [[#4190](https://github.com/plotly/plotly.py/pull/4190)]
9+
- Added some rounding to the `make_subplots` function to handle situations where the user-input specs cause the domain to exceed 1 by small amounts https://github.com/plotly/plotly.py/pull/4153
10+
511
## [5.14.1] - 2023-04-05
612

713
### Fixed

‎doc/python/static-image-export.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,42 +109,42 @@ If you are running this notebook live, click to [open the output directory](./im
109109

110110
plotly.py can output figures to several raster image formats including **PNG**, ...
111111

112-
```python
112+
~~~python
113113
fig.write_image("images/fig1.png")
114-
```
114+
~~~
115115

116116
**JPEG**, ...
117117

118-
```python
118+
~~~python
119119
fig.write_image("images/fig1.jpeg")
120-
```
120+
~~~
121121

122122
and **WebP**
123123

124-
```python
124+
~~~python
125125
fig.write_image("images/fig1.webp")
126-
```
126+
~~~
127127

128128
#### Vector Formats: SVG and PDF...
129129

130130

131131
plotly.py can also output figures in several vector formats including **SVG**, ...
132132

133-
```python
133+
~~~python
134134
fig.write_image("images/fig1.svg")
135-
```
135+
~~~
136136

137137
**PDF**, ...
138138

139-
```python
139+
~~~python
140140
fig.write_image("images/fig1.pdf")
141-
```
141+
~~~
142142

143143
and **EPS** (requires the poppler library)
144144

145-
```python
145+
~~~python
146146
fig.write_image("images/fig1.eps")
147-
```
147+
~~~
148148

149149
**Note:** It is important to note that any figures containing WebGL traces (i.e. of type `scattergl`, `heatmapgl`, `contourgl`, `scatter3d`, `surface`, `mesh3d`, `scatterpolargl`, `cone`, `streamtube`, `splom`, or `parcoords`) that are exported in a vector format will include encapsulated rasters, instead of vectors, for some parts of the image.
150150

@@ -199,14 +199,14 @@ Image(img_bytes)
199199
If `kaleido` is installed, it will automatically be used to perform image export. If it is not installed, plotly.py will attempt to use `orca` instead. The `engine` argument to the `to_image` and `write_image` functions can be used to override this default behavior.
200200

201201
Here is an example of specifying that orca should be used:
202-
```python
202+
~~~python
203203
fig.to_image(format="png", engine="orca")
204-
```
204+
~~~
205205

206206
And, here is an example of specifying that Kaleido should be used:
207-
```python
207+
~~~python
208208
fig.to_image(format="png", engine="kaleido")
209-
```
209+
~~~
210210

211211
<!-- #endregion -->
212212

‎packages/python/plotly/plotly/_subplots.py

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,6 @@ def _check_hv_spacing(dimsize, spacing, name, dimvarname, dimname):
671671
# Loop through specs -- (r, c) <-> (row, col)
672672
for r, spec_row in enumerate(specs):
673673
for c, spec in enumerate(spec_row):
674-
675674
if spec is None: # skip over None cells
676675
continue
677676

@@ -702,6 +701,46 @@ def _check_hv_spacing(dimsize, spacing, name, dimvarname, dimname):
702701
else:
703702
y_s = grid[r_spanned][c][1] + spec["b"]
704703
y_e = grid[r][c][1] + heights[-1 - r] - spec["t"]
704+
705+
if y_s < 0.0:
706+
# round for values very close to one
707+
# handles some floating point errors
708+
if y_s > -0.01:
709+
y_s = 0.0
710+
else:
711+
raise Exception(
712+
"A combination of the 'b' values, heights, and "
713+
"number of subplots too large for this subplot grid."
714+
)
715+
if y_s > 1.0:
716+
# round for values very close to one
717+
# handles some floating point errors
718+
if y_s < 1.01:
719+
y_s = 1.0
720+
else:
721+
raise Exception(
722+
"A combination of the 'b' values, heights, and "
723+
"number of subplots too large for this subplot grid."
724+
)
725+
726+
if y_e < 0.0:
727+
if y_e > -0.01:
728+
y_e = 0.0
729+
else:
730+
raise Exception(
731+
"A combination of the 't' values, heights, and "
732+
"number of subplots too large for this subplot grid."
733+
)
734+
735+
if y_e > 1.0:
736+
if y_e < 1.01:
737+
y_e = 1.0
738+
else:
739+
raise Exception(
740+
"A combination of the 't' values, heights, and "
741+
"number of subplots too large for this subplot grid."
742+
)
743+
705744
y_domain = [y_s, y_e]
706745

707746
list_of_domains.append(x_domain)
@@ -726,7 +765,6 @@ def _check_hv_spacing(dimsize, spacing, name, dimvarname, dimname):
726765
insets_ref = [None for inset in range(len(insets))] if insets else None
727766
if insets:
728767
for i_inset, inset in enumerate(insets):
729-
730768
r = inset["cell"][0] - 1
731769
c = inset["cell"][1] - 1
732770

@@ -1052,7 +1090,6 @@ def _subplot_type_for_trace_type(trace_type):
10521090

10531091

10541092
def _validate_coerce_subplot_type(subplot_type):
1055-
10561093
# Lowercase subplot_type
10571094
orig_subplot_type = subplot_type
10581095
subplot_type = subplot_type.lower()
@@ -1200,7 +1237,6 @@ def _build_subplot_title_annotations(
12001237

12011238

12021239
def _build_grid_str(specs, grid_ref, insets, insets_ref, row_seq):
1203-
12041240
# Compute rows and columns
12051241
rows = len(specs)
12061242
cols = len(specs[0])
@@ -1257,7 +1293,6 @@ def _pad(s, cell_len=cell_len):
12571293
# Loop through specs, fill in _tmp
12581294
for r, spec_row in enumerate(specs):
12591295
for c, spec in enumerate(spec_row):
1260-
12611296
ref = grid_ref[r][c]
12621297
if ref is None:
12631298
if _tmp[r][c] == "":
@@ -1339,7 +1374,6 @@ def _pad(s, cell_len=cell_len):
13391374

13401375

13411376
def _set_trace_grid_reference(trace, layout, grid_ref, row, col, secondary_y=False):
1342-
13431377
if row <= 0:
13441378
raise Exception(
13451379
"Row value is out of range. " "Note: the starting cell is (1, 1)"
@@ -1461,7 +1495,6 @@ def _get_grid_subplot(fig, row, col, secondary_y=False):
14611495

14621496

14631497
def _get_subplot_ref_for_trace(trace):
1464-
14651498
if "domain" in trace:
14661499
return SubplotRef(
14671500
subplot_type="domain",

‎packages/python/plotly/plotly/express/_core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ def make_trace_kwargs(args, trace_spec, trace_data, mapping_labels, sizeref):
268268
fit information to be used for trendlines
269269
"""
270270
if "line_close" in args and args["line_close"]:
271-
trace_data = trace_data.append(trace_data.iloc[0])
271+
trace_data = pd.concat([trace_data, trace_data.iloc[:1]])
272272
trace_patch = trace_spec.trace_patch.copy() or {}
273273
fit_results = None
274274
hover_header = ""

‎packages/python/plotly/plotly/matplotlylib/mplexporter/renderers/vega_renderer.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,18 @@ def open_axes(self, ax, props):
2323
dict(type="y", scale="y", ticks=10),
2424
]
2525
self.scales = [
26-
dict(name="x", domain=props["xlim"], type="linear", range="width",),
27-
dict(name="y", domain=props["ylim"], type="linear", range="height",),
26+
dict(
27+
name="x",
28+
domain=props["xlim"],
29+
type="linear",
30+
range="width",
31+
),
32+
dict(
33+
name="y",
34+
domain=props["ylim"],
35+
type="linear",
36+
range="height",
37+
),
2838
]
2939

3040
def draw_line(self, data, coordinates, style, label, mplobj=None):
@@ -103,7 +113,7 @@ def __init__(self, renderer):
103113

104114
def html(self):
105115
"""Build the HTML representation for IPython."""
106-
id = random.randint(0, 2 ** 16)
116+
id = random.randint(0, 2**16)
107117
html = '<div id="vis%d"></div>' % id
108118
html += "<script>\n"
109119
html += VEGA_TEMPLATE % (json.dumps(self.specification), id)

‎packages/python/plotly/plotly/matplotlylib/mplexporter/tests/test_basic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ def test_path():
146146

147147

148148
def test_Figure():
149-
""" if the fig is not associated with a canvas, FakeRenderer shall
150-
not fail. """
149+
"""if the fig is not associated with a canvas, FakeRenderer shall
150+
not fail."""
151151
fig = plt.Figure()
152152
ax = fig.add_subplot(111)
153153
ax.add_patch(plt.Circle((0, 0), 1))

‎packages/python/plotly/plotly/tests/test_core/test_subplots/test_make_subplots.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,22 @@ def test_specs_padding(self):
660660
)
661661
self.assertEqual(fig.to_plotly_json(), expected.to_plotly_json())
662662

663+
def test_specs_rounding_rounds_down(self):
664+
n_subplots = 8
665+
padding_size = 0.2
666+
667+
specs = []
668+
for _ in range(n_subplots):
669+
specs.append([{"b": padding_size / 2.0, "t": padding_size / 2.0}])
670+
671+
fig = subplots.make_subplots(rows=n_subplots, specs=specs)
672+
self.assertTrue(
673+
all(
674+
fig.layout[f"yaxis{i if i > 1 else ''}"]["domain"][0] <= 1.0
675+
for i in range(1, n_subplots + 1)
676+
)
677+
)
678+
663679
def test_specs_padding_bottom_left(self):
664680
expected = Figure(
665681
data=Data(),
@@ -1592,7 +1608,6 @@ def test_large_columns_no_errors(self):
15921608
)
15931609

15941610
def test_row_width_and_column_width(self):
1595-
15961611
expected = Figure(
15971612
{
15981613
"data": [],
@@ -1680,7 +1695,6 @@ def test_row_width_and_column_width(self):
16801695
self.assertEqual(fig.to_plotly_json(), expected.to_plotly_json())
16811696

16821697
def test_row_width_and_shared_yaxes(self):
1683-
16841698
expected = Figure(
16851699
{
16861700
"data": [],

‎packages/python/plotly/plotly/tests/test_orca/images/linux/fig1.eps

Lines changed: 1031 additions & 919 deletions
Large diffs are not rendered by default.

‎packages/python/plotly/plotly/tests/test_orca/images/linux/latexfig.eps

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
%!PS-Adobe-3.0 EPSF-3.0
2-
%Produced by poppler pdftops version: 0.71.0 (http://poppler.freedesktop.org)
2+
%Produced by poppler pdftops version: 22.02.0 (http://poppler.freedesktop.org)
33
%%Creator: Chromium
44
%%LanguageLevel: 2
55
%%DocumentSuppliedResources: (atend)

‎packages/python/plotly/plotly/tests/test_orca/images/linux/topofig.eps

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
%!PS-Adobe-3.0 EPSF-3.0
2-
%Produced by poppler pdftops version: 0.71.0 (http://poppler.freedesktop.org)
2+
%Produced by poppler pdftops version: 22.02.0 (http://poppler.freedesktop.org)
33
%%Creator: Chromium
44
%%LanguageLevel: 2
55
%%DocumentSuppliedResources: (atend)

‎packages/python/plotly/recipe/meta.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ requirements:
2121
- python
2222
- pip
2323
- jupyterlab =3
24-
- nodejs
24+
- nodejs =16
2525
- setuptools
2626
run:
2727
- python
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
requests==2.12.4
22
tenacity==6.2.0
33
pytest==3.5.1
4+
packaging

‎packages/python/plotly/test_requirements/requirements_39_pandas_2_optional.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
requests==2.25.1
22
tenacity==6.2.0
3-
pandas==2.0.0
3+
pandas==2.0.1
44
numpy==1.20.3
55
xarray==0.17.0
66
statsmodels

‎release.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Manually update the versions to `X.Y.Z` in the files specified below.
3535

3636
- `CHANGELOG.md`
3737
+ update the release date
38-
- `packages/python/plotly/README.md`
38+
- `README.md`
3939
+ this must be done at this point because the README gets baked into PyPI
4040
- `plotly/_widget_version.py`:
4141
+ Update `__frontend_version__` to `^X.Y.Z` (Note the `^` prefix)

‎test/percy/compare-pandas.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import difflib
2+
import json
3+
import os
4+
5+
os.chdir(os.path.dirname(__file__))
6+
7+
8+
def clean_float(numstr):
9+
# round numbers to 3 digits, to remove floating-point differences
10+
return round(float(numstr), 3)
11+
12+
13+
def get_fig(html):
14+
# strip off all the rest of the html and js
15+
fig_str = html[html.index("[{", html.rindex("Plotly.newPlot(")) :]
16+
fig_str = fig_str[: fig_str.index("} ") + 1]
17+
data, layout, config = json.loads(f"[{fig_str}]", parse_float=clean_float)
18+
fig_dict = dict(data=data, layout=layout, config=config)
19+
return json.dumps(fig_dict, indent=2).splitlines(keepends=True)
20+
21+
22+
for filename in os.listdir("pandas2"):
23+
with open(filename, encoding="utf-8") as f1:
24+
with open(os.path.join("pandas2", filename)) as f2:
25+
fig1 = get_fig(f1.read())
26+
fig2 = get_fig(f2.read())
27+
if any(l1 != l2 for l1, l2 in zip(fig1, fig2)):
28+
print("".join(difflib.unified_diff(fig1, fig2)))
29+
raise ValueError(f"Pandas 1/2 difference in {filename}")

‎test/percy/snapshots.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
version: 2
2+
static:
3+
options:
4+
waitForTimeout: 6000
5+
execute:
6+
beforeSnapshot: |
7+
const stash = window._canvasStash = [];
8+
Array.from(document.querySelectorAll('canvas')).forEach(c => {
9+
const i = document.createElement('img');
10+
i.src = c.toDataURL();
11+
i.width = c.width;
12+
i.height = c.height;
13+
i.setAttribute('style', c.getAttribute('style'));
14+
i.className = c.className;
15+
i.setAttribute('data-canvasnum', stash.length);
16+
stash.push(c);
17+
c.parentElement.insertBefore(i, c);
18+
c.parentElement.removeChild(c);
19+
});
20+
snapshot:
21+
widths:
22+
- 1280

0 commit comments

Comments
 (0)
Please sign in to comment.