From d6d041687f3ef01dabeac7cd6f92f8efb56c9e60 Mon Sep 17 00:00:00 2001 From: Devin Smith Date: Wed, 20 Dec 2023 13:11:48 -0800 Subject: [PATCH] feat: Add plotly-express JsPlugin implementation and registration (#150) This plumbs automatic JsPlugin registration - the server side depends on https://github.com/deephaven/deephaven-core/pull/4925. --- plugins/plotly-express/setup.cfg | 6 +- plugins/plotly-express/setup.py | 7 +- .../src/deephaven/plot/express/__init__.py | 21 ------ .../src/deephaven/plot/express/_js.py | 73 +++++++++++++++++++ .../src/deephaven/plot/express/_register.py | 24 ++++++ 5 files changed, 104 insertions(+), 27 deletions(-) create mode 100644 plugins/plotly-express/src/deephaven/plot/express/_js.py create mode 100644 plugins/plotly-express/src/deephaven/plot/express/_register.py diff --git a/plugins/plotly-express/setup.cfg b/plugins/plotly-express/setup.cfg index c13026191..237bb3d1f 100644 --- a/plugins/plotly-express/setup.cfg +++ b/plugins/plotly-express/setup.cfg @@ -3,7 +3,7 @@ name = deephaven-plugin-plotly-express description = Deephaven Chart Plugin long_description = file: README.md long_description_content_type = text/markdown -version = attr:deephaven.plot.express.__version__ +version = 0.3.0.dev0 url = https://github.com/deephaven/deephaven-plugins project_urls = Source Code = https://github.com/deephaven/deephaven-plugins @@ -25,7 +25,7 @@ package_dir= =src packages=find_namespace: install_requires = - deephaven-plugin>=0.5.0 + deephaven-plugin>=0.6.0 plotly include_package_data = True @@ -34,4 +34,4 @@ where=src [options.entry_points] deephaven.plugin = - registration_cls = deephaven.plot.express:ChartRegistration \ No newline at end of file + registration_cls = deephaven.plot.express._register:ExpressRegistration diff --git a/plugins/plotly-express/setup.py b/plugins/plotly-express/setup.py index 3de56d39d..d5125a974 100644 --- a/plugins/plotly-express/setup.py +++ b/plugins/plotly-express/setup.py @@ -2,7 +2,6 @@ from setuptools import setup import os import subprocess -import json # npm pack in js directory @@ -18,11 +17,13 @@ os.makedirs(dest_dir, exist_ok=True) # pack and unpack into the js plotly-express directory - subprocess.run(["npm", "pack", "--pack-destination", project], cwd=js_dir) + subprocess.run( + ["npm", "pack", "--pack-destination", project], cwd=js_dir, check=True + ) # it is assumed that there is only one tarball in the directory files = os.listdir(dest_dir) for file in files: - subprocess.run(["tar", "-xzf", file], cwd=dest_dir) + subprocess.run(["tar", "-xzf", file], cwd=dest_dir, check=True) os.remove(os.path.join(dest_dir, file)) # move the contents of the package directory to the plotly-express directory diff --git a/plugins/plotly-express/src/deephaven/plot/express/__init__.py b/plugins/plotly-express/src/deephaven/plot/express/__init__.py index fc33bd183..9764d2f95 100644 --- a/plugins/plotly-express/src/deephaven/plot/express/__init__.py +++ b/plugins/plotly-express/src/deephaven/plot/express/__init__.py @@ -2,7 +2,6 @@ import json -from deephaven.plugin import Registration, Callback from deephaven.plugin.object_type import BidirectionalObjectType, MessageStream from .communication.DeephavenFigureConnection import DeephavenFigureConnection @@ -44,7 +43,6 @@ from .data import data_generators -__version__ = "0.3.0.dev0" NAME = "deephaven.plot.express.DeephavenFigure" @@ -101,22 +99,3 @@ def create_client_connection( payload, references = figure_connection.on_data(initial_message, []) connection.on_data(payload, references) return figure_connection - - -class ChartRegistration(Registration): - """ - Register the DeephavenFigureType - - """ - - @classmethod - def register_into(cls, callback: Callback) -> None: - """ - Register the DeephavenFigureType - - Args: - callback: Registration.Callback: - A function to call after registration - - """ - callback.register(DeephavenFigureType) diff --git a/plugins/plotly-express/src/deephaven/plot/express/_js.py b/plugins/plotly-express/src/deephaven/plot/express/_js.py new file mode 100644 index 000000000..84d6c05fb --- /dev/null +++ b/plugins/plotly-express/src/deephaven/plot/express/_js.py @@ -0,0 +1,73 @@ +import importlib.resources +import json +import pathlib +import sys +from typing import Callable, ContextManager + +from deephaven.plugin.js import JsPlugin + + +class ExpressJsPlugin(JsPlugin): + def __init__( + self, + name: str, + version: str, + main: str, + path: pathlib.Path, + ) -> None: + self._name = name + self._version = version + self._main = main + self._path = path + + @property + def name(self) -> str: + return self._name + + @property + def version(self) -> str: + return self._version + + @property + def main(self) -> str: + return self._main + + def path(self) -> pathlib.Path: + return self._path + + +def _create_from_npm_package_json( + path_provider: Callable[[], ContextManager[pathlib.Path]] +) -> JsPlugin: + with path_provider() as tmp_js_path: + js_path = tmp_js_path + if not js_path.exists(): + raise Exception( + f"Package is not installed in a normal python filesystem, '{js_path}' does not exist" + ) + with (js_path / "package.json").open("rb") as f: + package_json = json.load(f) + return ExpressJsPlugin( + package_json["name"], + package_json["version"], + package_json["main"], + js_path, + ) + + +def _resource_js_path() -> ContextManager[pathlib.Path]: + # TODO: Js content should be in same package directory + # https://github.com/deephaven/deephaven-plugins/issues/139 + if sys.version_info < (3, 9): + return importlib.resources.path("js", "plotly-express") + else: + return importlib.resources.as_file( + importlib.resources.files("js").joinpath("plotly-express") + ) + + +def create_js_plugin() -> JsPlugin: + # TODO: Include developer instructions for installing in editable mode + # https://github.com/deephaven/deephaven-plugins/issues/93 + # TBD what editable mode looks like for JsPlugin + return _create_from_npm_package_json(_resource_js_path) diff --git a/plugins/plotly-express/src/deephaven/plot/express/_register.py b/plugins/plotly-express/src/deephaven/plot/express/_register.py new file mode 100644 index 000000000..378b35a8a --- /dev/null +++ b/plugins/plotly-express/src/deephaven/plot/express/_register.py @@ -0,0 +1,24 @@ +from . import DeephavenFigureType +from ._js import create_js_plugin + +from deephaven.plugin import Registration, Callback + + +class ExpressRegistration(Registration): + """ + Register the DeephavenFigureType and a JsPlugin + + """ + + @classmethod + def register_into(cls, callback: Callback) -> None: + """ + Register the DeephavenFigureType and a JsPlugin + + Args: + callback: Registration.Callback: + A function to call after registration + + """ + callback.register(DeephavenFigureType) + callback.register(create_js_plugin())