From 9914b8e74806ad97d68deb52f0dda5303024fbed Mon Sep 17 00:00:00 2001 From: "Maarten A. Breddels" Date: Tue, 16 Jul 2024 15:53:23 +0200 Subject: [PATCH 1/5] feat: use solara for pyinstaller --- .github/workflows/standalone.yml | 2 +- standalone/hooks/hook-ipyreact.py | 5 +++++ standalone/hooks/hook-ipyvuetify.py | 5 +++++ standalone/hooks/hook-solara.py | 5 +++++ standalone/hooks/hook-solara_server.py | 5 +++++ standalone/hooks/hook-solara_ui.py | 5 +++++ standalone/jdaviz-cli-entrypoint.py | 23 +++-------------------- 7 files changed, 29 insertions(+), 21 deletions(-) create mode 100644 standalone/hooks/hook-ipyreact.py create mode 100644 standalone/hooks/hook-ipyvuetify.py create mode 100644 standalone/hooks/hook-solara.py create mode 100644 standalone/hooks/hook-solara_server.py create mode 100644 standalone/hooks/hook-solara_ui.py diff --git a/.github/workflows/standalone.yml b/.github/workflows/standalone.yml index c08bef512b..e12c1ed99b 100644 --- a/.github/workflows/standalone.yml +++ b/.github/workflows/standalone.yml @@ -53,7 +53,7 @@ jobs: - name: Wait for Voila to get online uses: ifaxity/wait-on-action@a7d13170ec542bdca4ef8ac4b15e9c6aa00a6866 # v1.2.1 with: - resource: tcp:8866 + resource: tcp:8765 timeout: 60000 - name: Test standalone diff --git a/standalone/hooks/hook-ipyreact.py b/standalone/hooks/hook-ipyreact.py new file mode 100644 index 0000000000..8a2acbaaeb --- /dev/null +++ b/standalone/hooks/hook-ipyreact.py @@ -0,0 +1,5 @@ +from PyInstaller.utils.hooks import collect_data_files, copy_metadata, collect_submodules + +hiddenimports = collect_submodules("ipyreact") +datas = collect_data_files("ipyreact") # codespell:ignore datas +datas += copy_metadata("ipyreact") # codespell:ignore datas diff --git a/standalone/hooks/hook-ipyvuetify.py b/standalone/hooks/hook-ipyvuetify.py new file mode 100644 index 0000000000..d3bee8c400 --- /dev/null +++ b/standalone/hooks/hook-ipyvuetify.py @@ -0,0 +1,5 @@ +from PyInstaller.utils.hooks import collect_data_files, copy_metadata, collect_submodules + +hiddenimports = collect_submodules("ipyvuetify") +datas = collect_data_files('ipyvuetify') +datas += copy_metadata('ipyvuetify') diff --git a/standalone/hooks/hook-solara.py b/standalone/hooks/hook-solara.py new file mode 100644 index 0000000000..0a51665040 --- /dev/null +++ b/standalone/hooks/hook-solara.py @@ -0,0 +1,5 @@ +from PyInstaller.utils.hooks import collect_data_files, copy_metadata, collect_submodules + +hiddenimports = collect_submodules("solara") +datas = collect_data_files('solara') +datas += collect_data_files('solara-ui') diff --git a/standalone/hooks/hook-solara_server.py b/standalone/hooks/hook-solara_server.py new file mode 100644 index 0000000000..227108ff6a --- /dev/null +++ b/standalone/hooks/hook-solara_server.py @@ -0,0 +1,5 @@ +from PyInstaller.utils.hooks import collect_data_files, copy_metadata, collect_submodules + +hiddenimports = collect_submodules("solara-server") +datas = collect_data_files('solara-server') +datas += copy_metadata('solara-server') diff --git a/standalone/hooks/hook-solara_ui.py b/standalone/hooks/hook-solara_ui.py new file mode 100644 index 0000000000..3747e9a718 --- /dev/null +++ b/standalone/hooks/hook-solara_ui.py @@ -0,0 +1,5 @@ +from PyInstaller.utils.hooks import collect_data_files, copy_metadata, collect_submodules + +hiddenimports = collect_submodules("solara-ui") +datas = collect_data_files('solara-ui') +datas += copy_metadata('solara-ui') diff --git a/standalone/jdaviz-cli-entrypoint.py b/standalone/jdaviz-cli-entrypoint.py index 27dde09c5c..1fdde82efb 100644 --- a/standalone/jdaviz-cli-entrypoint.py +++ b/standalone/jdaviz-cli-entrypoint.py @@ -1,23 +1,6 @@ -import sys - -def start_as_kernel(): - # similar to https://github.com/astrofrog/voila-qt-app/blob/master/voila_demo.py - import sys - - from ipykernel import kernelapp as app - app.launch_new_instance() - sys.argv = [app.__file__, sys.argv[3:]] +import jdaviz.cli if __name__ == "__main__": - # When voila starts a kernel under pyinstaller, it will use sys.executable - # (which is this entry point again) - # if called like [sys.argv[0], "-m", "ipykernel_launcher", ...] - if len(sys.argv) >= 3 and sys.argv[1] == "-m" and sys.argv[2] == "ipykernel_launcher": - # it is important that we do not import jdaviz top level - # as that would cause it to import ipywidgets before the kernel is started - start_as_kernel() - else: - import jdaviz.cli - # should change this to _main, but now it doesn't need arguments - jdaviz.cli.main(layout="") + # should change this to _main, but now it doesn't need arguments + jdaviz.cli.main(layout="") From 1424739560d90a40c2f6dc1e3060117795450a43 Mon Sep 17 00:00:00 2001 From: "Maarten A. Breddels" Date: Tue, 16 Jul 2024 16:44:25 +0200 Subject: [PATCH 2/5] TEMP: always run standalone --- .github/workflows/standalone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/standalone.yml b/.github/workflows/standalone.yml index e12c1ed99b..2966aada00 100644 --- a/.github/workflows/standalone.yml +++ b/.github/workflows/standalone.yml @@ -17,7 +17,7 @@ defaults: jobs: build_binary_not_osx: runs-on: ${{ matrix.os }}-latest - if: (github.repository == 'spacetelescope/jdaviz' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, 'Build standalone'))) + # if: (github.repository == 'spacetelescope/jdaviz' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, 'Build standalone'))) strategy: matrix: os: [ubuntu, windows] From 986f2849357604c5d5799c54e2e78ea9f5b70958 Mon Sep 17 00:00:00 2001 From: "Maarten A. Breddels" Date: Tue, 23 Jul 2024 16:29:26 +0200 Subject: [PATCH 3/5] rich.logging hidden import --- standalone/jdaviz.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standalone/jdaviz.spec b/standalone/jdaviz.spec index 31e9f2f11b..11ddf9a610 100644 --- a/standalone/jdaviz.spec +++ b/standalone/jdaviz.spec @@ -26,7 +26,7 @@ a = Analysis( pathex=[], binaries=[], datas=datas, - hiddenimports=[], + hiddenimports=["rich.logging"], hookspath=["hooks"], hooksconfig={}, runtime_hooks=[], From f3c0bca70b81f0fc1a4a09790fd87dc01c1d1d96 Mon Sep 17 00:00:00 2001 From: "Maarten A. Breddels" Date: Tue, 23 Jul 2024 18:53:29 +0200 Subject: [PATCH 4/5] make test run --- standalone/test_standalone.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/standalone/test_standalone.py b/standalone/test_standalone.py index 2864d6362e..916d9b328c 100644 --- a/standalone/test_standalone.py +++ b/standalone/test_standalone.py @@ -4,9 +4,7 @@ def test_voila_basics(page: Page): - page.goto("http://localhost:8866/") + page.goto("http://localhost:8765/") - # basic voila is loaded - page.locator("body.theme-light").wait_for() # when jdaviz is loaded (button at the top left) page.locator("text=Welcome to Jdaviz").wait_for() From 25c55a8fff9ee2a4eaddfc50ee4bd2d61cbdfc15 Mon Sep 17 00:00:00 2001 From: "Maarten A. Breddels" Date: Tue, 30 Jul 2024 15:23:01 +0200 Subject: [PATCH 5/5] close when tab is closed --- jdaviz/solara.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/jdaviz/solara.py b/jdaviz/solara.py index 7234459b2e..906fd0b861 100644 --- a/jdaviz/solara.py +++ b/jdaviz/solara.py @@ -1,7 +1,9 @@ import os from pathlib import Path +import signal import solara +import solara.lab import ipygoldenlayout import ipysplitpanes import ipyvue @@ -16,6 +18,19 @@ jdaviz_history_verbosity = 'info' +@solara.lab.on_kernel_start +def on_kernel_start(): + # at import time, solara runs with a dummy kernel + # we simply ignore that + if "dummy" in solara.get_kernel_id(): + return + def on_kernel_close(): + # for some reason, sys.exit(0) does not work here + # see https://github.com/encode/uvicorn/discussions/1103 + signal.raise_signal(signal.SIGINT) + return on_kernel_close + + @solara.component def Page(): if config is None: