From b233a471f8a681cfb313507390b20f1c4d8398bc Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Thu, 29 Feb 2024 09:46:45 -0600 Subject: [PATCH 01/15] wip --- .github/workflows/modified-plugin.yml | 2 + .github/workflows/release-python-package.yml | 2 + plugins/utilities/.gitignore | 8 + plugins/utilities/LICENSE | 202 ++++++++++++++++++ plugins/utilities/README.md | 26 +++ plugins/utilities/pyproject.toml | 3 + plugins/utilities/setup.cfg | 31 +++ .../deephaven/plugin/utilities/__init__.py | 1 + .../src/deephaven/plugin/utilities/utils.py | 159 ++++++++++++++ tools/update_version.sh | 3 + 10 files changed, 437 insertions(+) create mode 100644 plugins/utilities/.gitignore create mode 100644 plugins/utilities/LICENSE create mode 100644 plugins/utilities/README.md create mode 100644 plugins/utilities/pyproject.toml create mode 100644 plugins/utilities/setup.cfg create mode 100644 plugins/utilities/src/deephaven/plugin/utilities/__init__.py create mode 100644 plugins/utilities/src/deephaven/plugin/utilities/utils.py diff --git a/.github/workflows/modified-plugin.yml b/.github/workflows/modified-plugin.yml index 4c4837347..00a96cb4d 100644 --- a/.github/workflows/modified-plugin.yml +++ b/.github/workflows/modified-plugin.yml @@ -11,6 +11,7 @@ on: - 'matplotlib-v*' - 'json-v*' - 'ui-v*' + - 'utilities-v*' jobs: changes: @@ -32,6 +33,7 @@ jobs: matplotlib: plugins/matplotlib/** json: plugins/json/** ui: plugins/ui/** + utilities: plugins/utilities/** # Test all python packages that have been modified individually test-python: diff --git a/.github/workflows/release-python-package.yml b/.github/workflows/release-python-package.yml index 5ffa014a2..5b4441f07 100644 --- a/.github/workflows/release-python-package.yml +++ b/.github/workflows/release-python-package.yml @@ -32,6 +32,8 @@ jobs: run: npm ci - name: Build npm packages + # utilities package does not have any npm package to build + if : ${{ inputs.package != 'utilities' }} run: npm run build -- --scope "@deephaven/js-plugin-${{ inputs.package }}" - name: Set up Python diff --git a/plugins/utilities/.gitignore b/plugins/utilities/.gitignore new file mode 100644 index 000000000..3356dc1ce --- /dev/null +++ b/plugins/utilities/.gitignore @@ -0,0 +1,8 @@ +build/ +dist/ +.venv/ +/venv +*.egg-info/ +.idea +.DS_store +__pycache__/ \ No newline at end of file diff --git a/plugins/utilities/LICENSE b/plugins/utilities/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/plugins/utilities/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/plugins/utilities/README.md b/plugins/utilities/README.md new file mode 100644 index 000000000..fb224f9c3 --- /dev/null +++ b/plugins/utilities/README.md @@ -0,0 +1,26 @@ +# Deephaven Plugin Utilities + +This is a Python package that stores cross-plugin utilities for building Deephaven plugins. +It is not a plugin itself. + +## Build + +To create your build / development environment (skip the first two lines if you already have a venv): + +```sh +python -m venv .venv +source .venv/bin/activate +pip install --upgrade pip setuptools +pip install build deephaven-plugin +``` + +To build: + +```sh +python -m build --wheel +``` + +The wheel is stored in `dist/`. + +To test within [deephaven-core](https://github.com/deephaven/deephaven-core), note where this wheel is stored (using `pwd`, for example). +Then, follow the directions in the top-level README.md to install the wheel into your Deephaven environment. diff --git a/plugins/utilities/pyproject.toml b/plugins/utilities/pyproject.toml new file mode 100644 index 000000000..62df2b006 --- /dev/null +++ b/plugins/utilities/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools>=43.0.0", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/plugins/utilities/setup.cfg b/plugins/utilities/setup.cfg new file mode 100644 index 000000000..78b1efcd4 --- /dev/null +++ b/plugins/utilities/setup.cfg @@ -0,0 +1,31 @@ +[metadata] +name = deephaven-plugin-utilities +description = Deephaven Plugin Utilities +long_description = file: README.md +long_description_content_type = text/markdown +version = 0.0.1.dev0 +url = https://github.com/deephaven/deephaven-plugins +project_urls = + Source Code = https://github.com/deephaven/deephaven-plugins + Bug Tracker = https://github.com/deephaven/deephaven-plugins/issues +classifiers = + Programming Language :: Python :: 3 + License :: OSI Approved :: Apache Software License + Operating System :: OS Independent + Environment :: Plugins + Development Status :: 3 - Alpha +keywords = deephaven, plugin, utilities +author = Joe Numainville +author_email = josephnumainville@deephaven.io +platforms = any + +[options] +package_dir= + =src +packages=find_namespace: +install_requires = + deephaven-plugin>=0.6.0 +include_package_data = True + +[options.packages.find] +where=src diff --git a/plugins/utilities/src/deephaven/plugin/utilities/__init__.py b/plugins/utilities/src/deephaven/plugin/utilities/__init__.py new file mode 100644 index 000000000..16281fe0b --- /dev/null +++ b/plugins/utilities/src/deephaven/plugin/utilities/__init__.py @@ -0,0 +1 @@ +from .utils import * diff --git a/plugins/utilities/src/deephaven/plugin/utilities/utils.py b/plugins/utilities/src/deephaven/plugin/utilities/utils.py new file mode 100644 index 000000000..6c1543c65 --- /dev/null +++ b/plugins/utilities/src/deephaven/plugin/utilities/utils.py @@ -0,0 +1,159 @@ +import abc +import logging +import shutil +import os +import subprocess +from functools import partial +from typing import Callable, ContextManager +import importlib.resources +import json +import pathlib +import sys +from deephaven.plugin import Callback +from deephaven.plugin.js import JsPlugin + +logger = logging.getLogger(__name__) + + +def package_js(js_dir: str, dest_dir: str) -> None: + """ + Package the built JS files at the given JS directory and unpack them into the destination directory. + + Args: + js_dir: + The directory containing the JS files + dest_dir: + The directory to unpack the JS files into + """ + dist_dir = os.path.join(js_dir, "dist") + build_dir = os.path.join(js_dir, "build") + package_dir = os.path.join(build_dir, "package") + + # copy the bundle to the directory + # the path may not exist (e.g. when running tests) + # so it is not strictly necessary to copy the bundle + if os.path.exists(dist_dir): + # ignore errors as the directory may not exist + shutil.rmtree(build_dir, ignore_errors=True) + shutil.rmtree(dest_dir, ignore_errors=True) + + os.makedirs(build_dir, exist_ok=True) + + # pack and unpack into the js directory + subprocess.run( + ["npm", "pack", "--pack-destination", "build"], cwd=js_dir, check=True + ) + # it is assumed that there is only one tarball in the directory + files = os.listdir(build_dir) + for file in files: + subprocess.run(["tar", "-xzf", file], cwd=build_dir, check=True) + os.remove(os.path.join(build_dir, file)) + + # move the package directory to the expected package location + shutil.move(package_dir, dest_dir) + + +def attempt_registration(callback: Callback, js_plugin: JsPlugin) -> None: + """ + Attempt to register a JS plugin. + If failed, and enterprise is not detected, it will log as a warning and continue. + + Args: + callback: + A callback to register the JS plugin + js_plugin: + The JS plugin to register + """ + try: + callback.register(js_plugin) + except RuntimeError: + # warning should only be logged if enterprise is not detected + if not os.path.exists("/usr/illumon/latest/bin"): + logger.warning( + f"Failed to register {js_plugin} embedded in python plugin. Skipping." + ) + + +def _create_from_npm_package_json( + path_provider: Callable[[], ContextManager[pathlib.Path]], plugin_class: abc.ABCMeta +) -> JsPlugin: + """ + Create a JsPlugin from an npm package.json file. + + Args: + path_provider: + A function that returns a context manager that provides a pathlib.Path to the package.json file + plugin_class: + The class to create. It must be a subclass of 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 plugin_class( + package_json["name"], + package_json["version"], + package_json["main"], + js_path, + ) + + +def _resource_js_path_provider( + package_namespace: str, js_name: str +) -> Callable[[], ContextManager[pathlib.Path]]: + """ + Get the path to a resource in a package. + + Args: + package_namespace: + The package namespace + js_name: + The resource name + """ + return partial(_resource_js_path, package_namespace, js_name) + + +def _resource_js_path( + package_namespace: str, js_name: str +) -> ContextManager[pathlib.Path]: + """ + Get the path to a resource in a package. + + Args: + package_namespace: + The package namespace + js_name: + The resource name + """ + + if sys.version_info < (3, 9): + return importlib.resources.path(package_namespace, js_name) + else: + return importlib.resources.as_file( + importlib.resources.files(package_namespace).joinpath(js_name) + ) + + +def create_js_plugin( + package_namespace: str, js_name: str, plugin_class: abc.ABCMeta +) -> JsPlugin: + """ + Create a JsPlugin from an npm package.json file. + + Args: + package_namespace: + The package namespace + js_name: + The resource name + plugin_class: + The class to create. It must be a subclass of JsPlugin. + + Returns: + The created JsPlugin + """ + js_path = _resource_js_path_provider(package_namespace, js_name) + return _create_from_npm_package_json(js_path, plugin_class) diff --git a/tools/update_version.sh b/tools/update_version.sh index 3892a1873..9279484c5 100755 --- a/tools/update_version.sh +++ b/tools/update_version.sh @@ -139,6 +139,9 @@ case "$package" in update_file ui/src/js/package.json '"version": "' '",' update_file ui/src/deephaven/ui/__init__.py '__version__ = "' '"' "$extra" ;; + utilities) + update_file utilities/setup.cfg 'version = ' '' "$extra" + ;; *) { log_error "Unhandled plugin $package. You will need to add wiring in $SCRIPT_NAME" From 3aea2fccc0493ad88ea72dc5adcd89fa6aee0b0e Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Thu, 29 Feb 2024 16:13:09 -0600 Subject: [PATCH 02/15] comments --- .github/workflows/modified-plugin.yml | 4 +- .github/workflows/release-python-package.yml | 4 +- plugins/packaging/.gitignore | 8 + plugins/packaging/LICENSE | 202 ++++++++++++++++++ plugins/packaging/README.md | 25 +++ plugins/packaging/pyproject.toml | 3 + plugins/packaging/setup.cfg | 29 +++ .../deephaven/plugin/packaging/__init__.py | 1 + .../src/deephaven/plugin/packaging/utils.py | 41 ++++ plugins/utilities/README.md | 3 +- .../deephaven/plugin/utilities/__init__.py | 1 + .../utilities/dhe_safe_callback_wrapper.py | 52 +++++ .../src/deephaven/plugin/utilities/utils.py | 62 +----- tools/update_version.sh | 3 + 14 files changed, 377 insertions(+), 61 deletions(-) create mode 100644 plugins/packaging/.gitignore create mode 100644 plugins/packaging/LICENSE create mode 100644 plugins/packaging/README.md create mode 100644 plugins/packaging/pyproject.toml create mode 100644 plugins/packaging/setup.cfg create mode 100644 plugins/packaging/src/deephaven/plugin/packaging/__init__.py create mode 100644 plugins/packaging/src/deephaven/plugin/packaging/utils.py create mode 100644 plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py diff --git a/.github/workflows/modified-plugin.yml b/.github/workflows/modified-plugin.yml index 00a96cb4d..f7e3ec601 100644 --- a/.github/workflows/modified-plugin.yml +++ b/.github/workflows/modified-plugin.yml @@ -11,7 +11,8 @@ on: - 'matplotlib-v*' - 'json-v*' - 'ui-v*' - - 'utilities-v*' + - 'packaging-v*' + - 'packaging-v*' jobs: changes: @@ -34,6 +35,7 @@ jobs: json: plugins/json/** ui: plugins/ui/** utilities: plugins/utilities/** + packaging: plugins/packaging/** # Test all python packages that have been modified individually test-python: diff --git a/.github/workflows/release-python-package.yml b/.github/workflows/release-python-package.yml index 5b4441f07..8f9c7e804 100644 --- a/.github/workflows/release-python-package.yml +++ b/.github/workflows/release-python-package.yml @@ -32,8 +32,8 @@ jobs: run: npm ci - name: Build npm packages - # utilities package does not have any npm package to build - if : ${{ inputs.package != 'utilities' }} + # packaging and packaging packages do not have npm packages to build + if : ${{ inputs.package != 'packaging' && inputs.package != 'packaging' }} run: npm run build -- --scope "@deephaven/js-plugin-${{ inputs.package }}" - name: Set up Python diff --git a/plugins/packaging/.gitignore b/plugins/packaging/.gitignore new file mode 100644 index 000000000..3356dc1ce --- /dev/null +++ b/plugins/packaging/.gitignore @@ -0,0 +1,8 @@ +build/ +dist/ +.venv/ +/venv +*.egg-info/ +.idea +.DS_store +__pycache__/ \ No newline at end of file diff --git a/plugins/packaging/LICENSE b/plugins/packaging/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/plugins/packaging/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/plugins/packaging/README.md b/plugins/packaging/README.md new file mode 100644 index 000000000..6f83ea754 --- /dev/null +++ b/plugins/packaging/README.md @@ -0,0 +1,25 @@ +# Deephaven Plugin Packaging + +This is a Python package that stores cross-plugin utilities for packaging Deephaven plugins. +This package is used by the Deephaven plugin build process to create wheels for plugins. +If the functions need to be available at runtime, they should be added to `utilities` instead. +This is not a plugin on its own. + +## Build + +To create your build / development environment (skip the first two lines if you already have a venv): + +```sh +python -m venv .venv +source .venv/bin/activate +pip install --upgrade pip setuptools +pip install build +``` + +To build: + +```sh +python -m build --wheel +``` + +The wheel is stored in `dist/`. diff --git a/plugins/packaging/pyproject.toml b/plugins/packaging/pyproject.toml new file mode 100644 index 000000000..62df2b006 --- /dev/null +++ b/plugins/packaging/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools>=43.0.0", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/plugins/packaging/setup.cfg b/plugins/packaging/setup.cfg new file mode 100644 index 000000000..1d2e14b16 --- /dev/null +++ b/plugins/packaging/setup.cfg @@ -0,0 +1,29 @@ +[metadata] +name = deephaven-plugin-packaging +description = Deephaven Plugin Packaging +long_description = file: README.md +long_description_content_type = text/markdown +version = 0.0.1.dev0 +url = https://github.com/deephaven/deephaven-plugins +project_urls = + Source Code = https://github.com/deephaven/deephaven-plugins + Bug Tracker = https://github.com/deephaven/deephaven-plugins/issues +classifiers = + Programming Language :: Python :: 3 + License :: OSI Approved :: Apache Software License + Operating System :: OS Independent + Environment :: Plugins + Development Status :: 3 - Alpha +keywords = deephaven, plugin, packaging +author = Joe Numainville +author_email = josephnumainville@deephaven.io +platforms = any + +[options] +package_dir= + =src +packages=find_namespace: +include_package_data = True + +[options.packages.find] +where=src diff --git a/plugins/packaging/src/deephaven/plugin/packaging/__init__.py b/plugins/packaging/src/deephaven/plugin/packaging/__init__.py new file mode 100644 index 000000000..16281fe0b --- /dev/null +++ b/plugins/packaging/src/deephaven/plugin/packaging/__init__.py @@ -0,0 +1 @@ +from .utils import * diff --git a/plugins/packaging/src/deephaven/plugin/packaging/utils.py b/plugins/packaging/src/deephaven/plugin/packaging/utils.py new file mode 100644 index 000000000..cc4bb6f69 --- /dev/null +++ b/plugins/packaging/src/deephaven/plugin/packaging/utils.py @@ -0,0 +1,41 @@ +import shutil +import os +import subprocess + + +def package_js(js_dir: str, dest_dir: str) -> None: + """ + Package the built JS files at the given JS directory and unpack them into the destination directory. + + Args: + js_dir: + The directory containing the JS files + dest_dir: + The directory to unpack the JS files into + """ + dist_dir = os.path.join(js_dir, "dist") + build_dir = os.path.join(js_dir, "build") + package_dir = os.path.join(build_dir, "package") + + # copy the bundle to the directory + # the path may not exist (e.g. when running tests) + # so it is not strictly necessary to copy the bundle + if os.path.exists(dist_dir): + # ignore errors as the directory may not exist + shutil.rmtree(build_dir, ignore_errors=True) + shutil.rmtree(dest_dir, ignore_errors=True) + + os.makedirs(build_dir, exist_ok=True) + + # pack and unpack into the js directory + subprocess.run( + ["npm", "pack", "--pack-destination", "build"], cwd=js_dir, check=True + ) + # it is assumed that there is only one tarball in the directory + files = os.listdir(build_dir) + for file in files: + subprocess.run(["tar", "-xzf", file], cwd=build_dir, check=True) + os.remove(os.path.join(build_dir, file)) + + # move the package directory to the expected package location + shutil.move(package_dir, dest_dir) diff --git a/plugins/utilities/README.md b/plugins/utilities/README.md index fb224f9c3..48f8ac1c0 100644 --- a/plugins/utilities/README.md +++ b/plugins/utilities/README.md @@ -1,7 +1,8 @@ # Deephaven Plugin Utilities This is a Python package that stores cross-plugin utilities for building Deephaven plugins. -It is not a plugin itself. +If the functions are only used during the build process, they should be added to `packaging` instead. +This is not a plugin on its own. ## Build diff --git a/plugins/utilities/src/deephaven/plugin/utilities/__init__.py b/plugins/utilities/src/deephaven/plugin/utilities/__init__.py index 16281fe0b..1b2cca4e7 100644 --- a/plugins/utilities/src/deephaven/plugin/utilities/__init__.py +++ b/plugins/utilities/src/deephaven/plugin/utilities/__init__.py @@ -1 +1,2 @@ from .utils import * +from .dhe_safe_callback_wrapper import * diff --git a/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py b/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py new file mode 100644 index 000000000..d02302075 --- /dev/null +++ b/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py @@ -0,0 +1,52 @@ +from deephaven.plugin import Callback, Plugin +import logging +from deephaven.plugin.js import JsPlugin +from .utils import in_enterprise_environment + +logger = logging.getLogger(__name__) + + +class DheSafeCallbackWrapper: + """ + + A wrapper around the Callback class that provides a safe way to register plugins. + + """ + + def __init__(self, callback: Callback): + self._callback = callback + + def register(self, plugin: Plugin) -> None: + """ + Register a plugin with the provided callback + + Args: + plugin: The plugin to register + + """ + if isinstance(plugin, JsPlugin): + self._register_js(plugin) + else: + self._callback.register(plugin) + + def _register_js(self, js_plugin: JsPlugin) -> None: + """ + Attempt to register a JS plugin. + If failed and enterprise is detected, a debug message will be logged. + If failed and enterprise is not detected, an exception will be raised. + + Args: + js_plugin: + The JS plugin to register + """ + try: + self._callback.register(js_plugin) + except RuntimeError as e: + if in_enterprise_environment(): + logger.debug( + f"Failed to register {js_plugin} embedded in Python plugin. Skipping." + ) + else: + raise RuntimeError( + f"Failed to register {js_plugin} embedded in Python plugin: {e}" + ) diff --git a/plugins/utilities/src/deephaven/plugin/utilities/utils.py b/plugins/utilities/src/deephaven/plugin/utilities/utils.py index 6c1543c65..f6d71bafb 100644 --- a/plugins/utilities/src/deephaven/plugin/utilities/utils.py +++ b/plugins/utilities/src/deephaven/plugin/utilities/utils.py @@ -1,77 +1,25 @@ import abc import logging -import shutil import os -import subprocess from functools import partial from typing import Callable, ContextManager import importlib.resources import json import pathlib import sys -from deephaven.plugin import Callback from deephaven.plugin.js import JsPlugin logger = logging.getLogger(__name__) -def package_js(js_dir: str, dest_dir: str) -> None: +def in_enterprise_environment() -> bool: """ - Package the built JS files at the given JS directory and unpack them into the destination directory. + Check if the environment is an enterprise environment. - Args: - js_dir: - The directory containing the JS files - dest_dir: - The directory to unpack the JS files into - """ - dist_dir = os.path.join(js_dir, "dist") - build_dir = os.path.join(js_dir, "build") - package_dir = os.path.join(build_dir, "package") - - # copy the bundle to the directory - # the path may not exist (e.g. when running tests) - # so it is not strictly necessary to copy the bundle - if os.path.exists(dist_dir): - # ignore errors as the directory may not exist - shutil.rmtree(build_dir, ignore_errors=True) - shutil.rmtree(dest_dir, ignore_errors=True) - - os.makedirs(build_dir, exist_ok=True) - - # pack and unpack into the js directory - subprocess.run( - ["npm", "pack", "--pack-destination", "build"], cwd=js_dir, check=True - ) - # it is assumed that there is only one tarball in the directory - files = os.listdir(build_dir) - for file in files: - subprocess.run(["tar", "-xzf", file], cwd=build_dir, check=True) - os.remove(os.path.join(build_dir, file)) - - # move the package directory to the expected package location - shutil.move(package_dir, dest_dir) - - -def attempt_registration(callback: Callback, js_plugin: JsPlugin) -> None: - """ - Attempt to register a JS plugin. - If failed, and enterprise is not detected, it will log as a warning and continue. - - Args: - callback: - A callback to register the JS plugin - js_plugin: - The JS plugin to register + Returns: + True if the environment is an enterprise environment, False otherwise """ - try: - callback.register(js_plugin) - except RuntimeError: - # warning should only be logged if enterprise is not detected - if not os.path.exists("/usr/illumon/latest/bin"): - logger.warning( - f"Failed to register {js_plugin} embedded in python plugin. Skipping." - ) + return any("coreplus" in path or "dnd" in path for path in sys.path) def _create_from_npm_package_json( diff --git a/tools/update_version.sh b/tools/update_version.sh index 9279484c5..0eee3ab85 100755 --- a/tools/update_version.sh +++ b/tools/update_version.sh @@ -142,6 +142,9 @@ case "$package" in utilities) update_file utilities/setup.cfg 'version = ' '' "$extra" ;; + packaging) + update_file packaging/setup.cfg 'version = ' '' "$extra" + ;; *) { log_error "Unhandled plugin $package. You will need to add wiring in $SCRIPT_NAME" From 5589f163610313e4575626d23f8264ad4486b142 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Thu, 29 Feb 2024 16:14:29 -0600 Subject: [PATCH 03/15] fix --- .github/workflows/modified-plugin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/modified-plugin.yml b/.github/workflows/modified-plugin.yml index f7e3ec601..eebae4032 100644 --- a/.github/workflows/modified-plugin.yml +++ b/.github/workflows/modified-plugin.yml @@ -11,7 +11,7 @@ on: - 'matplotlib-v*' - 'json-v*' - 'ui-v*' - - 'packaging-v*' + - 'utilities-v*' - 'packaging-v*' jobs: From 050a18f26ec14ea821a8e2d7196c9659f9b178c6 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Thu, 29 Feb 2024 16:15:57 -0600 Subject: [PATCH 04/15] silly --- .github/workflows/release-python-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-python-package.yml b/.github/workflows/release-python-package.yml index 8f9c7e804..2e9a51ec9 100644 --- a/.github/workflows/release-python-package.yml +++ b/.github/workflows/release-python-package.yml @@ -32,8 +32,8 @@ jobs: run: npm ci - name: Build npm packages - # packaging and packaging packages do not have npm packages to build - if : ${{ inputs.package != 'packaging' && inputs.package != 'packaging' }} + # utilities and packaging packages do not have npm packages to build + if : ${{ inputs.package != 'utilities' && inputs.package != 'packaging' }} run: npm run build -- --scope "@deephaven/js-plugin-${{ inputs.package }}" - name: Set up Python From 1639b799f36d80e974a69c6ff136846c66ae6988 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Thu, 29 Feb 2024 17:20:29 -0600 Subject: [PATCH 05/15] comments --- .../packaging/src/deephaven/plugin/packaging/utils.py | 2 ++ .../plugin/utilities/dhe_safe_callback_wrapper.py | 11 ++++++++--- .../utilities/src/deephaven/plugin/utilities/utils.py | 3 ++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/plugins/packaging/src/deephaven/plugin/packaging/utils.py b/plugins/packaging/src/deephaven/plugin/packaging/utils.py index cc4bb6f69..cfb1aa66d 100644 --- a/plugins/packaging/src/deephaven/plugin/packaging/utils.py +++ b/plugins/packaging/src/deephaven/plugin/packaging/utils.py @@ -2,6 +2,8 @@ import os import subprocess +__all__ = ["package_js"] + def package_js(js_dir: str, dest_dir: str) -> None: """ diff --git a/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py b/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py index d02302075..3754e2aaa 100644 --- a/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py +++ b/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py @@ -1,12 +1,17 @@ -from deephaven.plugin import Callback, Plugin +from __future__ import annotations + +from typing import Type import logging +from deephaven.plugin import Callback, Plugin from deephaven.plugin.js import JsPlugin from .utils import in_enterprise_environment logger = logging.getLogger(__name__) +__all__ = ["DheSafeCallbackWrapper"] + -class DheSafeCallbackWrapper: +class DheSafeCallbackWrapper(Callback): """ A wrapper around the Callback class that provides a safe way to register plugins. @@ -16,7 +21,7 @@ class DheSafeCallbackWrapper: def __init__(self, callback: Callback): self._callback = callback - def register(self, plugin: Plugin) -> None: + def register(self, plugin: Plugin | Type[Plugin]) -> None: """ Register a plugin with the provided callback diff --git a/plugins/utilities/src/deephaven/plugin/utilities/utils.py b/plugins/utilities/src/deephaven/plugin/utilities/utils.py index f6d71bafb..7afce6990 100644 --- a/plugins/utilities/src/deephaven/plugin/utilities/utils.py +++ b/plugins/utilities/src/deephaven/plugin/utilities/utils.py @@ -1,6 +1,5 @@ import abc import logging -import os from functools import partial from typing import Callable, ContextManager import importlib.resources @@ -11,6 +10,8 @@ logger = logging.getLogger(__name__) +__all__ = ["in_enterprise_environment", "create_js_plugin"] + def in_enterprise_environment() -> bool: """ From 56fd0e61dd6f203f69b105f883d2ae9bc2e6cc20 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 4 Mar 2024 13:42:30 -0600 Subject: [PATCH 06/15] comments --- .github/workflows/release-python-package.yml | 16 +++++++++++----- .../utilities/dhe_safe_callback_wrapper.py | 4 ++-- .../src/deephaven/plugin/utilities/utils.py | 5 +++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release-python-package.yml b/.github/workflows/release-python-package.yml index 2e9a51ec9..8b8171b15 100644 --- a/.github/workflows/release-python-package.yml +++ b/.github/workflows/release-python-package.yml @@ -28,13 +28,19 @@ jobs: node-version: '18.x' registry-url: 'https://registry.npmjs.org' + - name: Check file existence + id: check_files + uses: andstor/file-existence-action@v3 + with: + files: "plugins/${{ inputs.package }}/src/deephaven/js/package.json" + - name: Install npm dependencies - run: npm ci - + if: steps.check_files.outputs.files_exists == 'true' + run: npm install + - name: Build npm packages - # utilities and packaging packages do not have npm packages to build - if : ${{ inputs.package != 'utilities' && inputs.package != 'packaging' }} - run: npm run build -- --scope "@deephaven/js-plugin-${{ inputs.package }}" + if: steps.check_files.outputs.files_exists == 'true' + run: npm run build - name: Set up Python uses: actions/setup-python@v4 diff --git a/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py b/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py index 3754e2aaa..f9fb94a26 100644 --- a/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py +++ b/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py @@ -4,7 +4,7 @@ import logging from deephaven.plugin import Callback, Plugin from deephaven.plugin.js import JsPlugin -from .utils import in_enterprise_environment +from .utils import is_enterprise_environment logger = logging.getLogger(__name__) @@ -47,7 +47,7 @@ def _register_js(self, js_plugin: JsPlugin) -> None: try: self._callback.register(js_plugin) except RuntimeError as e: - if in_enterprise_environment(): + if is_enterprise_environment(): logger.debug( f"Failed to register {js_plugin} embedded in Python plugin. Skipping." ) diff --git a/plugins/utilities/src/deephaven/plugin/utilities/utils.py b/plugins/utilities/src/deephaven/plugin/utilities/utils.py index 7afce6990..62bbe0a0f 100644 --- a/plugins/utilities/src/deephaven/plugin/utilities/utils.py +++ b/plugins/utilities/src/deephaven/plugin/utilities/utils.py @@ -10,16 +10,17 @@ logger = logging.getLogger(__name__) -__all__ = ["in_enterprise_environment", "create_js_plugin"] +__all__ = ["is_enterprise_environment", "create_js_plugin"] -def in_enterprise_environment() -> bool: +def is_enterprise_environment() -> bool: """ Check if the environment is an enterprise environment. Returns: True if the environment is an enterprise environment, False otherwise """ + # TODO: better implementation after https://deephaven.atlassian.net/browse/DH-16573 return any("coreplus" in path or "dnd" in path for path in sys.path) From 43024a90c12feb9494d5c24d941425a656ddcc0b Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 4 Mar 2024 14:10:33 -0600 Subject: [PATCH 07/15] wip --- plugins/matplotlib/pyproject.toml | 2 +- plugins/matplotlib/setup.cfg | 2 +- plugins/matplotlib/setup.py | 11 +++++ .../deephaven/plugin/matplotlib/__init__.py | 23 ----------- .../deephaven/plugin/matplotlib/_js_plugin.py | 32 +++++++++++++++ .../deephaven/plugin/matplotlib/_register.py | 39 ++++++++++++++++++ plugins/plotly-express/pyproject.toml | 2 +- plugins/plotly-express/setup.py | 32 +-------------- .../src/deephaven/plot/express/_js_plugin.py | 41 ------------------- .../src/deephaven/plot/express/_register.py | 21 +++++++--- plugins/ui/pyproject.toml | 2 +- plugins/ui/setup.cfg | 2 +- plugins/ui/setup.py | 10 +++++ plugins/ui/src/deephaven/ui/__init__.py | 8 ---- plugins/ui/src/deephaven/ui/_js_plugin.py | 32 +++++++++++++++ plugins/ui/src/deephaven/ui/_register.py | 27 ++++++++++++ 16 files changed, 173 insertions(+), 113 deletions(-) create mode 100644 plugins/matplotlib/setup.py create mode 100644 plugins/matplotlib/src/deephaven/plugin/matplotlib/_js_plugin.py create mode 100644 plugins/matplotlib/src/deephaven/plugin/matplotlib/_register.py create mode 100644 plugins/ui/setup.py create mode 100644 plugins/ui/src/deephaven/ui/_js_plugin.py create mode 100644 plugins/ui/src/deephaven/ui/_register.py diff --git a/plugins/matplotlib/pyproject.toml b/plugins/matplotlib/pyproject.toml index 62df2b006..54e217464 100644 --- a/plugins/matplotlib/pyproject.toml +++ b/plugins/matplotlib/pyproject.toml @@ -1,3 +1,3 @@ [build-system] -requires = ["setuptools>=43.0.0", "wheel"] +requires = ["setuptools>=43.0.0", "wheel", "deephaven-plugin-packaging"] build-backend = "setuptools.build_meta" diff --git a/plugins/matplotlib/setup.cfg b/plugins/matplotlib/setup.cfg index 5052d68f7..3bca03613 100644 --- a/plugins/matplotlib/setup.cfg +++ b/plugins/matplotlib/setup.cfg @@ -43,4 +43,4 @@ where=src [options.entry_points] deephaven.plugin = - registration_cls = deephaven.plugin.matplotlib:MatplotlibRegistration \ No newline at end of file + registration_cls = deephaven.plugin.matplotlib._register:MatplotlibRegistration \ No newline at end of file diff --git a/plugins/matplotlib/setup.py b/plugins/matplotlib/setup.py new file mode 100644 index 000000000..674bdf627 --- /dev/null +++ b/plugins/matplotlib/setup.py @@ -0,0 +1,11 @@ +from setuptools import setup +import os + +from deephaven.plugin.packaging import package_js + +js_dir = "src/js/" +dest_dir = os.path.join("src/deephaven/plugin/matplotlib/_js") + +package_js(js_dir, dest_dir) + +setup(package_data={"deephaven.plugin.matplotlib._js": ["**"]}) diff --git a/plugins/matplotlib/src/deephaven/plugin/matplotlib/__init__.py b/plugins/matplotlib/src/deephaven/plugin/matplotlib/__init__.py index 17491fe08..590530d9e 100644 --- a/plugins/matplotlib/src/deephaven/plugin/matplotlib/__init__.py +++ b/plugins/matplotlib/src/deephaven/plugin/matplotlib/__init__.py @@ -1,32 +1,9 @@ from deephaven import numpy as dhnp -from deephaven.plugin import Registration, Callback from deephaven.table_listener import listen -from importlib import resources -import matplotlib.pyplot as plt from matplotlib.animation import Animation import itertools -def _init_theme(): - # Set the Deephaven style globally. - # We use the savefig function to export the Figure, and that uses the Figure's properties for colours rather than temporary styling. - # The Figure's properties are set on creation time of the Figure, rather than when the Figure is exported - # We do not have hooks into when a user creates a new Figure, so we set the theme globally ahead of time - # https://github.com/matplotlib/matplotlib/issues/6592/ - with resources.path(__package__, "deephaven.mplstyle") as p: - plt.style.use(["dark_background", p]) - - -class MatplotlibRegistration(Registration): - @classmethod - def register_into(cls, callback: Callback) -> None: - _init_theme() - plt.switch_backend("AGG") - from . import figure_type - - callback.register(figure_type.FigureType) - - class TableEventSource: """ Makes an event source for matplotlib that triggers whenever Deephaven Table updates. diff --git a/plugins/matplotlib/src/deephaven/plugin/matplotlib/_js_plugin.py b/plugins/matplotlib/src/deephaven/plugin/matplotlib/_js_plugin.py new file mode 100644 index 000000000..7c2e9bf65 --- /dev/null +++ b/plugins/matplotlib/src/deephaven/plugin/matplotlib/_js_plugin.py @@ -0,0 +1,32 @@ +import pathlib + +from deephaven.plugin.js import JsPlugin + + +class MatplotlibJsPlugin(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 diff --git a/plugins/matplotlib/src/deephaven/plugin/matplotlib/_register.py b/plugins/matplotlib/src/deephaven/plugin/matplotlib/_register.py new file mode 100644 index 000000000..d48a26aee --- /dev/null +++ b/plugins/matplotlib/src/deephaven/plugin/matplotlib/_register.py @@ -0,0 +1,39 @@ +from importlib import resources +import matplotlib.pyplot as plt +from deephaven.plugin import Registration, Callback +from deephaven.plugin.utilities import create_js_plugin, DheSafeCallbackWrapper +from ._js_plugin import MatplotlibJsPlugin + +PACKAGE_NAMESPACE = "deephaven.plot.express" +JS_NAME = "_js" +PLUGIN_CLASS = MatplotlibJsPlugin + + +def _init_theme(): + # Set the Deephaven style globally. + # We use the savefig function to export the Figure, and that uses the Figure's properties for colours rather than temporary styling. + # The Figure's properties are set on creation time of the Figure, rather than when the Figure is exported + # We do not have hooks into when a user creates a new Figure, so we set the theme globally ahead of time + # https://github.com/matplotlib/matplotlib/issues/6592/ + with resources.path(__package__, "deephaven.mplstyle") as p: + plt.style.use(["dark_background", p]) + + +class MatplotlibRegistration(Registration): + @classmethod + def register_into(cls, callback: Callback) -> None: + _init_theme() + plt.switch_backend("AGG") + from . import figure_type + + callback = DheSafeCallbackWrapper(callback) + + callback.register(figure_type.FigureType) + + js_plugin = create_js_plugin( + PACKAGE_NAMESPACE, + JS_NAME, + PLUGIN_CLASS, + ) + + callback.register(js_plugin) diff --git a/plugins/plotly-express/pyproject.toml b/plugins/plotly-express/pyproject.toml index 62df2b006..54e217464 100644 --- a/plugins/plotly-express/pyproject.toml +++ b/plugins/plotly-express/pyproject.toml @@ -1,3 +1,3 @@ [build-system] -requires = ["setuptools>=43.0.0", "wheel"] +requires = ["setuptools>=43.0.0", "wheel", "deephaven-plugin-packaging"] build-backend = "setuptools.build_meta" diff --git a/plugins/plotly-express/setup.py b/plugins/plotly-express/setup.py index 730690ce9..484dcc8aa 100644 --- a/plugins/plotly-express/setup.py +++ b/plugins/plotly-express/setup.py @@ -1,38 +1,10 @@ -import shutil from setuptools import setup import os -import subprocess - -# Uses npm pack to create a tarball of the package and unpacks it into a build directory -# Then uses that to add to the wheel +from deephaven.plugin.packaging import package_js js_dir = "src/js/" -dist_dir = os.path.join(js_dir, "dist") -build_dir = os.path.join(js_dir, "build") dest_dir = os.path.join("src/deephaven/plot/express/_js") -package_dir = os.path.join(build_dir, "package") - -# copy the bundle to the plotly-express directory -# the path may not exist (e.g. when running tests) -# so it is not strictly necessary to copy the bundle -if os.path.exists(dist_dir): - # ignore errors as the directory may not exist - shutil.rmtree(build_dir, ignore_errors=True) - shutil.rmtree(dest_dir, ignore_errors=True) - - os.makedirs(build_dir, exist_ok=True) - - # pack and unpack into the js plotly-express directory - subprocess.run( - ["npm", "pack", "--pack-destination", "build"], cwd=js_dir, check=True - ) - # it is assumed that there is only one tarball in the directory - files = os.listdir(build_dir) - for file in files: - subprocess.run(["tar", "-xzf", file], cwd=build_dir, check=True) - os.remove(os.path.join(build_dir, file)) - # move the package directory to the expected package location - shutil.move(package_dir, dest_dir) +package_js(js_dir, dest_dir) setup(package_data={"deephaven.plot.express._js": ["**"]}) diff --git a/plugins/plotly-express/src/deephaven/plot/express/_js_plugin.py b/plugins/plotly-express/src/deephaven/plot/express/_js_plugin.py index 3df3011f9..f1df67cba 100644 --- a/plugins/plotly-express/src/deephaven/plot/express/_js_plugin.py +++ b/plugins/plotly-express/src/deephaven/plot/express/_js_plugin.py @@ -1,8 +1,4 @@ -import importlib.resources -import json import pathlib -import sys -from typing import Callable, ContextManager from deephaven.plugin.js import JsPlugin @@ -34,40 +30,3 @@ def main(self) -> str: 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]: - namespace = "deephaven.plot.express" - name = "_js" - if sys.version_info < (3, 9): - return importlib.resources.path(namespace, name) - else: - return importlib.resources.as_file( - importlib.resources.files(namespace).joinpath(name) - ) - - -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 index f3f638ba5..34d2383ee 100644 --- a/plugins/plotly-express/src/deephaven/plot/express/_register.py +++ b/plugins/plotly-express/src/deephaven/plot/express/_register.py @@ -1,8 +1,11 @@ -import os +from deephaven.plugin import Registration, Callback +from deephaven.plugin.utilities import create_js_plugin, DheSafeCallbackWrapper from . import DeephavenFigureType -from ._js_plugin import create_js_plugin +from ._js_plugin import ExpressJsPlugin -from deephaven.plugin import Registration, Callback +PACKAGE_NAMESPACE = "deephaven.plot.express" +JS_NAME = "_js" +PLUGIN_CLASS = ExpressJsPlugin class ExpressRegistration(Registration): @@ -21,8 +24,14 @@ def register_into(cls, callback: Callback) -> None: A function to call after registration """ + callback = DheSafeCallbackWrapper(callback) + callback.register(DeephavenFigureType) - # Only register the JS plugins if the environment variable is set - if os.getenv("DEEPHAVEN_ENABLE_PY_JS", "False").lower() in ("true", "1"): - callback.register(create_js_plugin()) + js_plugin = create_js_plugin( + PACKAGE_NAMESPACE, + JS_NAME, + PLUGIN_CLASS, + ) + + callback.register(js_plugin) diff --git a/plugins/ui/pyproject.toml b/plugins/ui/pyproject.toml index 62df2b006..54e217464 100644 --- a/plugins/ui/pyproject.toml +++ b/plugins/ui/pyproject.toml @@ -1,3 +1,3 @@ [build-system] -requires = ["setuptools>=43.0.0", "wheel"] +requires = ["setuptools>=43.0.0", "wheel", "deephaven-plugin-packaging"] build-backend = "setuptools.build_meta" diff --git a/plugins/ui/setup.cfg b/plugins/ui/setup.cfg index cc9bb3235..764c64778 100644 --- a/plugins/ui/setup.cfg +++ b/plugins/ui/setup.cfg @@ -35,4 +35,4 @@ where=src [options.entry_points] deephaven.plugin = - registration_cls = deephaven.ui:UIRegistration + registration_cls = deephaven.ui._register:UIRegistration diff --git a/plugins/ui/setup.py b/plugins/ui/setup.py new file mode 100644 index 000000000..29b112d5b --- /dev/null +++ b/plugins/ui/setup.py @@ -0,0 +1,10 @@ +from setuptools import setup +import os +from deephaven.plugin.packaging import package_js + +js_dir = "src/js/" +dest_dir = os.path.join("src/deephaven/ui/_js") + +package_js(js_dir, dest_dir) + +setup(package_data={"deephaven.ui._js": ["**"]}) diff --git a/plugins/ui/src/deephaven/ui/__init__.py b/plugins/ui/src/deephaven/ui/__init__.py index ff607c414..f501f3812 100644 --- a/plugins/ui/src/deephaven/ui/__init__.py +++ b/plugins/ui/src/deephaven/ui/__init__.py @@ -4,17 +4,9 @@ The API is designed to be similar to React, but with some differences to make it more Pythonic. """ -from deephaven.plugin import Registration, Callback from .components import * from .elements import * from .hooks import * from .object_types import * __version__ = "0.7.0.dev0" - - -class UIRegistration(Registration): - @classmethod - def register_into(cls, callback: Callback) -> None: - callback.register(DashboardType) - callback.register(ElementType) diff --git a/plugins/ui/src/deephaven/ui/_js_plugin.py b/plugins/ui/src/deephaven/ui/_js_plugin.py new file mode 100644 index 000000000..fa3b9a05e --- /dev/null +++ b/plugins/ui/src/deephaven/ui/_js_plugin.py @@ -0,0 +1,32 @@ +import pathlib + +from deephaven.plugin.js import JsPlugin + + +class UiJsPlugin(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 diff --git a/plugins/ui/src/deephaven/ui/_register.py b/plugins/ui/src/deephaven/ui/_register.py new file mode 100644 index 000000000..3dfe4502b --- /dev/null +++ b/plugins/ui/src/deephaven/ui/_register.py @@ -0,0 +1,27 @@ +from . import DashboardType, ElementType +from deephaven.plugin import Registration, Callback +from deephaven.plugin.utilities import create_js_plugin, DheSafeCallbackWrapper + +from ._js_plugin import UiJsPlugin + +PACKAGE_NAMESPACE = "deephaven.ui" +JS_NAME = "_js" +PLUGIN_CLASS = UiJsPlugin + + +class UIRegistration(Registration): + @classmethod + def register_into(cls, callback: Callback) -> None: + + callback = DheSafeCallbackWrapper(callback) + + callback.register(DashboardType) + callback.register(ElementType) + + js_plugin = create_js_plugin( + PACKAGE_NAMESPACE, + JS_NAME, + PLUGIN_CLASS, + ) + + callback.register(js_plugin) From eacda880c6a5d4bc31d9984801472858b89d03d0 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Tue, 5 Mar 2024 09:42:26 -0600 Subject: [PATCH 08/15] silly mistakes --- .github/workflows/release-python-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-python-package.yml b/.github/workflows/release-python-package.yml index 8b8171b15..adebdbe90 100644 --- a/.github/workflows/release-python-package.yml +++ b/.github/workflows/release-python-package.yml @@ -32,15 +32,15 @@ jobs: id: check_files uses: andstor/file-existence-action@v3 with: - files: "plugins/${{ inputs.package }}/src/deephaven/js/package.json" + files: "plugins/${{ inputs.package }}/src/js/package.json" - name: Install npm dependencies if: steps.check_files.outputs.files_exists == 'true' - run: npm install + run: npm ci - name: Build npm packages if: steps.check_files.outputs.files_exists == 'true' - run: npm run build + run: npm run build -- --scope "@deephaven/js-plugin-${{ inputs.package }}" - name: Set up Python uses: actions/setup-python@v4 From eaa9a6065a2bc00f3df2e2b42b1216fd6810fe24 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Tue, 5 Mar 2024 09:43:22 -0600 Subject: [PATCH 09/15] remove space --- .github/workflows/release-python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-python-package.yml b/.github/workflows/release-python-package.yml index adebdbe90..c8045590a 100644 --- a/.github/workflows/release-python-package.yml +++ b/.github/workflows/release-python-package.yml @@ -37,7 +37,7 @@ jobs: - name: Install npm dependencies if: steps.check_files.outputs.files_exists == 'true' run: npm ci - + - name: Build npm packages if: steps.check_files.outputs.files_exists == 'true' run: npm run build -- --scope "@deephaven/js-plugin-${{ inputs.package }}" From 8142c521fad7e16e23dbbb9a073d29217a637b57 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Wed, 6 Mar 2024 10:30:04 -0600 Subject: [PATCH 10/15] adding type --- .../deephaven/plugin/utilities/dhe_safe_callback_wrapper.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py b/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py index f9fb94a26..21c9034e8 100644 --- a/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py +++ b/plugins/utilities/src/deephaven/plugin/utilities/dhe_safe_callback_wrapper.py @@ -29,12 +29,14 @@ def register(self, plugin: Plugin | Type[Plugin]) -> None: plugin: The plugin to register """ - if isinstance(plugin, JsPlugin): + if isinstance(plugin, JsPlugin) or ( + isinstance(plugin, type) and issubclass(plugin, JsPlugin) + ): self._register_js(plugin) else: self._callback.register(plugin) - def _register_js(self, js_plugin: JsPlugin) -> None: + def _register_js(self, js_plugin: JsPlugin | Type[JsPlugin]) -> None: """ Attempt to register a JS plugin. If failed and enterprise is detected, a debug message will be logged. From ac93088e74f194ee6316a874a6cf1f54a7f7dfdd Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Wed, 6 Mar 2024 11:04:27 -0600 Subject: [PATCH 11/15] adding config --- plugins/matplotlib/setup.cfg | 1 + plugins/plotly-express/setup.cfg | 1 + plugins/ui/setup.cfg | 1 + 3 files changed, 3 insertions(+) diff --git a/plugins/matplotlib/setup.cfg b/plugins/matplotlib/setup.cfg index 3bca03613..e26737146 100644 --- a/plugins/matplotlib/setup.cfg +++ b/plugins/matplotlib/setup.cfg @@ -29,6 +29,7 @@ install_requires = jpy>=0.14.0 deephaven-plugin>=0.5.0 matplotlib + deephaven-plugin-utilities include_package_data = True [options.extras_require] diff --git a/plugins/plotly-express/setup.cfg b/plugins/plotly-express/setup.cfg index cb392eaf3..9c7fe8ff2 100644 --- a/plugins/plotly-express/setup.cfg +++ b/plugins/plotly-express/setup.cfg @@ -27,6 +27,7 @@ packages=find_namespace: install_requires = deephaven-plugin>=0.6.0 plotly + deephaven-plugin-utilities include_package_data = True [options.packages.find] diff --git a/plugins/ui/setup.cfg b/plugins/ui/setup.cfg index 764c64778..cceff40ea 100644 --- a/plugins/ui/setup.cfg +++ b/plugins/ui/setup.cfg @@ -28,6 +28,7 @@ install_requires = deephaven-core>=0.31.0 deephaven-plugin>=0.6.0 json-rpc + deephaven-plugin-utilities include_package_data = True [options.packages.find] From 5b4b26ba213ac17d0bb1e5392b3d52c4faab507c Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Wed, 6 Mar 2024 14:35:02 -0600 Subject: [PATCH 12/15] fix pre commit --- .pre-commit-config.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ef4506e65..69809928c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,8 @@ repos: deephaven-core, plotly, json-rpc, - matplotlib + matplotlib, + deephaven-plugin-utilities ] - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.2.2 From b842035c97c884f3559a11a7390840f874d80305 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Wed, 6 Mar 2024 15:30:16 -0600 Subject: [PATCH 13/15] fixed incorrect name --- plugins/matplotlib/src/deephaven/plugin/matplotlib/_register.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/matplotlib/src/deephaven/plugin/matplotlib/_register.py b/plugins/matplotlib/src/deephaven/plugin/matplotlib/_register.py index d48a26aee..33d18567a 100644 --- a/plugins/matplotlib/src/deephaven/plugin/matplotlib/_register.py +++ b/plugins/matplotlib/src/deephaven/plugin/matplotlib/_register.py @@ -4,7 +4,7 @@ from deephaven.plugin.utilities import create_js_plugin, DheSafeCallbackWrapper from ._js_plugin import MatplotlibJsPlugin -PACKAGE_NAMESPACE = "deephaven.plot.express" +PACKAGE_NAMESPACE = "deephaven.plugin.matplotlib" JS_NAME = "_js" PLUGIN_CLASS = MatplotlibJsPlugin From 986fc61fc5bf36099336dcf4fc6385ab1f536141 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Thu, 7 Mar 2024 13:18:23 -0600 Subject: [PATCH 14/15] comments --- cog.toml | 2 ++ docker/config/deephaven.prop | 2 -- plugins/matplotlib/setup.cfg | 3 --- plugins/matplotlib/setup.py | 7 ++++++- plugins/ui/setup.cfg | 2 +- plugins/ui/src/deephaven/ui/__init__.py | 2 -- tools/update_version.sh | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cog.toml b/cog.toml index d84f61c28..6d8c99871 100644 --- a/cog.toml +++ b/cog.toml @@ -76,4 +76,6 @@ plotly = { path = "plugins/plotly", public_api=false } plotly-express = { path = "plugins/plotly-express", public_api=false } table-example = { path = "plugins/table-example", public_api=false } ui = { path = "plugins/ui", public_api=false } +packaging = { path = "plugins/packaging", public_api=false } +utilities = { path = "plugins/utilities", public_api=false } diff --git a/docker/config/deephaven.prop b/docker/config/deephaven.prop index 114ab0959..e2ebeb879 100644 --- a/docker/config/deephaven.prop +++ b/docker/config/deephaven.prop @@ -3,8 +3,6 @@ includefiles=dh-defaults.prop deephaven.console.type=python # Add all plugins that you want installed here -deephaven.jsPlugins.@deephaven/js-plugin-matplotlib=/opt/deephaven/config/plugins/plugins/matplotlib/src/js -deephaven.jsPlugins.@deephaven/js-plugin-ui=/opt/deephaven/config/plugins/plugins/ui/src/js # Anonymous authentication so we don't need to put in a password AuthHandlers=io.deephaven.auth.AnonymousAuthenticationHandler \ No newline at end of file diff --git a/plugins/matplotlib/setup.cfg b/plugins/matplotlib/setup.cfg index e26737146..2f1f71a99 100644 --- a/plugins/matplotlib/setup.cfg +++ b/plugins/matplotlib/setup.cfg @@ -39,9 +39,6 @@ seaborn = [options.packages.find] where=src -[options.package_data] -* = *.mplstyle - [options.entry_points] deephaven.plugin = registration_cls = deephaven.plugin.matplotlib._register:MatplotlibRegistration \ No newline at end of file diff --git a/plugins/matplotlib/setup.py b/plugins/matplotlib/setup.py index 674bdf627..b8d654031 100644 --- a/plugins/matplotlib/setup.py +++ b/plugins/matplotlib/setup.py @@ -8,4 +8,9 @@ package_js(js_dir, dest_dir) -setup(package_data={"deephaven.plugin.matplotlib._js": ["**"]}) +setup( + package_data={ + "deephaven.plugin.matplotlib._js": ["**"], + "deephaven.plugin.matplotlib": ["deephaven.mplstyle"], + } +) diff --git a/plugins/ui/setup.cfg b/plugins/ui/setup.cfg index cceff40ea..d02678caf 100644 --- a/plugins/ui/setup.cfg +++ b/plugins/ui/setup.cfg @@ -3,7 +3,7 @@ name = deephaven-plugin-ui description = deephaven.ui plugin long_description = file: README.md long_description_content_type = text/markdown -version = attr:deephaven.ui.__version__ +version = 0.8.0.dev0 url = https://github.com/deephaven/deephaven-plugins project_urls = Source Code = https://github.com/deephaven/deephaven-plugins diff --git a/plugins/ui/src/deephaven/ui/__init__.py b/plugins/ui/src/deephaven/ui/__init__.py index b0ef6dfc5..3b5ab4f7a 100644 --- a/plugins/ui/src/deephaven/ui/__init__.py +++ b/plugins/ui/src/deephaven/ui/__init__.py @@ -8,5 +8,3 @@ from .elements import * from .hooks import * from .object_types import * - -__version__ = "0.8.0.dev0" diff --git a/tools/update_version.sh b/tools/update_version.sh index 0eee3ab85..4f89bdf24 100755 --- a/tools/update_version.sh +++ b/tools/update_version.sh @@ -137,7 +137,7 @@ case "$package" in ;; ui) update_file ui/src/js/package.json '"version": "' '",' - update_file ui/src/deephaven/ui/__init__.py '__version__ = "' '"' "$extra" + update_file ui/src/setup.cfg 'version = ' '' "$extra" ;; utilities) update_file utilities/setup.cfg 'version = ' '' "$extra" From f0ea670bfd43d4328d9110387c052d45faaf8ffe Mon Sep 17 00:00:00 2001 From: Joe Date: Wed, 13 Mar 2024 14:16:01 -0500 Subject: [PATCH 15/15] Update docker/config/deephaven.prop Co-authored-by: Mike Bender --- docker/config/deephaven.prop | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/config/deephaven.prop b/docker/config/deephaven.prop index e2ebeb879..95662a24c 100644 --- a/docker/config/deephaven.prop +++ b/docker/config/deephaven.prop @@ -2,7 +2,6 @@ includefiles=dh-defaults.prop deephaven.console.type=python -# Add all plugins that you want installed here # Anonymous authentication so we don't need to put in a password AuthHandlers=io.deephaven.auth.AnonymousAuthenticationHandler \ No newline at end of file