Skip to content

Commit 9b09504

Browse files
authored
Merge branch 'main' into kaleido-docs-updates
2 parents 30cc778 + ab3fbbd commit 9b09504

File tree

14,862 files changed

+154755
-352444
lines changed

Some content is hidden

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

14,862 files changed

+154755
-352444
lines changed

.circleci/config.yml

+11-24
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@ commands:
5858
source .venv/bin/activate
5959
uv pip install .
6060
uv pip install -r ./test_requirements/requirements_optional.txt
61-
cd js
62-
npm ci
63-
npm run build
6461
6562
- when:
6663
condition:
@@ -129,7 +126,7 @@ jobs:
129126
command: |
130127
python -m venv venv
131128
. venv/bin/activate
132-
pip install black==22.3.0
129+
pip install black==25.1.0
133130
- run:
134131
name: Check formatting with black
135132
command: |
@@ -269,22 +266,18 @@ jobs:
269266

270267
steps:
271268
- checkout
272-
273269
- run:
274-
name: initial NPM Build
270+
name: PyPI Build
275271
command: |
276-
python -m venv venv
277-
. venv/bin/activate
272+
curl -LsSf https://astral.sh/uv/install.sh | sh
273+
uv venv
274+
source .venv/bin/activate
275+
uv pip install build
276+
uv pip install jupyter
278277
cd js
279278
npm ci
280279
npm run build
281-
git status
282-
283-
- run:
284-
name: PyPI Build
285-
command: |
286-
. venv/bin/activate
287-
pip install build
280+
cd ..
288281
python -m build --sdist --wheel -o dist
289282
cp -R dist output
290283
git status
@@ -310,7 +303,6 @@ jobs:
310303
- checkout
311304
- browser-tools/install-chrome
312305
- browser-tools/install-chromedriver
313-
314306
- run:
315307
name: Install dependencies
316308
command: |
@@ -319,16 +311,11 @@ jobs:
319311
uv venv
320312
source .venv/bin/activate
321313
uv pip install -r requirements.txt
314+
cd ..
322315
if [ "${CIRCLE_BRANCH}" != "doc-prod" ]; then
323316
uv pip uninstall plotly
324-
cd ..
325317
uv pip install -e .
326-
cd js
327-
npm ci
328-
npm run build
329-
cd ../doc
330318
fi
331-
cd ..
332319
333320
- run:
334321
name: make html
@@ -420,7 +407,7 @@ workflows:
420407
release_build:
421408
jobs:
422409
- full_build
423-
410+
424411
build:
425412
jobs:
426413
- test_core_py:
@@ -449,4 +436,4 @@ workflows:
449436
pandas_version: "1.2.4"
450437
numpy_version: "1.26.4"
451438
- python_311_percy
452-
- build-doc
439+
- build-doc

.github/workflows/check-js-build.yml

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
on: push
2+
3+
jobs:
4+
check-js-build:
5+
name: Check JS build artifacts
6+
runs-on: ubuntu-latest
7+
steps:
8+
- uses: actions/checkout@v4
9+
- name: Set up Python
10+
uses: actions/setup-python@v5
11+
with:
12+
python-version: "3.x"
13+
14+
- name: Install Node
15+
uses: actions/setup-node@v2
16+
with:
17+
node-version: '22'
18+
19+
- name: Copy current files to a temporary directory
20+
run: |
21+
cp -R plotly/labextension/ plotly/labextension-tmp/
22+
23+
- name: Install dependencies and build
24+
run: |
25+
curl -LsSf https://astral.sh/uv/install.sh | sh
26+
uv venv
27+
source .venv/bin/activate
28+
uv pip install jupyter
29+
cd js
30+
npm ci
31+
npm run build
32+
- name: Check JupyterLab build artifacts
33+
run: |
34+
# 1. Hash contents of all static files, sort by content hash
35+
find plotly/labextension/static -type f -exec sha256sum {} \; | awk '{print $1}' | sort > new_hashes.txt
36+
find plotly/labextension-tmp/static -type f -exec sha256sum {} \; | awk '{print $1}' | sort > old_hashes.txt
37+
38+
# 2. Compare the sorted content hashes
39+
diff old_hashes.txt new_hashes.txt > content_diff.txt
40+
41+
# Remove the "load" line from both package.json files before comparing
42+
grep -v '"load": "static/' plotly/labextension/package.json > pkg1.json
43+
grep -v '"load": "static/' plotly/labextension-tmp/package.json > pkg2.json
44+
45+
# Compare stripped versions
46+
diff pkg1.json pkg2.json > package_json_diff.txt
47+
48+
# 5. Final check
49+
if [ -s content_diff.txt ] || [ -s package_json_diff.txt ]; then
50+
echo "❌ Build artifacts differ:"
51+
echo "--- Unexpected diffs ---"
52+
cat content_diff.txt
53+
echo "--- Unexpected package.json diffs ---"
54+
cat package_json_diff.txt
55+
echo "Please replace the 'plotly/labextension' directory with the artifacts of this CI run."
56+
exit 1
57+
else
58+
echo "✅ Build artifacts match expected output (ignoring known 'load' hash in package.json)."
59+
fi
60+
61+
- name: Store the build artifacts from plotly/labextension
62+
uses: actions/upload-artifact@v4
63+
if: failure()
64+
with:
65+
name: labextension
66+
path: plotly/labextension

.github/workflows/test-release.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@ jobs:
2020
- name: Install Node
2121
uses: actions/setup-node@v2
2222
with:
23-
node-version: '18'
23+
node-version: '22'
2424

2525
- name: Install npm dependencies
2626
run: |
27+
curl -LsSf https://astral.sh/uv/install.sh | sh
28+
uv venv
29+
source .venv/bin/activate
30+
uv pip install jupyter
2731
cd js
2832
npm ci --verbose
2933
npm run build --verbose

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ doc/python/.mapbox_token
5959
doc/.ipynb_checkpoints
6060
tags
6161
doc/check-or-enforce-order.py
62-
plotly/package_data/widgetbundle.js
6362

6463
tests/percy/*.html
6564
tests/percy/pandas2/*.html

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Change Log
1+
# Changelog
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

CONTRIBUTING.md

+13
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,19 @@ and
169169
[`pip`](https://pip.pypa.io/en/stable/reference/pip_install/#install-editable)
170170
documentation on _development mode_.
171171

172+
### Updating the `js/` directory
173+
**This is only necessary if you're making changes to files in the `js/` directory.**
174+
If you make changes to any files in the `js/` directory, you must run `npm install && npm run build` from the `js/` directory to rebuild the FigureWidget and JupyterLab extension.
175+
You must then commit the build artifacts produced in `plotly/labextension`. A CI job will verify that this step has been done correctly.
176+
177+
**Notes on the contents of the `js/` directory:**
178+
The `js/` directory contains Javascript code which helps with using Plotly in Jupyter notebooks.
179+
180+
There are two kinds of Jupyter support included in the `js/` directory:
181+
1. **Mime Renderer JupyterLab extension**: This is the default renderer for Plotly `Figure()` objects in Jupyter notebooks. The Plotly mime renderer JupyterLab extension is used automatically by JupyterLab / Jupyter Notebook
182+
when it sees the mimetype `application/vnd.plotly.v1+json` in the notebook output. The mime renderer loads `plotly.js` a single time and references it each time a Plotly figure is used in the notebook. This allows us to avoid embedding `plotly.js` in the notebook output. The JupyterLab extension source code is located at `js/src/mimeExtension.ts` and the compiled extension code is located at `plotly/labextension` in the built Python package. The command `jupyter labextension build` (which is one of the steps called by `npm run build`) compiles the extension and places the build artifacts in `plotly/labextension`.
183+
2. **FigureWidget**: This is a more-interactive method for rendering Plotly charts in notebooks. FigureWidget used by creating a `FigureWidget()` object inside the notebook code (in place of a `Figure()`). It allows for communication between the Javascript frontend and Python backend, and requires the installation of an additional Python package (`anywidget`). The FigureWidget source code is located at `js/src/widget.ts`, and is included in the built Python package at `plotly/package_data/widgetbundle.js`.
184+
172185
### Configure black code formatting
173186

174187
This repo uses the [Black](https://black.readthedocs.io/en/stable/) code formatter,

_plotly_utils/basevalidators.py

+4-23
Original file line numberDiff line numberDiff line change
@@ -1328,25 +1328,14 @@ def numbers_allowed(self):
13281328
return self.colorscale_path is not None
13291329

13301330
def description(self):
1331-
1332-
named_clrs_str = "\n".join(
1333-
textwrap.wrap(
1334-
", ".join(self.named_colors),
1335-
width=79 - 16,
1336-
initial_indent=" " * 12,
1337-
subsequent_indent=" " * 12,
1338-
)
1339-
)
1340-
13411331
valid_color_description = """\
13421332
The '{plotly_name}' property is a color and may be specified as:
13431333
- A hex string (e.g. '#ff0000')
13441334
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
13451335
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
13461336
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
1347-
- A named CSS color:
1348-
{clrs}""".format(
1349-
plotly_name=self.plotly_name, clrs=named_clrs_str
1337+
- A named CSS color: see https://plotly.com/python/css-colors/ for a list""".format(
1338+
plotly_name=self.plotly_name
13501339
)
13511340

13521341
if self.colorscale_path:
@@ -2483,15 +2472,11 @@ def description(self):
24832472
that may be specified as:
24842473
- An instance of :class:`{module_str}.{class_str}`
24852474
- A dict of string/value properties that will be passed
2486-
to the {class_str} constructor
2487-
2488-
Supported dict properties:
2489-
{constructor_params_str}"""
2475+
to the {class_str} constructor"""
24902476
).format(
24912477
plotly_name=self.plotly_name,
24922478
class_str=self.data_class_str,
24932479
module_str=self.module_str,
2494-
constructor_params_str=self.data_docs,
24952480
)
24962481

24972482
return desc
@@ -2560,15 +2545,11 @@ def description(self):
25602545
{class_str} that may be specified as:
25612546
- A list or tuple of instances of {module_str}.{class_str}
25622547
- A list or tuple of dicts of string/value properties that
2563-
will be passed to the {class_str} constructor
2564-
2565-
Supported dict properties:
2566-
{constructor_params_str}"""
2548+
will be passed to the {class_str} constructor"""
25672549
).format(
25682550
plotly_name=self.plotly_name,
25692551
class_str=self.data_class_str,
25702552
module_str=self.module_str,
2571-
constructor_params_str=self.data_docs,
25722553
)
25732554

25742555
return desc

_plotly_utils/colors/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
Be careful! If you have a lot of unique numbers in your color column you will
7474
end up with a colormap that is massive and may slow down graphing performance.
7575
"""
76+
7677
import decimal
7778
from numbers import Number
7879

codegen/__init__.py

+30-32
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
get_data_validator_instance,
2727
)
2828

29+
# Target Python version for code formatting with Black.
30+
# Must be one of the values listed in pyproject.toml.
31+
BLACK_TARGET_VERSIONS = "py38 py39 py310 py311 py312"
32+
2933

3034
# Import notes
3135
# ------------
@@ -85,7 +89,7 @@ def preprocess_schema(plotly_schema):
8589
items["colorscale"] = items.pop("concentrationscales")
8690

8791

88-
def perform_codegen():
92+
def perform_codegen(reformat=True):
8993
# Set root codegen output directory
9094
# ---------------------------------
9195
# (relative to project root)
@@ -267,36 +271,24 @@ def perform_codegen():
267271
root_datatype_imports.append(f"._deprecations.{dep_clas}")
268272

269273
optional_figure_widget_import = f"""
270-
if sys.version_info < (3, 7) or TYPE_CHECKING:
271-
try:
272-
import ipywidgets as _ipywidgets
273-
from packaging.version import Version as _Version
274-
if _Version(_ipywidgets.__version__) >= _Version("7.0.0"):
275-
from ..graph_objs._figurewidget import FigureWidget
276-
else:
277-
raise ImportError()
278-
except Exception:
279-
from ..missing_anywidget import FigureWidget
280-
else:
281-
__all__.append("FigureWidget")
282-
orig_getattr = __getattr__
283-
def __getattr__(import_name):
284-
if import_name == "FigureWidget":
285-
try:
286-
import ipywidgets
287-
from packaging.version import Version
288-
289-
if Version(ipywidgets.__version__) >= Version("7.0.0"):
290-
from ..graph_objs._figurewidget import FigureWidget
291-
292-
return FigureWidget
293-
else:
294-
raise ImportError()
295-
except Exception:
296-
from ..missing_anywidget import FigureWidget
274+
__all__.append("FigureWidget")
275+
orig_getattr = __getattr__
276+
def __getattr__(import_name):
277+
if import_name == "FigureWidget":
278+
try:
279+
import ipywidgets
280+
from packaging.version import Version
281+
282+
if Version(ipywidgets.__version__) >= Version("7.0.0"):
283+
from ..graph_objs._figurewidget import FigureWidget
297284
return FigureWidget
285+
else:
286+
raise ImportError()
287+
except Exception:
288+
from ..missing_anywidget import FigureWidget
289+
return FigureWidget
298290
299-
return orig_getattr(import_name)
291+
return orig_getattr(import_name)
300292
"""
301293
# ### __all__ ###
302294
for path_parts, class_names in alls.items():
@@ -337,9 +329,15 @@ def __getattr__(import_name):
337329
f.write(graph_objects_init_source)
338330

339331
# ### Run black code formatter on output directories ###
340-
subprocess.call(["black", "--target-version=py36", validators_pkgdir])
341-
subprocess.call(["black", "--target-version=py36", graph_objs_pkgdir])
342-
subprocess.call(["black", "--target-version=py36", graph_objects_path])
332+
if reformat:
333+
target_version = [
334+
f"--target-version={v}" for v in BLACK_TARGET_VERSIONS.split()
335+
]
336+
subprocess.call(["black", *target_version, validators_pkgdir])
337+
subprocess.call(["black", *target_version, graph_objs_pkgdir])
338+
subprocess.call(["black", *target_version, graph_objects_path])
339+
else:
340+
print("skipping reformatting")
343341

344342

345343
if __name__ == "__main__":

codegen/compatibility.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def __init__(self, *args, **kwargs):
8989
{depr_msg}
9090
\"\"\"
9191
warnings.warn(\"\"\"{depr_msg}\"\"\", DeprecationWarning)
92-
super({class_name}, self).__init__(*args, **kwargs)\n\n\n"""
92+
super().__init__(*args, **kwargs)\n\n\n"""
9393
)
9494

9595
# Return source string

0 commit comments

Comments
 (0)