From aedd67ae6768ffad31740802dcb2be61b96e3d4e Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Thu, 4 May 2023 19:37:41 -0400 Subject: [PATCH 1/7] add a test that should fail since px doesn't support pandas 2 --- .circleci/config.yml | 16 +++++++++++++++- .gitignore | 1 + test/percy/compare-pandas.py | 8 ++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/percy/compare-pandas.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 3ce58a1eacd..bcf4700800b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -92,7 +92,21 @@ commands: cd packages/python/plotly . venv/bin/activate pytest -x test_init/test_lazy_imports.py - + - run: + name: Test PX if Pandas 2 + command: | + if [ "<>" == "39_pandas_2" ]; then + . packages/python/plotly/venv/bin/activate + pip install -e ./packages/python/plotly + pip install -e ./packages/python/plotly-geo + python test/percy/plotly-express.py + mkdir test/percy/pandas2 + mv test/percy/*.html test/percy/pandas2/ + # 1.1 is the earliest minor with Py3.9 wheels + pip install "pandas==1.1.5" + python test/percy/plotly-express.py + python test/percy/compare-pandas.py + fi test_orca: parameters: py: diff --git a/.gitignore b/.gitignore index 1be270ceac4..ccfd2b4e518 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,4 @@ packages/python/plotly/jupyterlab_plotly/labextension/ packages/python/plotly/jupyterlab_plotly/nbextension/index.js* test/percy/*.html +test/percy/pandas2/*.html diff --git a/test/percy/compare-pandas.py b/test/percy/compare-pandas.py new file mode 100644 index 00000000000..a1e11ae033c --- /dev/null +++ b/test/percy/compare-pandas.py @@ -0,0 +1,8 @@ +import os + +os.chdir(os.path.dirname(__file__)) + +for filename in os.listdir("pandas2"): + with open(filename, encoding="utf-8") as f: + with open(os.path.join("pandas2", filename)) as f2: + assert f.read() == f2.read(), f"Pandas 1/2 difference in {filename}" From efd4047b309c1dcbf45187fa1e7a296508eceb74 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Thu, 4 May 2023 19:56:18 -0400 Subject: [PATCH 2/7] move px pandas2 test to percy test, and update it to Py3.9 --- .circleci/config.yml | 32 ++++++++----------- .../requirements_39_pandas_2_optional.txt | 2 +- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bcf4700800b..31b72ea68c2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -92,21 +92,6 @@ commands: cd packages/python/plotly . venv/bin/activate pytest -x test_init/test_lazy_imports.py - - run: - name: Test PX if Pandas 2 - command: | - if [ "<>" == "39_pandas_2" ]; then - . packages/python/plotly/venv/bin/activate - pip install -e ./packages/python/plotly - pip install -e ./packages/python/plotly-geo - python test/percy/plotly-express.py - mkdir test/percy/pandas2 - mv test/percy/*.html test/percy/pandas2/ - # 1.1 is the earliest minor with Py3.9 wheels - pip install "pandas==1.1.5" - python test/percy/plotly-express.py - python test/percy/compare-pandas.py - fi test_orca: parameters: py: @@ -245,7 +230,7 @@ jobs: # Percy python_37_percy: docker: - - image: cimg/python:3.7-browsers + - image: cimg/python:3.9-browsers environment: PERCY_ENABLED: True PERCY_PROJECT: plotly/plotly.py @@ -267,18 +252,29 @@ jobs: pip install --upgrade pip wheel pip install -e ./packages/python/plotly pip install -e ./packages/python/plotly-geo - pip install -r ./packages/python/plotly/test_requirements/requirements_37_optional.txt + pip install -r ./packages/python/plotly/test_requirements/requirements_39_pandas_2_optional.txt + - run: + name: Build html figures (Pandas 2) + command: | + . venv/bin/activate + python test/percy/plotly-express.py - run: - name: Build html figures + name: Build html figures (Pandas 1) and compare command: | . venv/bin/activate + mkdir test/percy/pandas2 + mv test/percy/*.html test/percy/pandas2/ + # 1.1 is the earliest minor with Py3.9 wheels + pip install "pandas==1.1.5" python test/percy/plotly-express.py + python test/percy/compare-pandas.py - run: name: Run percy snapshots command: | npm i @percy/cli npx percy snapshot -c test/percy/snapshots.yml test/percy/ rm test/percy/*.html + rm -rf test/percy/pandas2 # Chart studio python_37_chart_studio: diff --git a/packages/python/plotly/test_requirements/requirements_39_pandas_2_optional.txt b/packages/python/plotly/test_requirements/requirements_39_pandas_2_optional.txt index 7132d8a6340..acb9752ac16 100644 --- a/packages/python/plotly/test_requirements/requirements_39_pandas_2_optional.txt +++ b/packages/python/plotly/test_requirements/requirements_39_pandas_2_optional.txt @@ -1,6 +1,6 @@ requests==2.25.1 tenacity==6.2.0 -pandas==2.0.0 +pandas==2.0.1 numpy==1.20.3 xarray==0.17.0 statsmodels From a8af752b16517ee52439341c364bddb2ca1c4dcd Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Thu, 4 May 2023 22:14:19 -0400 Subject: [PATCH 3/7] pandas append -> concat --- packages/python/plotly/plotly/express/_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 39dabba6351..76ab33c90fa 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -268,7 +268,7 @@ def make_trace_kwargs(args, trace_spec, trace_data, mapping_labels, sizeref): fit information to be used for trendlines """ if "line_close" in args and args["line_close"]: - trace_data = trace_data.append(trace_data.iloc[0]) + trace_data = pd.concat([trace_data, trace_data.iloc[:1]]) trace_patch = trace_spec.trace_patch.copy() or {} fit_results = None hover_header = "" From 06d0360a58aa7f54df14f070e08f96463d6de112 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Thu, 4 May 2023 22:25:23 -0400 Subject: [PATCH 4/7] changelog entry for pandas2 px line_close fix --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0019b2ccc65..78a9966375c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [UNRELEASED] + +### Fixed + - Fixed another compatibility issue with Pandas 2.0, just affecting `px.*(line_close=True)` [[#4190](https://github.com/plotly/plotly.py/pull/4190)] + ## [5.14.1] - 2023-04-05 ### Fixed From 9c04542ee7c8d3554a2ff5795a07915811a84085 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Fri, 5 May 2023 09:45:35 -0400 Subject: [PATCH 5/7] pandas 1/2 px comparison: looser equality of just the figure spec --- .circleci/config.yml | 2 ++ test/percy/compare-pandas.py | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 31b72ea68c2..d9dae38d2ff 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -275,6 +275,8 @@ jobs: npx percy snapshot -c test/percy/snapshots.yml test/percy/ rm test/percy/*.html rm -rf test/percy/pandas2 + - store_artifacts: + path: test/percy # Chart studio python_37_chart_studio: diff --git a/test/percy/compare-pandas.py b/test/percy/compare-pandas.py index a1e11ae033c..0ed3db3826a 100644 --- a/test/percy/compare-pandas.py +++ b/test/percy/compare-pandas.py @@ -1,8 +1,26 @@ +import difflib +import json import os os.chdir(os.path.dirname(__file__)) +def clean_float(numstr): + # round numbers to 3 digits, to remove floating-point differences + return round(float(numstr), 3) + +def get_fig(html): + # strip off all the rest of the html and js + fig_str = html[html.index('[{', html.rindex('Plotly.newPlot(')):] + fig_str = fig_str[:fig_str.index('} ') + 1] + data, layout, config = json.loads(f'[{fig_str}]', parse_float=clean_float) + fig_dict = dict(data=data, layout=layout, config=config) + return json.dumps(fig_dict, indent=2).splitlines(keepends=True) + for filename in os.listdir("pandas2"): - with open(filename, encoding="utf-8") as f: + with open(filename, encoding="utf-8") as f1: with open(os.path.join("pandas2", filename)) as f2: - assert f.read() == f2.read(), f"Pandas 1/2 difference in {filename}" + fig1 = get_fig(f1.read()) + fig2 = get_fig(f2.read()) + if any(l1 != l2 for l1, l2 in zip(fig1, fig2)): + print(''.join(difflib.unified_diff(fig1, fig2))) + raise ValueError(f"Pandas 1/2 difference in {filename}") From 810dca9600c97a4ffd1bb582bca5314a3bb3988d Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Fri, 5 May 2023 09:52:22 -0400 Subject: [PATCH 6/7] black compare-pandas --- test/percy/compare-pandas.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/percy/compare-pandas.py b/test/percy/compare-pandas.py index 0ed3db3826a..ded4e16ffef 100644 --- a/test/percy/compare-pandas.py +++ b/test/percy/compare-pandas.py @@ -4,23 +4,26 @@ os.chdir(os.path.dirname(__file__)) + def clean_float(numstr): # round numbers to 3 digits, to remove floating-point differences return round(float(numstr), 3) + def get_fig(html): # strip off all the rest of the html and js - fig_str = html[html.index('[{', html.rindex('Plotly.newPlot(')):] - fig_str = fig_str[:fig_str.index('} ') + 1] - data, layout, config = json.loads(f'[{fig_str}]', parse_float=clean_float) + fig_str = html[html.index("[{", html.rindex("Plotly.newPlot(")) :] + fig_str = fig_str[: fig_str.index("} ") + 1] + data, layout, config = json.loads(f"[{fig_str}]", parse_float=clean_float) fig_dict = dict(data=data, layout=layout, config=config) return json.dumps(fig_dict, indent=2).splitlines(keepends=True) + for filename in os.listdir("pandas2"): with open(filename, encoding="utf-8") as f1: with open(os.path.join("pandas2", filename)) as f2: fig1 = get_fig(f1.read()) fig2 = get_fig(f2.read()) if any(l1 != l2 for l1, l2 in zip(fig1, fig2)): - print(''.join(difflib.unified_diff(fig1, fig2))) + print("".join(difflib.unified_diff(fig1, fig2))) raise ValueError(f"Pandas 1/2 difference in {filename}") From 284e9bc7e27d4c844b6c74c104f0a69cfd62fccb Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Fri, 5 May 2023 10:12:10 -0400 Subject: [PATCH 7/7] remove pandas2 images so percy doesn't try to run them --- .circleci/config.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d9dae38d2ff..be8a88c814e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -268,15 +268,13 @@ jobs: pip install "pandas==1.1.5" python test/percy/plotly-express.py python test/percy/compare-pandas.py + rm -rf test/percy/pandas2 - run: name: Run percy snapshots command: | npm i @percy/cli npx percy snapshot -c test/percy/snapshots.yml test/percy/ rm test/percy/*.html - rm -rf test/percy/pandas2 - - store_artifacts: - path: test/percy # Chart studio python_37_chart_studio: