From f108db7bbac8ee8942f95308398140c06e2f66fb Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 10:32:29 -0500 Subject: [PATCH 01/33] add 3.10 tests, remove 3.6 + 3.7 --- .circleci/config.yml | 65 +++++++------------ .../requirements_310_core.txt | 3 + .../requirements_310_optional.txt | 22 +++++++ 3 files changed, 50 insertions(+), 40 deletions(-) create mode 100644 packages/python/plotly/test_requirements/requirements_310_core.txt create mode 100644 packages/python/plotly/test_requirements/requirements_310_optional.txt diff --git a/.circleci/config.yml b/.circleci/config.yml index ef17bac91d7..c8e836975f1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ commands: test_core: parameters: py: - default: "36" + default: "310" type: string steps: - checkout @@ -32,7 +32,7 @@ commands: test_optional: parameters: py: - default: "36" + default: "310" type: string steps: - checkout @@ -95,7 +95,7 @@ commands: test_orca: parameters: py: - default: "36" + default: "310" type: string steps: - checkout @@ -153,20 +153,6 @@ jobs: black --check . --exclude venv # Core - python_36_core: - docker: - - image: cimg/python:3.6-browsers - steps: - - test_core: - py: "36" - - python_37_core: - docker: - - image: cimg/python:3.7-browsers - steps: - - test_core: - py: "37" - python_38_core: docker: - image: cimg/python:3.8-browsers @@ -181,20 +167,14 @@ jobs: - test_core: py: "39" - # Optional - python_36_optional: + python_310_core: docker: - - image: cimg/python:3.6-browsers + - image: cimg/python:3.10-browsers steps: - - test_optional: - py: "36" + - test_core: + py: "310" - python_37_optional: - docker: - - image: cimg/python:3.7-browsers - steps: - - test_optional: - py: "37" + # Optional python_38_optional: docker: @@ -210,6 +190,13 @@ jobs: - test_optional: py: "39" + python_310_optional: + docker: + - image: cimg/python:3.10-browsers + steps: + - test_optional: + py: "310" + # Pandas python_39_pandas_2_optional: @@ -228,7 +215,7 @@ jobs: py: "38" # Percy - python_37_percy: + python_39_percy: docker: - image: cimg/python:3.9-browsers environment: @@ -277,9 +264,9 @@ jobs: rm test/percy/*.html # Chart studio - python_37_chart_studio: + python_38_chart_studio: docker: - - image: cimg/python:3.7 + - image: cimg/python:3.8 resource_class: large steps: @@ -291,7 +278,7 @@ jobs: python -m venv venv . venv/bin/activate pip install --upgrade pip wheel - pip install -r ./test_requirements/requirements_37.txt + pip install -r ./test_requirements/requirements_38.txt - run: name: Tests command: | @@ -302,7 +289,7 @@ jobs: plotlyjs_dev_build: docker: - - image: cimg/python:3.7-node + - image: cimg/python:3.8-node environment: LANG: en_US.UTF-8 resource_class: large @@ -316,7 +303,7 @@ jobs: python -m venv venv . venv/bin/activate pip install --upgrade pip wheel - pip install -r ./test_requirements/requirements_37_core.txt black inflect + pip install -r ./test_requirements/requirements_38_core.txt black inflect pip install jupyterlab~=3.0 - run: name: Update jupyterlab-plotly version @@ -433,7 +420,7 @@ jobs: docker: # specify the version you desire here # use `-browsers` prefix for selenium tests, for example, `3.6.1-browsers` - - image: cimg/python:3.7-browsers + - image: cimg/python:3.10-browsers steps: - add_ssh_keys: @@ -570,15 +557,13 @@ workflows: build: jobs: - - python_36_core - - python_37_core - python_38_core - python_39_core - - python_36_optional - - python_37_optional + - python_310_core - python_38_optional - python_39_optional + - python_310_optional - python_39_pandas_2_optional - python_38_orca - - python_37_percy + - python_39_percy - build-doc diff --git a/packages/python/plotly/test_requirements/requirements_310_core.txt b/packages/python/plotly/test_requirements/requirements_310_core.txt new file mode 100644 index 00000000000..fcacda06c79 --- /dev/null +++ b/packages/python/plotly/test_requirements/requirements_310_core.txt @@ -0,0 +1,3 @@ +requests==2.25.1 +tenacity==6.2.0 +pytest==7.4.4 diff --git a/packages/python/plotly/test_requirements/requirements_310_optional.txt b/packages/python/plotly/test_requirements/requirements_310_optional.txt new file mode 100644 index 00000000000..0086eac0f81 --- /dev/null +++ b/packages/python/plotly/test_requirements/requirements_310_optional.txt @@ -0,0 +1,22 @@ +requests==2.25.1 +tenacity==6.2.0 +pandas==1.5.3 +numpy==1.23.0 +xarray==0.17.0 +statsmodels +Pillow==10.2.0 +pytest==7.4.4 +pytz==2023.3.post1 +ipython[all]==7.22.0 +ipywidgets==8.0.2 +ipykernel==5.5.3 +jupyter==1.0.0 +scipy==1.11.4 +Shapely==1.8.5 +geopandas==0.9.0 +pyshp==2.1.3 +matplotlib==3.8.0 +scikit-image==0.22.0 +psutil==5.7.0 +kaleido +orjson==3.8.12 From 4fc892e48f3ed8298451e935c23711c3ee7f53f4 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 12:33:16 -0500 Subject: [PATCH 02/33] check only for near equality --- .../test_figure_factory/test_figure_factory.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index 8783dce1ab4..4dbe0abfb38 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -4310,6 +4310,17 @@ def test_optional_arguments(self): class TestHexbinMapbox(NumpyTestUtilsMixin, TestCaseNoTemplate): + def assert_dict_equal(self, dict1, dict2, decimal=7): + for k, v in dict1.items(): + if isinstance(v, dict): + assert_dict_almost_equal(v, dict2[k], decimal=decimal) + elif isinstance(v, float): + np.testing.assert_almost_equal(v, dict2[k], decimal=decimal) + else: + assert ( + v == dict2[k] + ), f"Values for key {k} are not equal: {v} != {dict2[k]}" + def test_aggregation(self): lat = [0, 1, 1, 2, 4, 5, 1, 2, 4, 5, 2, 3, 2, 1, 5, 3, 5] From 6391f3f695a98720b0f996abc582aa90e6ed483d Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 12:42:47 -0500 Subject: [PATCH 03/33] fix function call --- .../test_optional/test_figure_factory/test_figure_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index 4dbe0abfb38..50534954c85 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -4313,7 +4313,7 @@ class TestHexbinMapbox(NumpyTestUtilsMixin, TestCaseNoTemplate): def assert_dict_equal(self, dict1, dict2, decimal=7): for k, v in dict1.items(): if isinstance(v, dict): - assert_dict_almost_equal(v, dict2[k], decimal=decimal) + assert_dict_equal(self, v, dict2[k], decimal=decimal) elif isinstance(v, float): np.testing.assert_almost_equal(v, dict2[k], decimal=decimal) else: From b40f5e43101f20f57648347d054cd1668d593be9 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 12:42:58 -0500 Subject: [PATCH 04/33] add py311 tests --- .circleci/config.yml | 14 ++++++++++++ .../requirements_311_core.txt | 3 +++ .../requirements_311_optional.txt | 22 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 packages/python/plotly/test_requirements/requirements_311_core.txt create mode 100644 packages/python/plotly/test_requirements/requirements_311_optional.txt diff --git a/.circleci/config.yml b/.circleci/config.yml index c8e836975f1..725f6f639c9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -174,6 +174,13 @@ jobs: - test_core: py: "310" + python_311_core: + docker: + - image: cimg/python:3.11-browsers + steps: + - test_core: + py: "311" + # Optional python_38_optional: @@ -197,6 +204,13 @@ jobs: - test_optional: py: "310" + python_311_optional: + docker: + - image: cimg/python:3.11-browsers + steps: + - test_optional: + py: "311" + # Pandas python_39_pandas_2_optional: diff --git a/packages/python/plotly/test_requirements/requirements_311_core.txt b/packages/python/plotly/test_requirements/requirements_311_core.txt new file mode 100644 index 00000000000..fcacda06c79 --- /dev/null +++ b/packages/python/plotly/test_requirements/requirements_311_core.txt @@ -0,0 +1,3 @@ +requests==2.25.1 +tenacity==6.2.0 +pytest==7.4.4 diff --git a/packages/python/plotly/test_requirements/requirements_311_optional.txt b/packages/python/plotly/test_requirements/requirements_311_optional.txt new file mode 100644 index 00000000000..dda98f32cf1 --- /dev/null +++ b/packages/python/plotly/test_requirements/requirements_311_optional.txt @@ -0,0 +1,22 @@ +requests==2.25.1 +tenacity==6.2.0 +pandas==1.5.3 +numpy==1.23.2 +xarray==0.17.0 +statsmodels +Pillow==10.2.0 +pytest==7.4.4 +pytz==2023.3.post1 +ipython[all]==7.22.0 +ipywidgets==8.0.2 +ipykernel==5.5.3 +jupyter==1.0.0 +scipy==1.11.4 +Shapely==1.8.5 +geopandas==0.9.0 +pyshp==2.1.3 +matplotlib==3.8.0 +scikit-image==0.22.0 +psutil==5.7.0 +kaleido +orjson==3.8.12 From d8bb3b2a4a2d4f1796063d5c0a7dadbd12c428c4 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 12:45:09 -0500 Subject: [PATCH 05/33] add python 3.11 in workflows --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 725f6f639c9..bb0a59c3cde 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -574,9 +574,11 @@ workflows: - python_38_core - python_39_core - python_310_core + - python_311_core - python_38_optional - python_39_optional - python_310_optional + - python_311_optional - python_39_pandas_2_optional - python_38_orca - python_39_percy From ab92c7dd95596c1b9240a1f70711a2289fd3e986 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 12:57:10 -0500 Subject: [PATCH 06/33] fix function call --- .../test_figure_factory/test_figure_factory.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index 50534954c85..7e5054737b2 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -4310,10 +4310,10 @@ def test_optional_arguments(self): class TestHexbinMapbox(NumpyTestUtilsMixin, TestCaseNoTemplate): - def assert_dict_equal(self, dict1, dict2, decimal=7): + def assert_dict_almost_equal(self, dict1, dict2, decimal=7): for k, v in dict1.items(): if isinstance(v, dict): - assert_dict_equal(self, v, dict2[k], decimal=decimal) + assert_dict_almost_equal(self, v, dict2[k], decimal=decimal) elif isinstance(v, float): np.testing.assert_almost_equal(v, dict2[k], decimal=decimal) else: @@ -4427,7 +4427,7 @@ def test_aggregation(self): actual_agg = [2.0, 2.0, 1.0, 3.0, 9.0] - self.assert_dict_equal(fig1.data[0].geojson, actual_geojson) + self.assert_dict_almost_equal(self, fig1.data[0].geojson, actual_geojson) assert np.array_equal(fig1.data[0].z, actual_agg) fig2 = ff.create_hexbin_mapbox( From 2f6a186a5187feaed8c941e879e6ed54496dd7d2 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 13:00:38 -0500 Subject: [PATCH 07/33] update for python 3.11 and later --- .../tests/test_core/test_errors/test_dict_path_errors.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/tests/test_core/test_errors/test_dict_path_errors.py b/packages/python/plotly/plotly/tests/test_core/test_errors/test_dict_path_errors.py index 8b899a6f5a3..c0c9a173203 100644 --- a/packages/python/plotly/plotly/tests/test_core/test_errors/test_dict_path_errors.py +++ b/packages/python/plotly/plotly/tests/test_core/test_errors/test_dict_path_errors.py @@ -1,6 +1,7 @@ import plotly.graph_objects as go from _plotly_utils.exceptions import PlotlyKeyError import pytest +import sys def error_substr(s, r): @@ -400,9 +401,11 @@ def test_described_subscript_error_on_type_error(some_fig): except ValueError as e: raised = True print(e.args[0]) + # Error is different in Python 3.11 and later + error_addition_py_311 = ", not 'str'" if sys.version_info >= (3, 11, 0) else "" e_substr = error_substr( e.args[0], - """string indices must be integers + f"""string indices must be integers{error_addition_py_311} Invalid value received for the 'plot_bgcolor' property of layout From 8185cc571181ab809d5351d6ec4583497058b799 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 13:20:51 -0500 Subject: [PATCH 08/33] Update test_figure_factory.py --- .../test_optional/test_figure_factory/test_figure_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index 7e5054737b2..68504d3af19 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -4427,7 +4427,7 @@ def test_aggregation(self): actual_agg = [2.0, 2.0, 1.0, 3.0, 9.0] - self.assert_dict_almost_equal(self, fig1.data[0].geojson, actual_geojson) + self.assert_dict_almost_equal(fig1.data[0].geojson, actual_geojson) assert np.array_equal(fig1.data[0].z, actual_agg) fig2 = ff.create_hexbin_mapbox( From 4f5006bb37d75f02021009f8222c8a55277beeb7 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 13:35:39 -0500 Subject: [PATCH 09/33] Update test_figure_factory.py --- .../test_figure_factory/test_figure_factory.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index 68504d3af19..e96aff46cb4 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -4313,7 +4313,17 @@ class TestHexbinMapbox(NumpyTestUtilsMixin, TestCaseNoTemplate): def assert_dict_almost_equal(self, dict1, dict2, decimal=7): for k, v in dict1.items(): if isinstance(v, dict): - assert_dict_almost_equal(self, v, dict2[k], decimal=decimal) + self.assert_dict_almost_equal(v, dict2[k], decimal=decimal) + elif isinstance(v, list): + for i in range(len(v)): + if isinstance(v[i], float): + np.testing.assert_almost_equal( + v[i], dict2[k][i], decimal=decimal + ) + else: + assert ( + v[i] == dict2[k][i] + ), f"Values at index {i} for key {k} are not equal: {v[i]} != {dict2[k][i]}" elif isinstance(v, float): np.testing.assert_almost_equal(v, dict2[k], decimal=decimal) else: From f86e0fb931b692b49807887e53be7cfd2b54348d Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 13:41:25 -0500 Subject: [PATCH 10/33] add statsmodels version --- .../plotly/test_requirements/requirements_310_optional.txt | 2 +- .../plotly/test_requirements/requirements_311_optional.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/python/plotly/test_requirements/requirements_310_optional.txt b/packages/python/plotly/test_requirements/requirements_310_optional.txt index 0086eac0f81..105eda9b252 100644 --- a/packages/python/plotly/test_requirements/requirements_310_optional.txt +++ b/packages/python/plotly/test_requirements/requirements_310_optional.txt @@ -3,7 +3,7 @@ tenacity==6.2.0 pandas==1.5.3 numpy==1.23.0 xarray==0.17.0 -statsmodels +statsmodels==0.14.1 Pillow==10.2.0 pytest==7.4.4 pytz==2023.3.post1 diff --git a/packages/python/plotly/test_requirements/requirements_311_optional.txt b/packages/python/plotly/test_requirements/requirements_311_optional.txt index dda98f32cf1..800dbeb6a25 100644 --- a/packages/python/plotly/test_requirements/requirements_311_optional.txt +++ b/packages/python/plotly/test_requirements/requirements_311_optional.txt @@ -3,7 +3,7 @@ tenacity==6.2.0 pandas==1.5.3 numpy==1.23.2 xarray==0.17.0 -statsmodels +statsmodels==0.14.1 Pillow==10.2.0 pytest==7.4.4 pytz==2023.3.post1 From fc42fdaba14c79fcc30e6ba95b9ce3aa8389016a Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 13:41:41 -0500 Subject: [PATCH 11/33] add python 3.12 tests --- .circleci/config.yml | 16 ++++++++++++++ .../requirements_312_core.txt | 3 +++ .../requirements_312_optional.txt | 22 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 packages/python/plotly/test_requirements/requirements_312_core.txt create mode 100644 packages/python/plotly/test_requirements/requirements_312_optional.txt diff --git a/.circleci/config.yml b/.circleci/config.yml index bb0a59c3cde..2aef00687fa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -181,6 +181,13 @@ jobs: - test_core: py: "311" + python_312_core: + docker: + - image: cimg/python:3.12-browsers + steps: + - test_core: + py: "312" + # Optional python_38_optional: @@ -211,6 +218,13 @@ jobs: - test_optional: py: "311" + python_312_optional: + docker: + - image: cimg/python:3.12-browsers + steps: + - test_optional: + py: "312" + # Pandas python_39_pandas_2_optional: @@ -575,10 +589,12 @@ workflows: - python_39_core - python_310_core - python_311_core + - python_312_core - python_38_optional - python_39_optional - python_310_optional - python_311_optional + - python_312_optional - python_39_pandas_2_optional - python_38_orca - python_39_percy diff --git a/packages/python/plotly/test_requirements/requirements_312_core.txt b/packages/python/plotly/test_requirements/requirements_312_core.txt new file mode 100644 index 00000000000..fcacda06c79 --- /dev/null +++ b/packages/python/plotly/test_requirements/requirements_312_core.txt @@ -0,0 +1,3 @@ +requests==2.25.1 +tenacity==6.2.0 +pytest==7.4.4 diff --git a/packages/python/plotly/test_requirements/requirements_312_optional.txt b/packages/python/plotly/test_requirements/requirements_312_optional.txt new file mode 100644 index 00000000000..05185830b85 --- /dev/null +++ b/packages/python/plotly/test_requirements/requirements_312_optional.txt @@ -0,0 +1,22 @@ +requests==2.31.0 +tenacity==8.2.3 +pandas +numpy +xarray==2023.12.0 +statsmodels +Pillow==10.2.0 +pytest==7.4.4 +pytz==2023.3.post1 +ipython[all]==7.22.0 +ipywidgets<8 +ipykernel==5.5.3 +jupyter==1.0.0 +scipy==1.11.4 +Shapely==2.0.2 +geopandas==0.14.2 +pyshp==2.3.1 +matplotlib==3.8.2 +scikit-image==0.22.0 +psutil==5.9.7 +kaleido +orjson==3.9.10 \ No newline at end of file From bb73b70b5e239a8a1994ba3c76aec50ae1bb2a52 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 13:52:34 -0500 Subject: [PATCH 12/33] Update test_figure_factory.py --- .../test_figure_factory.py | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index e96aff46cb4..542d19cecd7 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -4310,20 +4310,24 @@ def test_optional_arguments(self): class TestHexbinMapbox(NumpyTestUtilsMixin, TestCaseNoTemplate): - def assert_dict_almost_equal(self, dict1, dict2, decimal=7): + def compare_list_values(self, list1, list2, decimal=7): + assert len(list1) == len(list2), "Lists are not of the same length." + for i in range(len(list1)): + if isinstance(list1[i], list): + self.compare_list_values(list1[i], list2[i], decimal=decimal) + elif isinstance(list1[i], float): + np.testing.assert_almost_equal(list1[i], list2[i], decimal=decimal) + else: + assert ( + list1[i] == list2[i] + ), f"Values at index {i} are not equal: {list1[i]} != {list2[i]}" + + def compare_dict_values(self, dict1, dict2, decimal=7): for k, v in dict1.items(): if isinstance(v, dict): - self.assert_dict_almost_equal(v, dict2[k], decimal=decimal) + self.compare_dict_values(v, dict2[k], decimal=decimal) elif isinstance(v, list): - for i in range(len(v)): - if isinstance(v[i], float): - np.testing.assert_almost_equal( - v[i], dict2[k][i], decimal=decimal - ) - else: - assert ( - v[i] == dict2[k][i] - ), f"Values at index {i} for key {k} are not equal: {v[i]} != {dict2[k][i]}" + self.compare_list_values(v, dict2[k], decimal=decimal) elif isinstance(v, float): np.testing.assert_almost_equal(v, dict2[k], decimal=decimal) else: @@ -4437,7 +4441,7 @@ def test_aggregation(self): actual_agg = [2.0, 2.0, 1.0, 3.0, 9.0] - self.assert_dict_almost_equal(fig1.data[0].geojson, actual_geojson) + self.compare_dict_values(fig1.data[0].geojson, actual_geojson) assert np.array_equal(fig1.data[0].z, actual_agg) fig2 = ff.create_hexbin_mapbox( From f51c371eb696c154849eb33a3c1b9ff5a71f205e Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 13:57:55 -0500 Subject: [PATCH 13/33] Update test_figure_factory.py --- .../test_optional/test_figure_factory/test_figure_factory.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py index 542d19cecd7..20a1b23f7ff 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_figure_factory/test_figure_factory.py @@ -4315,6 +4315,8 @@ def compare_list_values(self, list1, list2, decimal=7): for i in range(len(list1)): if isinstance(list1[i], list): self.compare_list_values(list1[i], list2[i], decimal=decimal) + elif isinstance(list1[i], dict): + self.compare_dict_values(list1[i], list2[i], decimal=decimal) elif isinstance(list1[i], float): np.testing.assert_almost_equal(list1[i], list2[i], decimal=decimal) else: From 3a229600660d94305a1fd5fc9cdc25dac073ba39 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 14:07:57 -0500 Subject: [PATCH 14/33] only run polars/vaex tests on 3.11 or earlier --- .../plotly/tests/test_optional/test_px/test_px_input.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py b/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py index 94382cb9e01..8f8de64a2de 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py @@ -7,6 +7,7 @@ import unittest.mock as mock from plotly.express._core import build_dataframe from pandas.testing import assert_frame_equal +import sys # Fixtures @@ -318,7 +319,8 @@ def __dataframe__(self): @pytest.mark.skipif( - version.parse(pd.__version__) < version.parse("2.0.2"), + version.parse(pd.__version__) < version.parse("2.0.2") + or sys.version_info >= (3, 12), reason="plotly doesn't use a dataframe interchange protocol for pandas < 2.0.2", ) @pytest.mark.parametrize("test_lib", ["vaex", "polars"]) @@ -339,7 +341,8 @@ def test_build_df_from_vaex_and_polars(test_lib): @pytest.mark.skipif( - version.parse(pd.__version__) < version.parse("2.0.2"), + version.parse(pd.__version__) < version.parse("2.0.2") + or sys.version_info >= (3, 12), reason="plotly doesn't use a dataframe interchange protocol for pandas < 2.0.2", ) @pytest.mark.parametrize("test_lib", ["vaex", "polars"]) From 315ccd44f2a2bef53f50bebd57e103156534c9e1 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 14:20:46 -0500 Subject: [PATCH 15/33] Update _county_choropleth.py --- .../plotly/plotly/figure_factory/_county_choropleth.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/python/plotly/plotly/figure_factory/_county_choropleth.py b/packages/python/plotly/plotly/figure_factory/_county_choropleth.py index 65c5e5ffede..62a921a3fc6 100644 --- a/packages/python/plotly/plotly/figure_factory/_county_choropleth.py +++ b/packages/python/plotly/plotly/figure_factory/_county_choropleth.py @@ -358,15 +358,15 @@ def _calculations( elif fips_polygon_map[f].type == "MultiPolygon": x = [ poly.simplify(simplify_county).exterior.xy[0].tolist() - for poly in fips_polygon_map[f] + for poly in fips_polygon_map[f].geoms ] y = [ poly.simplify(simplify_county).exterior.xy[1].tolist() - for poly in fips_polygon_map[f] + for poly in fips_polygon_map[f].geoms ] - x_c = [poly.centroid.xy[0].tolist() for poly in fips_polygon_map[f]] - y_c = [poly.centroid.xy[1].tolist() for poly in fips_polygon_map[f]] + x_c = [poly.centroid.xy[0].tolist() for poly in fips_polygon_map[f].geoms] + y_c = [poly.centroid.xy[1].tolist() for poly in fips_polygon_map[f].geoms] county_name_str = str(df[df["FIPS"] == f]["COUNTY_NAME"].iloc[0]) state_name_str = str(df[df["FIPS"] == f]["STATE_NAME"].iloc[0]) From c2c9c7d0674563cabad81b3d84b35fb051c472dc Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 14:28:15 -0500 Subject: [PATCH 16/33] update --- .../plotly/plotly/figure_factory/_county_choropleth.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/python/plotly/plotly/figure_factory/_county_choropleth.py b/packages/python/plotly/plotly/figure_factory/_county_choropleth.py index 62a921a3fc6..c646aa5b034 100644 --- a/packages/python/plotly/plotly/figure_factory/_county_choropleth.py +++ b/packages/python/plotly/plotly/figure_factory/_county_choropleth.py @@ -382,7 +382,7 @@ def _calculations( + "
Value: " + str(values[index]) ) - t_c = [text for poly in fips_polygon_map[f]] + t_c = [text for poly in fips_polygon_map[f].geoms] x_centroids = x_c + x_centroids y_centroids = y_c + y_centroids centroid_text = t_c + centroid_text @@ -853,11 +853,11 @@ def create_choropleth( elif df_state["geometry"][index].type == "MultiPolygon": x = [ poly.simplify(simplify_state).exterior.xy[0].tolist() - for poly in df_state["geometry"][index] + for poly in df_state["geometry"][index].geoms ] y = [ poly.simplify(simplify_state).exterior.xy[1].tolist() - for poly in df_state["geometry"][index] + for poly in df_state["geometry"][index].geoms ] for segment in range(len(x)): x_states = x_states + x[segment] From 635e933f8982bf2817bb09086a02ba3fdab74101 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 15:05:52 -0500 Subject: [PATCH 17/33] Update test_to_from_plotly_json.py --- .../plotly/plotly/tests/test_io/test_to_from_plotly_json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/tests/test_io/test_to_from_plotly_json.py b/packages/python/plotly/plotly/tests/test_io/test_to_from_plotly_json.py index ff8ad213c84..38bbcdaeceb 100644 --- a/packages/python/plotly/plotly/tests/test_io/test_to_from_plotly_json.py +++ b/packages/python/plotly/plotly/tests/test_io/test_to_from_plotly_json.py @@ -96,7 +96,7 @@ def numeric_numpy_array(request): @pytest.fixture(scope="module") def object_numpy_array(request): - return np.array(["a", 1, [2, 3]]) + return np.array(["a", 1, [2, 3]], dtype="object") @pytest.fixture(scope="module") From 709fb99179a5f2f200a70480f98f6f43e5e8a8f3 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 15:17:41 -0500 Subject: [PATCH 18/33] update docs requirements --- .circleci/config.yml | 2 +- doc/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2aef00687fa..18a1d5bbc71 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -448,7 +448,7 @@ jobs: docker: # specify the version you desire here # use `-browsers` prefix for selenium tests, for example, `3.6.1-browsers` - - image: cimg/python:3.10-browsers + - image: cimg/python:3.9-browsers steps: - add_ssh_keys: diff --git a/doc/requirements.txt b/doc/requirements.txt index 58ab8f22b22..0e4b2455ff6 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -4,7 +4,7 @@ ipywidgets==7.7.2 jupyter-client<7 jupyter notebook -pandas==1.0.3 +pandas==1.1.3 statsmodels==0.11.1 scipy==1.3.1 patsy==0.5.1 From f3b427a04f0e853d64380e7ff1d58ef86a4864a3 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 15:25:48 -0500 Subject: [PATCH 19/33] Update requirements.txt --- doc/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index 0e4b2455ff6..4d6e93465b0 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -5,7 +5,7 @@ jupyter-client<7 jupyter notebook pandas==1.1.3 -statsmodels==0.11.1 +statsmodels==0.12.1 scipy==1.3.1 patsy==0.5.1 numpy==1.19.5 From a2236ee72e292d66c64a5a4a1807d46b793afe09 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 15:32:54 -0500 Subject: [PATCH 20/33] Update requirements.txt --- doc/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index 4d6e93465b0..da70117479d 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -6,7 +6,7 @@ jupyter notebook pandas==1.1.3 statsmodels==0.12.1 -scipy==1.3.1 +scipy==1.5.4 patsy==0.5.1 numpy==1.19.5 plotly-geo From b4c3a70840ccca8c513806720b44b7e8636349cc Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 15:51:05 -0500 Subject: [PATCH 21/33] update docs page to use same versions as docs --- doc/python/county-choropleth.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/python/county-choropleth.md b/doc/python/county-choropleth.md index ffed5efedc6..1340b4a75ad 100644 --- a/doc/python/county-choropleth.md +++ b/doc/python/county-choropleth.md @@ -47,9 +47,9 @@ Run the following commands to install the correct versions of the following modu ```python !pip install plotly-geo==1.0.0 -!pip install geopandas==0.3.0 -!pip install pyshp==1.2.10 -!pip install shapely==1.6.3 +!pip install geopandas==0.8.1 +!pip install pyshp==2.1.2 +!pip install shapely==1.7.1 ``` If you are using Windows, follow this post to properly install geopandas and dependencies: http://geoffboeing.com/2014/09/using-geopandas-windows/. If you are using Anaconda, do not use PIP to install the packages above. Instead use conda to install them: From 5725d6d7d82a5e7aeedb42a29e16d663d3b4e14e Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 15:53:58 -0500 Subject: [PATCH 22/33] Update requirements.txt --- binder/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/binder/requirements.txt b/binder/requirements.txt index 38f2ca900a3..814206bdb34 100644 --- a/binder/requirements.txt +++ b/binder/requirements.txt @@ -2,8 +2,8 @@ jupytext plotly==5.18.0 jupyter notebook -pandas==1.0.3 -statsmodels==0.11.1 +pandas==1.1.3 +statsmodels==0.12.1 scipy patsy==0.5.1 numpy From 1dfcb3e5f3e775d39277e0b16d88927a22fe9011 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 15:56:09 -0500 Subject: [PATCH 23/33] Update requirements.txt --- doc/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index da70117479d..cf52351e9d4 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -25,7 +25,7 @@ sphinx_bootstrap_theme recommonmark pathlib python-frontmatter -datashader +datashader==0.14.4 pyarrow cufflinks==0.17.3 kaleido From e0b22d870a8a2ab5535c8c8d9f1716a4131199f4 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 15:59:46 -0500 Subject: [PATCH 24/33] Update ml-regression.md --- doc/python/ml-regression.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/python/ml-regression.md b/doc/python/ml-regression.md index 9b07a7a9851..b8be347943a 100644 --- a/doc/python/ml-regression.md +++ b/doc/python/ml-regression.md @@ -6,9 +6,9 @@ jupyter: extension: .md format_name: markdown format_version: '1.3' - jupytext_version: 1.14.1 + jupytext_version: 1.16.1 kernelspec: - display_name: Python 3 + display_name: Python 3 (ipykernel) language: python name: python3 language_info: @@ -20,7 +20,7 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.8.8 + version: 3.10.0 plotly: description: Visualize regression in scikit-learn with Plotly. display_as: ai_ml @@ -412,6 +412,7 @@ import pandas as pd import plotly.express as px import plotly.graph_objects as go from sklearn.linear_model import LassoCV +from sklearn.preprocessing import StandardScaler N_FOLD = 6 @@ -421,9 +422,13 @@ X = df.drop(columns=['lifeExp', 'iso_num']) X = pd.get_dummies(X, columns=['country', 'continent', 'iso_alpha']) y = df['lifeExp'] +# Normalize the data +scaler = StandardScaler() +X_scaled = scaler.fit_transform(X) + # Train model to predict life expectancy -model = LassoCV(cv=N_FOLD, normalize=True) -model.fit(X, y) +model = LassoCV(cv=N_FOLD) +model.fit(X_scaled, y) mean_alphas = model.mse_path_.mean(axis=-1) fig = go.Figure([ From 37116fb95fb4667b73b05a9a417b65e2fdd56a59 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 16:22:11 -0500 Subject: [PATCH 25/33] Update requirements.txt --- doc/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index cf52351e9d4..3d1a83d96d5 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -4,7 +4,7 @@ ipywidgets==7.7.2 jupyter-client<7 jupyter notebook -pandas==1.1.3 +pandas==1.1.5 statsmodels==0.12.1 scipy==1.5.4 patsy==0.5.1 @@ -16,7 +16,7 @@ pyshp==2.1.2 shapely==1.7.1 psutil requests -networkx +networkx==2.6.3 squarify scikit-image==0.18.1 scikit-learn From aa5965d638ad3195c7b9c2dc8d4b6265e1554ae0 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 16:34:39 -0500 Subject: [PATCH 26/33] Update setup.py --- packages/python/plotly/setup.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/python/plotly/setup.py b/packages/python/plotly/setup.py index a9a2ac5869f..e1247b9f937 100644 --- a/packages/python/plotly/setup.py +++ b/packages/python/plotly/setup.py @@ -217,8 +217,8 @@ def finalize_options(self): pass def run(self): - if sys.version_info < (3, 6): - raise ImportError("Code generation must be executed with Python >= 3.6") + if sys.version_info < (3, 8): + raise ImportError("Code generation must be executed with Python >= 3.8") from codegen import perform_codegen @@ -506,16 +506,15 @@ def run(self): long_description_content_type="text/markdown", classifiers=[ "Development Status :: 5 - Production/Stable", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Topic :: Scientific/Engineering :: Visualization", "License :: OSI Approved :: MIT License", ], - python_requires=">=3.6", + python_requires=">=3.8", license="MIT", packages=[ "jupyterlab_plotly", From 8abb15238663e7b2bb64134e128c8ce3ec5e0cc4 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 17:38:45 -0500 Subject: [PATCH 27/33] update pandas version --- doc/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/requirements.txt b/doc/requirements.txt index 3d1a83d96d5..b329e22271b 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -4,7 +4,7 @@ ipywidgets==7.7.2 jupyter-client<7 jupyter notebook -pandas==1.1.5 +pandas==1.2.0 statsmodels==0.12.1 scipy==1.5.4 patsy==0.5.1 From 8655c10c3621ccfaf78eb85b9dc8f3cef5c4360b Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 17:50:25 -0500 Subject: [PATCH 28/33] Update ml-pca.md --- doc/python/ml-pca.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/python/ml-pca.md b/doc/python/ml-pca.md index cbd38e0fd9c..1143e5cdeb1 100644 --- a/doc/python/ml-pca.md +++ b/doc/python/ml-pca.md @@ -6,9 +6,9 @@ jupyter: extension: .md format_name: markdown format_version: '1.3' - jupytext_version: 1.14.1 + jupytext_version: 1.16.1 kernelspec: - display_name: Python 3 + display_name: Python 3 (ipykernel) language: python name: python3 language_info: @@ -20,7 +20,7 @@ jupyter: name: python nbconvert_exporter: python pygments_lexer: ipython3 - version: 3.8.8 + version: 3.10.11 plotly: description: Visualize Principle Component Analysis (PCA) of your high-dimensional data in Python with Plotly. @@ -105,17 +105,17 @@ fig.show() When you will have too many features to visualize, you might be interested in only visualizing the most relevant components. Those components often capture a majority of the [explained variance](https://en.wikipedia.org/wiki/Explained_variation), which is a good way to tell if those components are sufficient for modelling this dataset. -In the example below, our dataset contains 10 features, but we only select the first 4 components, since they explain over 99% of the total variance. +In the example below, our dataset contains 8 features, but we only select the first 2 components. ```python import pandas as pd import plotly.express as px from sklearn.decomposition import PCA -from sklearn.datasets import load_boston +from sklearn.datasets import fetch_california_housing -boston = load_boston() -df = pd.DataFrame(boston.data, columns=boston.feature_names) -n_components = 4 +housing = fetch_california_housing(as_frame=True) +df = housing.data +n_components = 2 pca = PCA(n_components=n_components) components = pca.fit_transform(df) @@ -127,7 +127,7 @@ labels['color'] = 'Median Price' fig = px.scatter_matrix( components, - color=boston.target, + color=housing.target, dimensions=range(n_components), labels=labels, title=f'Total Explained Variance: {total_var:.2f}%', From 0bdd6e08aee2c20a3baf445655fb79ff1972fb18 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 17:53:22 -0500 Subject: [PATCH 29/33] Update conda_build_config.yaml --- packages/python/plotly/recipe/conda_build_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/python/plotly/recipe/conda_build_config.yaml b/packages/python/plotly/recipe/conda_build_config.yaml index abcf8353472..86b425eca79 100644 --- a/packages/python/plotly/recipe/conda_build_config.yaml +++ b/packages/python/plotly/recipe/conda_build_config.yaml @@ -1,2 +1,2 @@ python: - - 3.6 + - 3.8 From 9602b65d048d13454659e971a11d970a8bb9d8b4 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 17:56:12 -0500 Subject: [PATCH 30/33] Update requirements.txt --- doc/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/requirements.txt b/doc/requirements.txt index b329e22271b..ba4d9f758b4 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -38,3 +38,4 @@ dash-bio jinja2<3.1 parmed<=3.4.4; python_version<"3.8" polars +dask==2022.2.0 \ No newline at end of file From 045778ab0872365e6caee7fb51d40957127ae993 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 18:12:57 -0500 Subject: [PATCH 31/33] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6df6cde3b59..43972321be8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] +### Updated +- Removed Python 3.6 and Python 3.7 support [[#4490](https://github.com/plotly/plotly.py/pull/4490)] + ### Fixed - Ensure scatter `mode` is deterministic from `px` [[#4429](https://github.com/plotly/plotly.py/pull/4429)] - Fix issue with creating dendrogram in subplots [[#4411](https://github.com/plotly/plotly.py/pull/4411)], From 13809ac916c83f2fd1548b4ca6cca94f08e587f4 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 18:13:01 -0500 Subject: [PATCH 32/33] Update requirements.txt --- binder/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binder/requirements.txt b/binder/requirements.txt index 814206bdb34..ff37485019b 100644 --- a/binder/requirements.txt +++ b/binder/requirements.txt @@ -2,7 +2,7 @@ jupytext plotly==5.18.0 jupyter notebook -pandas==1.1.3 +pandas==1.2.0 statsmodels==0.12.1 scipy patsy==0.5.1 From ca597f9d5919dd3709b95e3221a64f0a6a76bd77 Mon Sep 17 00:00:00 2001 From: Liam Connors Date: Mon, 22 Jan 2024 18:19:28 -0500 Subject: [PATCH 33/33] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43972321be8..52ee62a7562 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] ### Updated -- Removed Python 3.6 and Python 3.7 support [[#4490](https://github.com/plotly/plotly.py/pull/4490)] +- Removed Python 3.6 and Python 3.7 support [[#4492](https://github.com/plotly/plotly.py/pull/4492)] ### Fixed - Ensure scatter `mode` is deterministic from `px` [[#4429](https://github.com/plotly/plotly.py/pull/4429)]