From b098da1c4024efba5a10cdba66cb76b8f38bb399 Mon Sep 17 00:00:00 2001 From: Maarten Breddels Date: Mon, 8 Apr 2024 16:36:52 +0200 Subject: [PATCH] refactor: separate solara into a meta package and subpackages (#585) This allows us to install solara-ui without solara-server and not having to install all dependencies of solara-server. This is useful when you need solara in the Jupyter environment and want less dependencies installed. --- .bumpversion.cfg | 8 +- ...ows-python3.8-voila0.4.0-ipywidgets8.0.txt | 235 ------------------ .../unit/osmacos-python3.6-ipywidgets7.7.txt | 182 -------------- .../unit/osmacos-python3.9-ipywidgets7.7.txt | 217 ---------------- .../unit/osmacos-python3.9-ipywidgets8.0.txt | 217 ---------------- .../unit/osubuntu-python3.6-ipywidgets7.7.txt | 181 -------------- .../unit/osubuntu-python3.9-ipywidgets7.7.txt | 216 ---------------- .../unit/osubuntu-python3.9-ipywidgets8.0.txt | 216 ---------------- .../oswindows-python3.9-ipywidgets7.7.txt | 220 ---------------- .../oswindows-python3.9-ipywidgets8.0.txt | 220 ---------------- .github/workflows/test.yaml | 118 +++++++-- .pre-commit-config.yaml | 2 +- mypy.ini | 2 +- .../{assets => pytest-ipywidgets}/LICENSE | 0 packages/pytest-ipywidgets/README.md | 41 +++ packages/pytest-ipywidgets/pyproject.toml | 56 +++++ packages/{assets => solara-assets}/.gitignore | 0 packages/solara-assets/LICENSE | 21 ++ packages/{assets => solara-assets}/RELEASE.md | 0 .../download_cdn_test.py | 0 .../{assets => solara-assets}/hatch_build.py | 0 .../{assets => solara-assets}/pyproject.toml | 0 .../solara_assets/__init__.py | 0 packages/solara-enterprise/pyproject.toml | 5 +- packages/solara-meta/LICENSE | 21 ++ packages/solara-meta/README.md | 3 + packages/solara-meta/main.README.md | 106 ++++++++ packages/solara-meta/pyproject.toml | 84 +++++++ packages/solara-server/LICENSE | 21 ++ packages/solara-server/README.md | 15 ++ packages/solara-server/pyproject.toml | 56 +++++ packages/solara-vuetify-app/.bumpversion.cfg | 2 +- packages/solara-vuetify3-app/.bumpversion.cfg | 2 +- pyproject.toml | 121 +++------ requirements.txt | 12 +- solara/autorouting.py | 1 + solara/cache.py | 20 +- solara/components/markdown.py | 15 +- solara/lab/__init__.py | 2 +- solara/lifecycle.py | 46 ++++ solara/server/app.py | 3 +- solara/server/kernel_context.py | 49 +--- solara/server/settings.py | 7 +- solara/toestand.py | 8 +- .../advanced/content/10-howto/30-testing.md | 34 ++- .../20-understanding/50-solara-server.md | 11 + .../getting_started/content/02-installing.md | 49 ++++ tests/unit/reload_test.py | 18 +- 48 files changed, 746 insertions(+), 2117 deletions(-) delete mode 100644 .ci-package-locks/integration/oswindows-python3.8-voila0.4.0-ipywidgets8.0.txt delete mode 100644 .ci-package-locks/unit/osmacos-python3.6-ipywidgets7.7.txt delete mode 100644 .ci-package-locks/unit/osmacos-python3.9-ipywidgets7.7.txt delete mode 100644 .ci-package-locks/unit/osmacos-python3.9-ipywidgets8.0.txt delete mode 100644 .ci-package-locks/unit/osubuntu-python3.6-ipywidgets7.7.txt delete mode 100644 .ci-package-locks/unit/osubuntu-python3.9-ipywidgets7.7.txt delete mode 100644 .ci-package-locks/unit/osubuntu-python3.9-ipywidgets8.0.txt delete mode 100644 .ci-package-locks/unit/oswindows-python3.9-ipywidgets7.7.txt delete mode 100644 .ci-package-locks/unit/oswindows-python3.9-ipywidgets8.0.txt rename packages/{assets => pytest-ipywidgets}/LICENSE (100%) create mode 100644 packages/pytest-ipywidgets/README.md create mode 100644 packages/pytest-ipywidgets/pyproject.toml rename packages/{assets => solara-assets}/.gitignore (100%) create mode 100644 packages/solara-assets/LICENSE rename packages/{assets => solara-assets}/RELEASE.md (100%) rename packages/{assets => solara-assets}/download_cdn_test.py (100%) rename packages/{assets => solara-assets}/hatch_build.py (100%) rename packages/{assets => solara-assets}/pyproject.toml (100%) rename packages/{assets => solara-assets}/solara_assets/__init__.py (100%) create mode 100644 packages/solara-meta/LICENSE create mode 100644 packages/solara-meta/README.md create mode 100644 packages/solara-meta/main.README.md create mode 100644 packages/solara-meta/pyproject.toml create mode 100644 packages/solara-server/LICENSE create mode 100644 packages/solara-server/README.md create mode 100644 packages/solara-server/pyproject.toml create mode 100644 solara/lifecycle.py diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 0d3618ead..f9a7811fb 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -19,12 +19,18 @@ values = [bumpversion:file:pyproject.toml] -[bumpversion:file:packages/assets/solara_assets/__init__.py] +[bumpversion:file:packages/solara-assets/solara_assets/__init__.py] [bumpversion:file:packages/solara-enterprise/solara_enterprise/__init__.py] [bumpversion:file:packages/solara-enterprise/pyproject.toml] +[bumpversion:file:packages/solara-server/pyproject.toml] + +[bumpversion:file:packages/solara-meta/pyproject.toml] + +[bumpversion:file:packages/pytest-ipywidgets/pyproject.toml] + [bumpversion:file:solara/server/static/solara_bootstrap.py] [bumpversion:file:release.md] diff --git a/.ci-package-locks/integration/oswindows-python3.8-voila0.4.0-ipywidgets8.0.txt b/.ci-package-locks/integration/oswindows-python3.8-voila0.4.0-ipywidgets8.0.txt deleted file mode 100644 index 67b56f13f..000000000 --- a/.ci-package-locks/integration/oswindows-python3.8-voila0.4.0-ipywidgets8.0.txt +++ /dev/null @@ -1,235 +0,0 @@ -aiofiles==22.1.0 -aiosqlite==0.20.0 -altair==5.2.0 -annotated-types==0.6.0 -anyio==4.3.0 -anywidget==0.9.3 -aplus==0.11.0 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asttokens==2.4.1 -async-lru==2.0.4 -attrs==23.2.0 -Authlib==1.3.0 -Babel==2.14.0 -backcall==0.2.0 -beautifulsoup4==4.12.3 -black==24.3.0 -blake3==0.4.1 -bleach==6.1.0 -blinker==1.7.0 -bqplot==0.12.43 -bqplot-image-gl==1.4.11 -branca==0.7.1 -bump2version==1.0.1 -cachetools==5.3.3 -certifi==2024.2.2 -cffi==1.16.0 -cfgv==3.4.0 -charset-normalizer==3.3.2 -click==8.1.7 -cloudpickle==3.0.0 -codespell==2.2.6 -comm==0.2.2 -contourpy==1.1.1 -coverage==7.4.4 -cryptography==42.0.5 -cycler==0.12.1 -dask==2023.5.0 -debugpy==1.8.1 -decorator==5.1.1 -defusedxml==0.7.1 -distlib==0.3.8 -distro==1.9.0 -entrypoints==0.4 -exceptiongroup==1.2.0 -executing==2.0.1 -fastjsonschema==2.19.1 -filelock==3.13.1 -flake8==7.0.0 -Flask==3.0.2 -flask-sock==0.7.0 -folium==0.16.0 -fonttools==4.50.0 -fqdn==1.5.1 -frozendict==2.4.0 -fsspec==2024.3.1 -future==1.0.0 -greenlet==3.0.3 -h11==0.14.0 -h5py==3.10.0 -httpcore==1.0.4 -httpx==0.27.0 -humanize==4.9.0 -identify==2.5.35 -idna==3.6 -importlib_metadata==7.0.2 -importlib_resources==6.3.1 -iniconfig==2.0.0 -ipycanvas==0.13.1 -ipydatawidgets==4.3.5 -ipykernel==6.29.3 -ipyleaflet==0.18.2 -ipympl==0.9.3 -ipyreact==0.4.1 -ipython==8.12.3 -ipython-genutils==0.2.0 -ipyvolume==0.6.3 -ipyvue==1.10.2 -ipyvuetify==1.9.2 -ipywebrtc==0.6.0 -ipywidgets==8.1.2 -isoduration==20.11.0 -itsdangerous==2.1.2 -jedi==0.19.1 -Jinja2==3.1.3 -json5==0.9.24 -jsonpointer==2.4 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -jupyter-events==0.10.0 -jupyter-lsp==2.2.4 -jupyter-ydoc==0.2.5 -jupyter_client==7.4.9 -jupyter_core==5.7.2 -jupyter_server==2.13.0 -jupyter_server_fileid==0.9.1 -jupyter_server_terminals==0.5.3 -jupyter_server_ydoc==0.8.0 -jupyterlab==3.6.7 -jupyterlab_pygments==0.3.0 -jupyterlab_server==2.25.4 -jupyterlab_widgets==3.0.10 -kiwisolver==1.4.5 -locket==1.0.0 -Markdown==3.6 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -matplotlib==3.7.5 -matplotlib-inline==0.1.6 -mccabe==0.7.0 -mdit-py-plugins==0.4.0 -mdurl==0.1.2 -mistune==3.0.2 -mypy==1.9.0 -mypy-extensions==1.0.0 -nbclassic==1.0.0 -nbclient==0.7.4 -nbconvert==7.16.2 -nbformat==5.10.3 -nest-asyncio==1.6.0 -nodeenv==1.8.0 -notebook==6.5.6 -notebook_shim==0.2.4 -numpy==1.24.4 -openai==1.14.1 -overrides==7.7.0 -packaging==24.0 -pandas==2.0.3 -pandocfilters==1.5.1 -parso==0.8.3 -partd==1.4.1 -pathspec==0.12.1 -pexpect==4.9.0 -pickleshare==0.7.5 -pillow==10.2.0 -pixelmatch==0.3.0 -pkgutil_resolve_name==1.3.10 -platformdirs==4.2.0 -playwright==1.41.2 -plotly==5.20.0 -pluggy==1.4.0 -polars==0.20.16 -pre-commit==3.5.0 -progressbar2==4.4.2 -prometheus_client==0.20.0 -prompt-toolkit==3.0.43 -psutil==5.9.8 -psygnal==0.10.2 -ptyprocess==0.7.0 -pure-eval==0.2.2 -pyarrow==15.0.2 -pycodestyle==2.11.1 -pycparser==2.21 -pydantic==1.10.14 -pydantic_core==2.16.3 -pyee==11.0.1 -pyflakes==3.2.0 -Pygments==2.17.2 -pymdown-extensions==10.7.1 -pyparsing==3.1.2 -pytest==8.1.1 -pytest-base-url==2.1.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-playwright==0.4.4 -pytest-timeout==2.3.1 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -python-json-logger==2.0.7 -python-slugify==8.0.4 -python-utils==3.8.2 -pythreejs==2.4.2 -pytz==2024.1 -PyYAML==6.0.1 -pyzmq==24.0.1 -reacton==1.8.3 -referencing==0.34.0 -regex==2023.12.25 -requests==2.31.0 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 -rich==13.7.1 -rich-click==1.7.4 -rpds-py==0.18.0 -Send2Trash==1.8.2 -simple-websocket==1.0.0 -six==1.16.0 -sniffio==1.3.1 -soupsieve==2.5 -stack-data==0.6.3 -starlette==0.37.2 -tabulate==0.9.0 -tenacity==8.2.3 -terminado==0.18.1 -text-unidecode==1.3 -tiktoken==0.6.0 -tinycss2==1.2.1 -tomli==2.0.1 -toolz==0.12.1 -tornado==6.4 -tqdm==4.66.2 -traitlets==5.14.2 -traittypes==0.2.1 -types-Markdown==3.6.0.20240316 -types-python-dateutil==2.9.0.20240316 -types-PyYAML==6.0.12.20240311 -types-requests==2.31.0.20240311 -typing_extensions==4.10.0 -tzdata==2024.1 -uri-template==1.3.0 -urllib3==2.2.1 -uvicorn==0.28.1 -vaex-core==4.17.1 -vaex-hdf5==0.14.1 -vaex-jupyter==0.8.2 -vaex-viz==0.5.4 -vega-datasets==0.9.0 -virtualenv==20.25.1 -voila==0.4.3 -watchdog==4.0.0 -watchfiles==0.21.0 -wcwidth==0.2.13 -webcolors==1.13 -webencodings==0.5.1 -websocket-client==1.7.0 -websockets==12.0 -Werkzeug==3.0.1 -widgetsnbextension==4.0.10 -wsproto==1.2.0 -xarray==2023.1.0 -xyzservices==2023.10.1 -y-py==0.6.2 -ypy-websocket==0.8.4 -zipp==3.18.1 diff --git a/.ci-package-locks/unit/osmacos-python3.6-ipywidgets7.7.txt b/.ci-package-locks/unit/osmacos-python3.6-ipywidgets7.7.txt deleted file mode 100644 index d144c60d9..000000000 --- a/.ci-package-locks/unit/osmacos-python3.6-ipywidgets7.7.txt +++ /dev/null @@ -1,182 +0,0 @@ -anyio==3.6.2 -aplus==0.11.0 -appnope==0.1.4 -argon2-cffi==21.3.0 -argon2-cffi-bindings==21.2.0 -asgiref==3.4.1 -async-generator==1.10 -async-timeout==4.0.2 -attrs==21.4.0 -Authlib==1.2.1 -Babel==2.11.0 -backcall==0.2.0 -beautifulsoup4==4.12.3 -black==22.8.0 -blake3==0.3.1 -bleach==4.1.0 -bqplot==0.12.43 -bqplot-image-gl==1.4.11 -bump2version==1.0.1 -cached-property==1.5.2 -cachetools==4.2.4 -certifi==2024.2.2 -cffi==1.15.1 -cfgv==3.3.1 -charset-normalizer==2.0.12 -click==8.0.4 -cloudpickle==2.2.1 -codespell==2.2.1 -comm==0.1.4 -commonmark==0.9.1 -contextlib2==21.6.0 -contextvars==2.4 -coverage==6.2 -cryptography==40.0.2 -cycler==0.11.0 -dask==2021.3.0 -dataclasses==0.8 -decorator==5.1.1 -defusedxml==0.7.1 -diskcache==5.6.3 -distlib==0.3.8 -entrypoints==0.4 -filelock==3.4.1 -flake8==5.0.4 -frozendict==2.4.0 -fsspec==2022.1.0 -future==1.0.0 -h11==0.12.0 -h5py==3.1.0 -httpcore==0.14.7 -httpx==0.22.0 -humanize==3.14.0 -identify==2.4.4 -idna==3.6 -immutables==0.19 -importlib-metadata==4.2.0 -importlib-resources==5.2.3 -iniconfig==1.1.1 -ipydatawidgets==4.3.1.post1 -ipykernel==5.5.6 -ipyleaflet==0.14.0 -ipympl==0.8.8 -ipython==7.16.3 -ipython-genutils==0.2.0 -ipyvolume==0.5.2 -ipyvue==1.10.2 -ipyvuetify==1.9.2 -ipywebrtc==0.6.0 -ipywidgets==7.8.1 -itsdangerous==2.0.1 -jedi==0.17.2 -Jinja2==3.0.3 -json5==0.9.16 -jsonschema==3.2.0 -jupyter-client==7.1.2 -jupyter-core==4.9.2 -jupyter-server==1.13.1 -jupyterlab==3.2.9 -jupyterlab-pygments==0.1.2 -jupyterlab-server==2.10.3 -jupyterlab-widgets==1.1.7 -kiwisolver==1.3.1 -locket==1.0.0 -Markdown==3.3.4 -markdown-it-py==2.0.1 -MarkupSafe==2.0.1 -matplotlib==3.3.4 -mccabe==0.7.0 -mdit-py-plugins==0.3.0 -mdurl==0.1.0 -mistune==0.8.4 -mypy==0.971 -mypy-extensions==1.0.0 -nbclassic==0.3.5 -nbclient==0.5.9 -nbconvert==6.0.7 -nbformat==5.1.3 -nest-asyncio==1.6.0 -nodeenv==1.6.0 -notebook==6.4.10 -numpy==1.19.5 -packaging==21.3 -pandas==1.1.5 -pandocfilters==1.5.1 -parso==0.7.1 -partd==1.2.0 -pathspec==0.9.0 -pexpect==4.9.0 -pickleshare==0.7.5 -Pillow==8.4.0 -platformdirs==2.4.0 -plotly==5.18.0 -pluggy==1.0.0 -polars==0.12.5 -pre-commit==2.17.0 -progressbar2==3.55.0 -prometheus-client==0.17.1 -prompt-toolkit==3.0.36 -ptyprocess==0.7.0 -py==1.11.0 -pyarrow==6.0.1 -pycodestyle==2.9.1 -pycparser==2.21 -pydantic==1.9.2 -pyflakes==2.5.0 -Pygments==2.10.0 -pymdown-extensions==9.1 -pyparsing==3.1.2 -pyrsistent==0.18.0 -pytest==7.0.1 -pytest-cov==4.0.0 -pytest-mock==3.6.1 -pytest-timeout==2.1.0 -python-dateutil==2.9.0.post0 -python-dotenv==0.20.0 -python-utils==3.5.2 -pythreejs==2.3.0 -pytz==2024.1 -PyYAML==6.0.1 -pyzmq==25.1.2 -reacton==1.8.3 -redis==4.3.6 -requests==2.27.1 -rfc3986==1.5.0 -rich==12.6.0 -rich-click==1.2.1 -Send2Trash==1.8.2 -six==1.16.0 -sniffio==1.2.0 -soupsieve==2.3.2.post1 -starlette==0.19.1 -tabulate==0.8.10 -tenacity==8.2.2 -terminado==0.12.1 -testpath==0.6.0 -toml==0.10.2 -tomli==1.2.3 -toolz==0.12.0 -tornado==6.1 -traitlets==4.3.3 -traittypes==0.2.1 -typed-ast==1.5.5 -types-Markdown==3.4.2.10 -types-PyYAML==6.0.12.12 -types-requests==2.31.0.5 -types-urllib3==1.26.25.14 -typing_extensions==4.1.1 -urllib3==1.26.18 -uvicorn==0.16.0 -vaex-core==4.17.1 -vaex-hdf5==0.14.1 -vaex-jupyter==0.8.2 -vaex-viz==0.5.4 -virtualenv==20.16.2 -watchdog==2.3.1 -wcwidth==0.2.13 -webencodings==0.5.1 -websocket-client==1.3.1 -websockets==9.1 -widgetsnbextension==3.6.6 -xarray==0.16.2 -zipp==3.6.0 diff --git a/.ci-package-locks/unit/osmacos-python3.9-ipywidgets7.7.txt b/.ci-package-locks/unit/osmacos-python3.9-ipywidgets7.7.txt deleted file mode 100644 index 6cc382bc9..000000000 --- a/.ci-package-locks/unit/osmacos-python3.9-ipywidgets7.7.txt +++ /dev/null @@ -1,217 +0,0 @@ -aiofiles==22.1.0 -aiosqlite==0.20.0 -annotated-types==0.6.0 -anyio==4.3.0 -anywidget==0.9.3 -aplus==0.11.0 -appnope==0.1.4 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asttokens==2.4.1 -async-timeout==4.0.3 -attrs==23.2.0 -Authlib==1.3.0 -Babel==2.14.0 -beautifulsoup4==4.12.3 -black==24.3.0 -blake3==0.4.1 -bleach==6.1.0 -bqplot==0.12.43 -bqplot-image-gl==1.4.11 -branca==0.7.1 -bump2version==1.0.1 -cachetools==5.3.3 -certifi==2024.2.2 -cffi==1.16.0 -cfgv==3.4.0 -charset-normalizer==3.3.2 -click==8.1.7 -cloudpickle==3.0.0 -codespell==2.2.6 -comm==0.2.2 -contourpy==1.2.0 -coverage==7.4.4 -cryptography==42.0.5 -cycler==0.12.1 -dask==2024.3.1 -debugpy==1.8.1 -decorator==5.1.1 -defusedxml==0.7.1 -diskcache==5.6.3 -distlib==0.3.8 -entrypoints==0.4 -exceptiongroup==1.2.0 -executing==2.0.1 -fastjsonschema==2.19.1 -filelock==3.13.1 -flake8==7.0.0 -fonttools==4.50.0 -fqdn==1.5.1 -frozendict==2.4.0 -fsspec==2024.3.1 -future==1.0.0 -greenlet==3.0.3 -h11==0.14.0 -h5py==3.10.0 -httpcore==1.0.4 -httpx==0.27.0 -humanize==4.9.0 -identify==2.5.35 -idna==3.6 -importlib_metadata==7.0.2 -importlib_resources==6.3.1 -iniconfig==2.0.0 -ipydatawidgets==4.3.5 -ipykernel==6.29.3 -ipyleaflet==0.18.2 -ipympl==0.9.3 -ipyreact==0.4.1 -ipython==8.18.1 -ipython-genutils==0.2.0 -ipyvolume==0.6.3 -ipyvue==1.10.2 -ipyvuetify==1.9.2 -ipywebrtc==0.6.0 -ipywidgets==7.8.1 -isoduration==20.11.0 -itsdangerous==2.1.2 -jedi==0.19.1 -Jinja2==3.1.3 -json5==0.9.24 -jsonpointer==2.4 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -jupyter-events==0.10.0 -jupyter-ydoc==0.2.5 -jupyter_client==7.4.9 -jupyter_core==5.7.2 -jupyter_server==2.13.0 -jupyter_server_fileid==0.9.1 -jupyter_server_terminals==0.5.3 -jupyter_server_ydoc==0.8.0 -jupyterlab==3.6.7 -jupyterlab-widgets==1.1.7 -jupyterlab_pygments==0.3.0 -jupyterlab_server==2.25.4 -kiwisolver==1.4.5 -locket==1.0.0 -Markdown==3.6 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -matplotlib==3.8.3 -matplotlib-inline==0.1.6 -mccabe==0.7.0 -mdit-py-plugins==0.4.0 -mdurl==0.1.2 -mistune==3.0.2 -mypy==1.9.0 -mypy-extensions==1.0.0 -nbclassic==1.0.0 -nbclient==0.10.0 -nbconvert==7.16.2 -nbformat==5.10.3 -nest-asyncio==1.6.0 -nodeenv==1.8.0 -notebook==6.5.6 -notebook_shim==0.2.4 -numpy==1.26.4 -overrides==7.7.0 -packaging==24.0 -pandas==2.2.1 -pandocfilters==1.5.1 -parso==0.8.3 -partd==1.4.1 -pathspec==0.12.1 -pexpect==4.9.0 -pillow==10.2.0 -platformdirs==4.2.0 -playwright==1.42.0 -plotly==5.20.0 -pluggy==1.4.0 -polars==0.20.16 -pre-commit==3.6.2 -progressbar2==4.4.2 -prometheus_client==0.20.0 -prompt-toolkit==3.0.43 -psutil==5.9.8 -psygnal==0.10.2 -ptyprocess==0.7.0 -pure-eval==0.2.2 -pyarrow==15.0.2 -pycodestyle==2.11.1 -pycparser==2.21 -pydantic==2.6.4 -pydantic_core==2.16.3 -pyee==11.0.1 -pyflakes==3.2.0 -Pygments==2.17.2 -pymdown-extensions==10.7.1 -pyparsing==3.1.2 -pytest==8.1.1 -pytest-base-url==2.1.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-playwright==0.4.4 -pytest-timeout==2.3.1 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -python-json-logger==2.0.7 -python-slugify==8.0.4 -python-utils==3.8.2 -pythreejs==2.4.2 -pytz==2024.1 -PyYAML==6.0.1 -pyzmq==24.0.1 -reacton==1.8.3 -redis==5.0.3 -referencing==0.34.0 -requests==2.31.0 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 -rich==13.7.1 -rich-click==1.7.4 -rpds-py==0.18.0 -Send2Trash==1.8.2 -six==1.16.0 -sniffio==1.3.1 -soupsieve==2.5 -stack-data==0.6.3 -starlette==0.37.2 -tabulate==0.9.0 -tenacity==8.2.3 -terminado==0.18.1 -text-unidecode==1.3 -tinycss2==1.2.1 -tomli==2.0.1 -toolz==0.12.1 -tornado==6.4 -traitlets==5.14.2 -traittypes==0.2.1 -types-Markdown==3.6.0.20240316 -types-python-dateutil==2.9.0.20240316 -types-PyYAML==6.0.12.20240311 -types-requests==2.31.0.20240311 -typing_extensions==4.10.0 -tzdata==2024.1 -uri-template==1.3.0 -urllib3==2.2.1 -uvicorn==0.28.1 -vaex-core==4.17.1 -vaex-hdf5==0.14.1 -vaex-jupyter==0.8.2 -vaex-viz==0.5.4 -virtualenv==20.25.1 -watchdog==4.0.0 -watchfiles==0.21.0 -wcwidth==0.2.13 -webcolors==1.13 -webencodings==0.5.1 -websocket-client==1.7.0 -websockets==12.0 -widgetsnbextension==3.6.6 -xarray==2024.2.0 -xyzservices==2023.10.1 -y-py==0.6.2 -ypy-websocket==0.8.4 -zipp==3.18.1 diff --git a/.ci-package-locks/unit/osmacos-python3.9-ipywidgets8.0.txt b/.ci-package-locks/unit/osmacos-python3.9-ipywidgets8.0.txt deleted file mode 100644 index 37f1825d0..000000000 --- a/.ci-package-locks/unit/osmacos-python3.9-ipywidgets8.0.txt +++ /dev/null @@ -1,217 +0,0 @@ -aiofiles==22.1.0 -aiosqlite==0.20.0 -annotated-types==0.6.0 -anyio==4.3.0 -anywidget==0.9.3 -aplus==0.11.0 -appnope==0.1.4 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asttokens==2.4.1 -async-timeout==4.0.3 -attrs==23.2.0 -Authlib==1.3.0 -Babel==2.14.0 -beautifulsoup4==4.12.3 -black==24.3.0 -blake3==0.4.1 -bleach==6.1.0 -bqplot==0.12.43 -bqplot-image-gl==1.4.11 -branca==0.7.1 -bump2version==1.0.1 -cachetools==5.3.3 -certifi==2024.2.2 -cffi==1.16.0 -cfgv==3.4.0 -charset-normalizer==3.3.2 -click==8.1.7 -cloudpickle==3.0.0 -codespell==2.2.6 -comm==0.2.2 -contourpy==1.2.0 -coverage==7.4.4 -cryptography==42.0.5 -cycler==0.12.1 -dask==2024.3.1 -debugpy==1.8.1 -decorator==5.1.1 -defusedxml==0.7.1 -diskcache==5.6.3 -distlib==0.3.8 -entrypoints==0.4 -exceptiongroup==1.2.0 -executing==2.0.1 -fastjsonschema==2.19.1 -filelock==3.13.1 -flake8==7.0.0 -fonttools==4.50.0 -fqdn==1.5.1 -frozendict==2.4.0 -fsspec==2024.3.1 -future==1.0.0 -greenlet==3.0.3 -h11==0.14.0 -h5py==3.10.0 -httpcore==1.0.4 -httpx==0.27.0 -humanize==4.9.0 -identify==2.5.35 -idna==3.6 -importlib_metadata==7.0.2 -importlib_resources==6.3.1 -iniconfig==2.0.0 -ipydatawidgets==4.3.5 -ipykernel==6.29.3 -ipyleaflet==0.18.2 -ipympl==0.9.3 -ipyreact==0.4.1 -ipython==8.18.1 -ipython-genutils==0.2.0 -ipyvolume==0.6.3 -ipyvue==1.10.2 -ipyvuetify==1.9.2 -ipywebrtc==0.6.0 -ipywidgets==8.1.2 -isoduration==20.11.0 -itsdangerous==2.1.2 -jedi==0.19.1 -Jinja2==3.1.3 -json5==0.9.24 -jsonpointer==2.4 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -jupyter-events==0.10.0 -jupyter-ydoc==0.2.5 -jupyter_client==7.4.9 -jupyter_core==5.7.2 -jupyter_server==2.13.0 -jupyter_server_fileid==0.9.1 -jupyter_server_terminals==0.5.3 -jupyter_server_ydoc==0.8.0 -jupyterlab==3.6.7 -jupyterlab_pygments==0.3.0 -jupyterlab_server==2.25.4 -jupyterlab_widgets==3.0.10 -kiwisolver==1.4.5 -locket==1.0.0 -Markdown==3.6 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -matplotlib==3.8.3 -matplotlib-inline==0.1.6 -mccabe==0.7.0 -mdit-py-plugins==0.4.0 -mdurl==0.1.2 -mistune==3.0.2 -mypy==1.9.0 -mypy-extensions==1.0.0 -nbclassic==1.0.0 -nbclient==0.10.0 -nbconvert==7.16.2 -nbformat==5.10.3 -nest-asyncio==1.6.0 -nodeenv==1.8.0 -notebook==6.5.6 -notebook_shim==0.2.4 -numpy==1.26.4 -overrides==7.7.0 -packaging==24.0 -pandas==2.2.1 -pandocfilters==1.5.1 -parso==0.8.3 -partd==1.4.1 -pathspec==0.12.1 -pexpect==4.9.0 -pillow==10.2.0 -platformdirs==4.2.0 -playwright==1.42.0 -plotly==5.20.0 -pluggy==1.4.0 -polars==0.20.16 -pre-commit==3.6.2 -progressbar2==4.4.2 -prometheus_client==0.20.0 -prompt-toolkit==3.0.43 -psutil==5.9.8 -psygnal==0.10.2 -ptyprocess==0.7.0 -pure-eval==0.2.2 -pyarrow==15.0.2 -pycodestyle==2.11.1 -pycparser==2.21 -pydantic==2.6.4 -pydantic_core==2.16.3 -pyee==11.0.1 -pyflakes==3.2.0 -Pygments==2.17.2 -pymdown-extensions==10.7.1 -pyparsing==3.1.2 -pytest==8.1.1 -pytest-base-url==2.1.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-playwright==0.4.4 -pytest-timeout==2.3.1 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -python-json-logger==2.0.7 -python-slugify==8.0.4 -python-utils==3.8.2 -pythreejs==2.4.2 -pytz==2024.1 -PyYAML==6.0.1 -pyzmq==24.0.1 -reacton==1.8.3 -redis==5.0.3 -referencing==0.34.0 -requests==2.31.0 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 -rich==13.7.1 -rich-click==1.7.4 -rpds-py==0.18.0 -Send2Trash==1.8.2 -six==1.16.0 -sniffio==1.3.1 -soupsieve==2.5 -stack-data==0.6.3 -starlette==0.37.2 -tabulate==0.9.0 -tenacity==8.2.3 -terminado==0.18.1 -text-unidecode==1.3 -tinycss2==1.2.1 -tomli==2.0.1 -toolz==0.12.1 -tornado==6.4 -traitlets==5.14.2 -traittypes==0.2.1 -types-Markdown==3.6.0.20240316 -types-python-dateutil==2.9.0.20240316 -types-PyYAML==6.0.12.20240311 -types-requests==2.31.0.20240311 -typing_extensions==4.10.0 -tzdata==2024.1 -uri-template==1.3.0 -urllib3==2.2.1 -uvicorn==0.28.1 -vaex-core==4.17.1 -vaex-hdf5==0.14.1 -vaex-jupyter==0.8.2 -vaex-viz==0.5.4 -virtualenv==20.25.1 -watchdog==4.0.0 -watchfiles==0.21.0 -wcwidth==0.2.13 -webcolors==1.13 -webencodings==0.5.1 -websocket-client==1.7.0 -websockets==12.0 -widgetsnbextension==4.0.10 -xarray==2024.2.0 -xyzservices==2023.10.1 -y-py==0.6.2 -ypy-websocket==0.8.4 -zipp==3.18.1 diff --git a/.ci-package-locks/unit/osubuntu-python3.6-ipywidgets7.7.txt b/.ci-package-locks/unit/osubuntu-python3.6-ipywidgets7.7.txt deleted file mode 100644 index bf9d38a9d..000000000 --- a/.ci-package-locks/unit/osubuntu-python3.6-ipywidgets7.7.txt +++ /dev/null @@ -1,181 +0,0 @@ -anyio==3.6.2 -aplus==0.11.0 -argon2-cffi==21.3.0 -argon2-cffi-bindings==21.2.0 -asgiref==3.4.1 -async-generator==1.10 -async-timeout==4.0.2 -attrs==21.4.0 -Authlib==1.2.1 -Babel==2.11.0 -backcall==0.2.0 -beautifulsoup4==4.12.3 -black==22.8.0 -blake3==0.3.1 -bleach==4.1.0 -bqplot==0.12.43 -bqplot-image-gl==1.4.11 -bump2version==1.0.1 -cached-property==1.5.2 -cachetools==4.2.4 -certifi==2024.2.2 -cffi==1.15.1 -cfgv==3.3.1 -charset-normalizer==2.0.12 -click==8.0.4 -cloudpickle==2.2.1 -codespell==2.2.1 -comm==0.1.4 -commonmark==0.9.1 -contextlib2==21.6.0 -contextvars==2.4 -coverage==6.2 -cryptography==40.0.2 -cycler==0.11.0 -dask==2021.3.0 -dataclasses==0.8 -decorator==5.1.1 -defusedxml==0.7.1 -diskcache==5.6.3 -distlib==0.3.8 -entrypoints==0.4 -filelock==3.4.1 -flake8==5.0.4 -frozendict==2.4.0 -fsspec==2022.1.0 -future==1.0.0 -h11==0.12.0 -h5py==3.1.0 -httpcore==0.14.7 -httpx==0.22.0 -humanize==3.14.0 -identify==2.4.4 -idna==3.6 -immutables==0.19 -importlib-metadata==4.2.0 -importlib-resources==5.2.3 -iniconfig==1.1.1 -ipydatawidgets==4.3.1.post1 -ipykernel==5.5.6 -ipyleaflet==0.14.0 -ipympl==0.8.8 -ipython==7.16.3 -ipython-genutils==0.2.0 -ipyvolume==0.5.2 -ipyvue==1.10.2 -ipyvuetify==1.9.2 -ipywebrtc==0.6.0 -ipywidgets==7.8.1 -itsdangerous==2.0.1 -jedi==0.17.2 -Jinja2==3.0.3 -json5==0.9.16 -jsonschema==3.2.0 -jupyter-client==7.1.2 -jupyter-core==4.9.2 -jupyter-server==1.13.1 -jupyterlab==3.2.9 -jupyterlab-pygments==0.1.2 -jupyterlab-server==2.10.3 -jupyterlab-widgets==1.1.7 -kiwisolver==1.3.1 -locket==1.0.0 -Markdown==3.3.4 -markdown-it-py==2.0.1 -MarkupSafe==2.0.1 -matplotlib==3.3.4 -mccabe==0.7.0 -mdit-py-plugins==0.3.0 -mdurl==0.1.0 -mistune==0.8.4 -mypy==0.971 -mypy-extensions==1.0.0 -nbclassic==0.3.5 -nbclient==0.5.9 -nbconvert==6.0.7 -nbformat==5.1.3 -nest-asyncio==1.6.0 -nodeenv==1.6.0 -notebook==6.4.10 -numpy==1.19.5 -packaging==21.3 -pandas==1.1.5 -pandocfilters==1.5.1 -parso==0.7.1 -partd==1.2.0 -pathspec==0.9.0 -pexpect==4.9.0 -pickleshare==0.7.5 -Pillow==8.4.0 -platformdirs==2.4.0 -plotly==5.18.0 -pluggy==1.0.0 -polars==0.12.5 -pre-commit==2.17.0 -progressbar2==3.55.0 -prometheus-client==0.17.1 -prompt-toolkit==3.0.36 -ptyprocess==0.7.0 -py==1.11.0 -pyarrow==6.0.1 -pycodestyle==2.9.1 -pycparser==2.21 -pydantic==1.9.2 -pyflakes==2.5.0 -Pygments==2.10.0 -pymdown-extensions==9.1 -pyparsing==3.1.2 -pyrsistent==0.18.0 -pytest==7.0.1 -pytest-cov==4.0.0 -pytest-mock==3.6.1 -pytest-timeout==2.1.0 -python-dateutil==2.9.0.post0 -python-dotenv==0.20.0 -python-utils==3.5.2 -pythreejs==2.3.0 -pytz==2024.1 -PyYAML==6.0.1 -pyzmq==25.1.2 -reacton==1.8.3 -redis==4.3.6 -requests==2.27.1 -rfc3986==1.5.0 -rich==12.6.0 -rich-click==1.2.1 -Send2Trash==1.8.2 -six==1.16.0 -sniffio==1.2.0 -soupsieve==2.3.2.post1 -starlette==0.19.1 -tabulate==0.8.10 -tenacity==8.2.2 -terminado==0.12.1 -testpath==0.6.0 -toml==0.10.2 -tomli==1.2.3 -toolz==0.12.0 -tornado==6.1 -traitlets==4.3.3 -traittypes==0.2.1 -typed-ast==1.5.5 -types-Markdown==3.4.2.10 -types-PyYAML==6.0.12.12 -types-requests==2.31.0.5 -types-urllib3==1.26.25.14 -typing_extensions==4.1.1 -urllib3==1.26.18 -uvicorn==0.16.0 -vaex-core==4.17.1 -vaex-hdf5==0.14.1 -vaex-jupyter==0.8.2 -vaex-viz==0.5.4 -virtualenv==20.16.2 -watchdog==2.3.1 -wcwidth==0.2.13 -webencodings==0.5.1 -websocket-client==1.3.1 -websockets==9.1 -widgetsnbextension==3.6.6 -xarray==0.16.2 -zipp==3.6.0 diff --git a/.ci-package-locks/unit/osubuntu-python3.9-ipywidgets7.7.txt b/.ci-package-locks/unit/osubuntu-python3.9-ipywidgets7.7.txt deleted file mode 100644 index a9f101835..000000000 --- a/.ci-package-locks/unit/osubuntu-python3.9-ipywidgets7.7.txt +++ /dev/null @@ -1,216 +0,0 @@ -aiofiles==22.1.0 -aiosqlite==0.20.0 -annotated-types==0.6.0 -anyio==4.3.0 -anywidget==0.9.3 -aplus==0.11.0 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asttokens==2.4.1 -async-timeout==4.0.3 -attrs==23.2.0 -Authlib==1.3.0 -Babel==2.14.0 -beautifulsoup4==4.12.3 -black==24.3.0 -blake3==0.4.1 -bleach==6.1.0 -bqplot==0.12.43 -bqplot-image-gl==1.4.11 -branca==0.7.1 -bump2version==1.0.1 -cachetools==5.3.3 -certifi==2024.2.2 -cffi==1.16.0 -cfgv==3.4.0 -charset-normalizer==3.3.2 -click==8.1.7 -cloudpickle==3.0.0 -codespell==2.2.6 -comm==0.2.2 -contourpy==1.2.0 -coverage==7.4.4 -cryptography==42.0.5 -cycler==0.12.1 -dask==2024.3.1 -debugpy==1.8.1 -decorator==5.1.1 -defusedxml==0.7.1 -diskcache==5.6.3 -distlib==0.3.8 -entrypoints==0.4 -exceptiongroup==1.2.0 -executing==2.0.1 -fastjsonschema==2.19.1 -filelock==3.13.1 -flake8==7.0.0 -fonttools==4.50.0 -fqdn==1.5.1 -frozendict==2.4.0 -fsspec==2024.3.1 -future==1.0.0 -greenlet==3.0.3 -h11==0.14.0 -h5py==3.10.0 -httpcore==1.0.4 -httpx==0.27.0 -humanize==4.9.0 -identify==2.5.35 -idna==3.6 -importlib_metadata==7.0.2 -importlib_resources==6.3.1 -iniconfig==2.0.0 -ipydatawidgets==4.3.5 -ipykernel==6.29.3 -ipyleaflet==0.18.2 -ipympl==0.9.3 -ipyreact==0.4.1 -ipython==8.18.1 -ipython-genutils==0.2.0 -ipyvolume==0.6.3 -ipyvue==1.10.2 -ipyvuetify==1.9.2 -ipywebrtc==0.6.0 -ipywidgets==7.8.1 -isoduration==20.11.0 -itsdangerous==2.1.2 -jedi==0.19.1 -Jinja2==3.1.3 -json5==0.9.24 -jsonpointer==2.4 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -jupyter-events==0.10.0 -jupyter-ydoc==0.2.5 -jupyter_client==7.4.9 -jupyter_core==5.7.2 -jupyter_server==2.13.0 -jupyter_server_fileid==0.9.1 -jupyter_server_terminals==0.5.3 -jupyter_server_ydoc==0.8.0 -jupyterlab==3.6.7 -jupyterlab-widgets==1.1.7 -jupyterlab_pygments==0.3.0 -jupyterlab_server==2.25.4 -kiwisolver==1.4.5 -locket==1.0.0 -Markdown==3.6 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -matplotlib==3.8.3 -matplotlib-inline==0.1.6 -mccabe==0.7.0 -mdit-py-plugins==0.4.0 -mdurl==0.1.2 -mistune==3.0.2 -mypy==1.9.0 -mypy-extensions==1.0.0 -nbclassic==1.0.0 -nbclient==0.10.0 -nbconvert==7.16.2 -nbformat==5.10.3 -nest-asyncio==1.6.0 -nodeenv==1.8.0 -notebook==6.5.6 -notebook_shim==0.2.4 -numpy==1.26.4 -overrides==7.7.0 -packaging==24.0 -pandas==2.2.1 -pandocfilters==1.5.1 -parso==0.8.3 -partd==1.4.1 -pathspec==0.12.1 -pexpect==4.9.0 -pillow==10.2.0 -platformdirs==4.2.0 -playwright==1.42.0 -plotly==5.20.0 -pluggy==1.4.0 -polars==0.20.16 -pre-commit==3.6.2 -progressbar2==4.4.2 -prometheus_client==0.20.0 -prompt-toolkit==3.0.43 -psutil==5.9.8 -psygnal==0.10.2 -ptyprocess==0.7.0 -pure-eval==0.2.2 -pyarrow==15.0.2 -pycodestyle==2.11.1 -pycparser==2.21 -pydantic==2.6.4 -pydantic_core==2.16.3 -pyee==11.0.1 -pyflakes==3.2.0 -Pygments==2.17.2 -pymdown-extensions==10.7.1 -pyparsing==3.1.2 -pytest==8.1.1 -pytest-base-url==2.1.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-playwright==0.4.4 -pytest-timeout==2.3.1 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -python-json-logger==2.0.7 -python-slugify==8.0.4 -python-utils==3.8.2 -pythreejs==2.4.2 -pytz==2024.1 -PyYAML==6.0.1 -pyzmq==24.0.1 -reacton==1.8.3 -redis==5.0.3 -referencing==0.34.0 -requests==2.31.0 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 -rich==13.7.1 -rich-click==1.7.4 -rpds-py==0.18.0 -Send2Trash==1.8.2 -six==1.16.0 -sniffio==1.3.1 -soupsieve==2.5 -stack-data==0.6.3 -starlette==0.37.2 -tabulate==0.9.0 -tenacity==8.2.3 -terminado==0.18.1 -text-unidecode==1.3 -tinycss2==1.2.1 -tomli==2.0.1 -toolz==0.12.1 -tornado==6.4 -traitlets==5.14.2 -traittypes==0.2.1 -types-Markdown==3.6.0.20240316 -types-python-dateutil==2.9.0.20240316 -types-PyYAML==6.0.12.20240311 -types-requests==2.31.0.20240311 -typing_extensions==4.10.0 -tzdata==2024.1 -uri-template==1.3.0 -urllib3==2.2.1 -uvicorn==0.28.1 -vaex-core==4.17.1 -vaex-hdf5==0.14.1 -vaex-jupyter==0.8.2 -vaex-viz==0.5.4 -virtualenv==20.25.1 -watchdog==4.0.0 -watchfiles==0.21.0 -wcwidth==0.2.13 -webcolors==1.13 -webencodings==0.5.1 -websocket-client==1.7.0 -websockets==12.0 -widgetsnbextension==3.6.6 -xarray==2024.2.0 -xyzservices==2023.10.1 -y-py==0.6.2 -ypy-websocket==0.8.4 -zipp==3.18.1 diff --git a/.ci-package-locks/unit/osubuntu-python3.9-ipywidgets8.0.txt b/.ci-package-locks/unit/osubuntu-python3.9-ipywidgets8.0.txt deleted file mode 100644 index d75b95ac4..000000000 --- a/.ci-package-locks/unit/osubuntu-python3.9-ipywidgets8.0.txt +++ /dev/null @@ -1,216 +0,0 @@ -aiofiles==22.1.0 -aiosqlite==0.20.0 -annotated-types==0.6.0 -anyio==4.3.0 -anywidget==0.9.3 -aplus==0.11.0 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asttokens==2.4.1 -async-timeout==4.0.3 -attrs==23.2.0 -Authlib==1.3.0 -Babel==2.14.0 -beautifulsoup4==4.12.3 -black==24.3.0 -blake3==0.4.1 -bleach==6.1.0 -bqplot==0.12.43 -bqplot-image-gl==1.4.11 -branca==0.7.1 -bump2version==1.0.1 -cachetools==5.3.3 -certifi==2024.2.2 -cffi==1.16.0 -cfgv==3.4.0 -charset-normalizer==3.3.2 -click==8.1.7 -cloudpickle==3.0.0 -codespell==2.2.6 -comm==0.2.2 -contourpy==1.2.0 -coverage==7.4.4 -cryptography==42.0.5 -cycler==0.12.1 -dask==2024.3.1 -debugpy==1.8.1 -decorator==5.1.1 -defusedxml==0.7.1 -diskcache==5.6.3 -distlib==0.3.8 -entrypoints==0.4 -exceptiongroup==1.2.0 -executing==2.0.1 -fastjsonschema==2.19.1 -filelock==3.13.1 -flake8==7.0.0 -fonttools==4.50.0 -fqdn==1.5.1 -frozendict==2.4.0 -fsspec==2024.3.1 -future==1.0.0 -greenlet==3.0.3 -h11==0.14.0 -h5py==3.10.0 -httpcore==1.0.4 -httpx==0.27.0 -humanize==4.9.0 -identify==2.5.35 -idna==3.6 -importlib_metadata==7.0.2 -importlib_resources==6.3.1 -iniconfig==2.0.0 -ipydatawidgets==4.3.5 -ipykernel==6.29.3 -ipyleaflet==0.18.2 -ipympl==0.9.3 -ipyreact==0.4.1 -ipython==8.18.1 -ipython-genutils==0.2.0 -ipyvolume==0.6.3 -ipyvue==1.10.2 -ipyvuetify==1.9.2 -ipywebrtc==0.6.0 -ipywidgets==8.1.2 -isoduration==20.11.0 -itsdangerous==2.1.2 -jedi==0.19.1 -Jinja2==3.1.3 -json5==0.9.24 -jsonpointer==2.4 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -jupyter-events==0.10.0 -jupyter-ydoc==0.2.5 -jupyter_client==7.4.9 -jupyter_core==5.7.2 -jupyter_server==2.13.0 -jupyter_server_fileid==0.9.1 -jupyter_server_terminals==0.5.3 -jupyter_server_ydoc==0.8.0 -jupyterlab==3.6.7 -jupyterlab_pygments==0.3.0 -jupyterlab_server==2.25.4 -jupyterlab_widgets==3.0.10 -kiwisolver==1.4.5 -locket==1.0.0 -Markdown==3.6 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -matplotlib==3.8.3 -matplotlib-inline==0.1.6 -mccabe==0.7.0 -mdit-py-plugins==0.4.0 -mdurl==0.1.2 -mistune==3.0.2 -mypy==1.9.0 -mypy-extensions==1.0.0 -nbclassic==1.0.0 -nbclient==0.10.0 -nbconvert==7.16.2 -nbformat==5.10.3 -nest-asyncio==1.6.0 -nodeenv==1.8.0 -notebook==6.5.6 -notebook_shim==0.2.4 -numpy==1.26.4 -overrides==7.7.0 -packaging==24.0 -pandas==2.2.1 -pandocfilters==1.5.1 -parso==0.8.3 -partd==1.4.1 -pathspec==0.12.1 -pexpect==4.9.0 -pillow==10.2.0 -platformdirs==4.2.0 -playwright==1.42.0 -plotly==5.20.0 -pluggy==1.4.0 -polars==0.20.16 -pre-commit==3.6.2 -progressbar2==4.4.2 -prometheus_client==0.20.0 -prompt-toolkit==3.0.43 -psutil==5.9.8 -psygnal==0.10.2 -ptyprocess==0.7.0 -pure-eval==0.2.2 -pyarrow==15.0.2 -pycodestyle==2.11.1 -pycparser==2.21 -pydantic==2.6.4 -pydantic_core==2.16.3 -pyee==11.0.1 -pyflakes==3.2.0 -Pygments==2.17.2 -pymdown-extensions==10.7.1 -pyparsing==3.1.2 -pytest==8.1.1 -pytest-base-url==2.1.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-playwright==0.4.4 -pytest-timeout==2.3.1 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -python-json-logger==2.0.7 -python-slugify==8.0.4 -python-utils==3.8.2 -pythreejs==2.4.2 -pytz==2024.1 -PyYAML==6.0.1 -pyzmq==24.0.1 -reacton==1.8.3 -redis==5.0.3 -referencing==0.34.0 -requests==2.31.0 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 -rich==13.7.1 -rich-click==1.7.4 -rpds-py==0.18.0 -Send2Trash==1.8.2 -six==1.16.0 -sniffio==1.3.1 -soupsieve==2.5 -stack-data==0.6.3 -starlette==0.37.2 -tabulate==0.9.0 -tenacity==8.2.3 -terminado==0.18.1 -text-unidecode==1.3 -tinycss2==1.2.1 -tomli==2.0.1 -toolz==0.12.1 -tornado==6.4 -traitlets==5.14.2 -traittypes==0.2.1 -types-Markdown==3.6.0.20240316 -types-python-dateutil==2.9.0.20240316 -types-PyYAML==6.0.12.20240311 -types-requests==2.31.0.20240311 -typing_extensions==4.10.0 -tzdata==2024.1 -uri-template==1.3.0 -urllib3==2.2.1 -uvicorn==0.28.1 -vaex-core==4.17.1 -vaex-hdf5==0.14.1 -vaex-jupyter==0.8.2 -vaex-viz==0.5.4 -virtualenv==20.25.1 -watchdog==4.0.0 -watchfiles==0.21.0 -wcwidth==0.2.13 -webcolors==1.13 -webencodings==0.5.1 -websocket-client==1.7.0 -websockets==12.0 -widgetsnbextension==4.0.10 -xarray==2024.2.0 -xyzservices==2023.10.1 -y-py==0.6.2 -ypy-websocket==0.8.4 -zipp==3.18.1 diff --git a/.ci-package-locks/unit/oswindows-python3.9-ipywidgets7.7.txt b/.ci-package-locks/unit/oswindows-python3.9-ipywidgets7.7.txt deleted file mode 100644 index 190689249..000000000 --- a/.ci-package-locks/unit/oswindows-python3.9-ipywidgets7.7.txt +++ /dev/null @@ -1,220 +0,0 @@ -aiofiles==22.1.0 -aiosqlite==0.20.0 -annotated-types==0.6.0 -anyio==4.3.0 -anywidget==0.9.3 -aplus==0.11.0 -argcomplete==3.2.3 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asttokens==2.4.1 -async-timeout==4.0.3 -attrs==23.2.0 -Authlib==1.3.0 -Babel==2.14.0 -beautifulsoup4==4.12.3 -black==24.3.0 -blake3==0.4.1 -bleach==6.1.0 -bqplot==0.12.43 -bqplot-image-gl==1.4.11 -branca==0.7.1 -bump2version==1.0.1 -cachetools==5.3.3 -certifi==2024.2.2 -cffi==1.16.0 -cfgv==3.4.0 -charset-normalizer==3.3.2 -click==8.1.7 -cloudpickle==3.0.0 -codespell==2.2.6 -colorama==0.4.6 -comm==0.2.2 -contourpy==1.2.0 -coverage==7.4.4 -cryptography==42.0.5 -cycler==0.12.1 -dask==2024.3.1 -debugpy==1.8.1 -decorator==5.1.1 -defusedxml==0.7.1 -diskcache==5.6.3 -distlib==0.3.8 -entrypoints==0.4 -exceptiongroup==1.2.0 -executing==2.0.1 -fastjsonschema==2.19.1 -filelock==3.13.1 -flake8==7.0.0 -fonttools==4.50.0 -fqdn==1.5.1 -frozendict==2.4.0 -fsspec==2024.3.1 -future==1.0.0 -greenlet==3.0.3 -h11==0.14.0 -h5py==3.10.0 -httpcore==1.0.4 -httpx==0.27.0 -humanize==4.9.0 -identify==2.5.35 -idna==3.6 -importlib_metadata==7.0.2 -importlib_resources==6.3.1 -iniconfig==2.0.0 -ipydatawidgets==4.3.5 -ipykernel==6.29.3 -ipyleaflet==0.18.2 -ipympl==0.9.3 -ipyreact==0.4.1 -ipython==8.18.1 -ipython-genutils==0.2.0 -ipyvolume==0.6.3 -ipyvue==1.10.2 -ipyvuetify==1.9.2 -ipywebrtc==0.6.0 -ipywidgets==7.8.1 -isoduration==20.11.0 -itsdangerous==2.1.2 -jedi==0.19.1 -Jinja2==3.1.3 -json5==0.9.24 -jsonpointer==2.4 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -jupyter-events==0.10.0 -jupyter-ydoc==0.2.5 -jupyter_client==7.4.9 -jupyter_core==5.7.2 -jupyter_server==2.13.0 -jupyter_server_fileid==0.9.1 -jupyter_server_terminals==0.5.3 -jupyter_server_ydoc==0.8.0 -jupyterlab==3.6.7 -jupyterlab-widgets==1.1.7 -jupyterlab_pygments==0.3.0 -jupyterlab_server==2.25.4 -kiwisolver==1.4.5 -locket==1.0.0 -Markdown==3.6 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -matplotlib==3.8.3 -matplotlib-inline==0.1.6 -mccabe==0.7.0 -mdit-py-plugins==0.4.0 -mdurl==0.1.2 -mistune==3.0.2 -mypy==1.9.0 -mypy-extensions==1.0.0 -nbclassic==1.0.0 -nbclient==0.10.0 -nbconvert==7.16.2 -nbformat==5.10.3 -nest-asyncio==1.6.0 -nodeenv==1.8.0 -notebook==6.5.6 -notebook_shim==0.2.4 -numpy==1.26.4 -overrides==7.7.0 -packaging==24.0 -pandas==2.2.1 -pandocfilters==1.5.1 -parso==0.8.3 -partd==1.4.1 -pathspec==0.12.1 -pillow==10.2.0 -pipx==1.4.3 -platformdirs==4.2.0 -playwright==1.42.0 -plotly==5.20.0 -pluggy==1.4.0 -polars==0.20.16 -pre-commit==3.6.2 -progressbar2==4.4.2 -prometheus_client==0.20.0 -prompt-toolkit==3.0.43 -psutil==5.9.8 -psygnal==0.10.2 -pure-eval==0.2.2 -pyarrow==15.0.2 -pycodestyle==2.11.1 -pycparser==2.21 -pydantic==2.6.4 -pydantic_core==2.16.3 -pyee==11.0.1 -pyflakes==3.2.0 -Pygments==2.17.2 -pymdown-extensions==10.7.1 -pyparsing==3.1.2 -pytest==8.1.1 -pytest-base-url==2.1.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-playwright==0.4.4 -pytest-timeout==2.3.1 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -python-json-logger==2.0.7 -python-slugify==8.0.4 -python-utils==3.8.2 -pythreejs==2.4.2 -pytz==2024.1 -pywin32==306 -pywinpty==2.0.13 -PyYAML==6.0.1 -pyzmq==24.0.1 -reacton==1.8.3 -redis==5.0.3 -referencing==0.34.0 -requests==2.31.0 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 -rich==13.7.1 -rich-click==1.7.4 -rpds-py==0.18.0 -Send2Trash==1.8.2 -six==1.16.0 -sniffio==1.3.1 -soupsieve==2.5 -stack-data==0.6.3 -starlette==0.37.2 -tabulate==0.9.0 -tenacity==8.2.3 -terminado==0.18.1 -text-unidecode==1.3 -tinycss2==1.2.1 -tomli==2.0.1 -toolz==0.12.1 -tornado==6.4 -traitlets==5.14.2 -traittypes==0.2.1 -types-Markdown==3.6.0.20240316 -types-python-dateutil==2.9.0.20240316 -types-PyYAML==6.0.12.20240311 -types-requests==2.31.0.20240311 -typing_extensions==4.10.0 -tzdata==2024.1 -uri-template==1.3.0 -urllib3==2.2.1 -userpath==1.9.2 -uvicorn==0.28.1 -vaex-core==4.17.1 -vaex-hdf5==0.14.1 -vaex-jupyter==0.8.2 -vaex-viz==0.5.4 -virtualenv==20.25.1 -watchdog==4.0.0 -watchfiles==0.21.0 -wcwidth==0.2.13 -webcolors==1.13 -webencodings==0.5.1 -websocket-client==1.7.0 -websockets==12.0 -widgetsnbextension==3.6.6 -xarray==2024.2.0 -xyzservices==2023.10.1 -y-py==0.6.2 -ypy-websocket==0.8.4 -zipp==3.18.1 diff --git a/.ci-package-locks/unit/oswindows-python3.9-ipywidgets8.0.txt b/.ci-package-locks/unit/oswindows-python3.9-ipywidgets8.0.txt deleted file mode 100644 index 1d4a662f6..000000000 --- a/.ci-package-locks/unit/oswindows-python3.9-ipywidgets8.0.txt +++ /dev/null @@ -1,220 +0,0 @@ -aiofiles==22.1.0 -aiosqlite==0.20.0 -annotated-types==0.6.0 -anyio==4.3.0 -anywidget==0.9.3 -aplus==0.11.0 -argcomplete==3.2.3 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asttokens==2.4.1 -async-timeout==4.0.3 -attrs==23.2.0 -Authlib==1.3.0 -Babel==2.14.0 -beautifulsoup4==4.12.3 -black==24.3.0 -blake3==0.4.1 -bleach==6.1.0 -bqplot==0.12.43 -bqplot-image-gl==1.4.11 -branca==0.7.1 -bump2version==1.0.1 -cachetools==5.3.3 -certifi==2024.2.2 -cffi==1.16.0 -cfgv==3.4.0 -charset-normalizer==3.3.2 -click==8.1.7 -cloudpickle==3.0.0 -codespell==2.2.6 -colorama==0.4.6 -comm==0.2.2 -contourpy==1.2.0 -coverage==7.4.4 -cryptography==42.0.5 -cycler==0.12.1 -dask==2024.3.1 -debugpy==1.8.1 -decorator==5.1.1 -defusedxml==0.7.1 -diskcache==5.6.3 -distlib==0.3.8 -entrypoints==0.4 -exceptiongroup==1.2.0 -executing==2.0.1 -fastjsonschema==2.19.1 -filelock==3.13.1 -flake8==7.0.0 -fonttools==4.50.0 -fqdn==1.5.1 -frozendict==2.4.0 -fsspec==2024.3.1 -future==1.0.0 -greenlet==3.0.3 -h11==0.14.0 -h5py==3.10.0 -httpcore==1.0.4 -httpx==0.27.0 -humanize==4.9.0 -identify==2.5.35 -idna==3.6 -importlib_metadata==7.0.2 -importlib_resources==6.3.1 -iniconfig==2.0.0 -ipydatawidgets==4.3.5 -ipykernel==6.29.3 -ipyleaflet==0.18.2 -ipympl==0.9.3 -ipyreact==0.4.1 -ipython==8.18.1 -ipython-genutils==0.2.0 -ipyvolume==0.6.3 -ipyvue==1.10.2 -ipyvuetify==1.9.2 -ipywebrtc==0.6.0 -ipywidgets==8.1.2 -isoduration==20.11.0 -itsdangerous==2.1.2 -jedi==0.19.1 -Jinja2==3.1.3 -json5==0.9.24 -jsonpointer==2.4 -jsonschema==4.21.1 -jsonschema-specifications==2023.12.1 -jupyter-events==0.10.0 -jupyter-ydoc==0.2.5 -jupyter_client==7.4.9 -jupyter_core==5.7.2 -jupyter_server==2.13.0 -jupyter_server_fileid==0.9.1 -jupyter_server_terminals==0.5.3 -jupyter_server_ydoc==0.8.0 -jupyterlab==3.6.7 -jupyterlab_pygments==0.3.0 -jupyterlab_server==2.25.4 -jupyterlab_widgets==3.0.10 -kiwisolver==1.4.5 -locket==1.0.0 -Markdown==3.6 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -matplotlib==3.8.3 -matplotlib-inline==0.1.6 -mccabe==0.7.0 -mdit-py-plugins==0.4.0 -mdurl==0.1.2 -mistune==3.0.2 -mypy==1.9.0 -mypy-extensions==1.0.0 -nbclassic==1.0.0 -nbclient==0.10.0 -nbconvert==7.16.2 -nbformat==5.10.3 -nest-asyncio==1.6.0 -nodeenv==1.8.0 -notebook==6.5.6 -notebook_shim==0.2.4 -numpy==1.26.4 -overrides==7.7.0 -packaging==24.0 -pandas==2.2.1 -pandocfilters==1.5.1 -parso==0.8.3 -partd==1.4.1 -pathspec==0.12.1 -pillow==10.2.0 -pipx==1.4.3 -platformdirs==4.2.0 -playwright==1.42.0 -plotly==5.20.0 -pluggy==1.4.0 -polars==0.20.16 -pre-commit==3.6.2 -progressbar2==4.4.2 -prometheus_client==0.20.0 -prompt-toolkit==3.0.43 -psutil==5.9.8 -psygnal==0.10.2 -pure-eval==0.2.2 -pyarrow==15.0.2 -pycodestyle==2.11.1 -pycparser==2.21 -pydantic==2.6.4 -pydantic_core==2.16.3 -pyee==11.0.1 -pyflakes==3.2.0 -Pygments==2.17.2 -pymdown-extensions==10.7.1 -pyparsing==3.1.2 -pytest==8.1.1 -pytest-base-url==2.1.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-playwright==0.4.4 -pytest-timeout==2.3.1 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -python-json-logger==2.0.7 -python-slugify==8.0.4 -python-utils==3.8.2 -pythreejs==2.4.2 -pytz==2024.1 -pywin32==306 -pywinpty==2.0.13 -PyYAML==6.0.1 -pyzmq==24.0.1 -reacton==1.8.3 -redis==5.0.3 -referencing==0.34.0 -requests==2.31.0 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 -rich==13.7.1 -rich-click==1.7.4 -rpds-py==0.18.0 -Send2Trash==1.8.2 -six==1.16.0 -sniffio==1.3.1 -soupsieve==2.5 -stack-data==0.6.3 -starlette==0.37.2 -tabulate==0.9.0 -tenacity==8.2.3 -terminado==0.18.1 -text-unidecode==1.3 -tinycss2==1.2.1 -tomli==2.0.1 -toolz==0.12.1 -tornado==6.4 -traitlets==5.14.2 -traittypes==0.2.1 -types-Markdown==3.6.0.20240316 -types-python-dateutil==2.9.0.20240316 -types-PyYAML==6.0.12.20240311 -types-requests==2.31.0.20240311 -typing_extensions==4.10.0 -tzdata==2024.1 -uri-template==1.3.0 -urllib3==2.2.1 -userpath==1.9.2 -uvicorn==0.28.1 -vaex-core==4.17.1 -vaex-hdf5==0.14.1 -vaex-jupyter==0.8.2 -vaex-viz==0.5.4 -virtualenv==20.25.1 -watchdog==4.0.0 -watchfiles==0.21.0 -wcwidth==0.2.13 -webcolors==1.13 -webencodings==0.5.1 -websocket-client==1.7.0 -websockets==12.0 -widgetsnbextension==4.0.10 -xarray==2024.2.0 -xyzservices==2023.10.1 -y-py==0.6.2 -ypy-websocket==0.8.4 -zipp==3.18.1 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 969744bf5..f71ce0ba9 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -77,6 +77,15 @@ jobs: - name: Build solara run: hatch build + - name: Build solara-server + run: (cd packages/solara-server; hatch build) + + - name: Build pytest-ipywidgets + run: (cd packages/pytest-ipywidgets; hatch build) + + - name: Build solara-meta + run: (cd packages/solara-meta; hatch build) + - name: Build solara-enterprise run: (cd packages/solara-enterprise; hatch build) @@ -87,6 +96,10 @@ jobs: name: solara-builds-${{ github.run_number }} path: | dist + packages/assets/dist + packages/solara-server/dist + packages/solara-meta/dist + packages/pytest-ipywidgets/dist packages/solara-enterprise/dist packages/solara-vuetify-app/dist packages/solara-vuetify3-app/dist @@ -170,12 +183,17 @@ jobs: - name: Debug run: ls -R dist - - name: Install - run: pip install dist/*.whl + - name: Install solara-ui + run: + pip install dist/*.whl - name: Test import run: python -c "import solara" + - name: Install solara-server + run: + pip install `echo packages/solara-server/dist/*.whl`[starlette] + - name: Run solara create run: solara create button test.py @@ -192,6 +210,11 @@ jobs: - name: Test import run: python -c "import solara_enterprise" + - name: Install solara-meta + run: + pip install packages/solara-meta/dist/*.whl + + integration-test: needs: [build] timeout-minutes: 15 @@ -246,17 +269,23 @@ jobs: id: install_no_lock run: | mkdir -p .ci-package-locks/integration - pip install `echo dist/*.whl`[dev,documentation,flask,pytest] + pip install `echo dist/*.whl`[all] + pip install `echo packages/solara-server/dist/*.whl`[all] + pip install `echo packages/pytest-ipywidgets/dist/*.whl`[all] + pip install `echo packages/solara-meta/dist/*.whl`[dev,documentation] pip install `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] pip install "voila~=${{ matrix.voila }}" "jupyterlab<4" "pydantic<2" "playwright==1.41.2" "ipywidgets~=${{ matrix.ipywidgets }}" - pip freeze --exclude solara --exclude solara-enterprise > ${{ env.LOCK_FILE_LOCATION }} + pip freeze --exclude solara --exclude solara-ui --exclude solara-server --exclude pytest-ipywidgets--exclude solara-enterprise > ${{ env.LOCK_FILE_LOCATION }} git diff --quiet || echo "HAS_DIFF=true" >> "$GITHUB_OUTPUT" - name: Install if: github.event_name != 'schedule' && steps.prepare.outputs.LOCKS_EXIST == 'true' run: | pip install -r ${{ env.LOCK_FILE_LOCATION }} - pip install `echo dist/*.whl`[dev,documentation,flask,pytest] + pip install `echo dist/*.whl`[all] + pip install `echo packages/solara-server/dist/*.whl`[all] + pip install `echo packages/pytest-ipywidgets/dist/*.whl`[all] + pip install `echo packages/solara-meta/dist/*.whl`[dev,documentation] pip install `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] - name: Install playwright @@ -340,19 +369,25 @@ jobs: if: github.event_name == 'schedule' || steps.prepare.outputs.LOCKS_EXIST == 'false' run: | mkdir -p .ci-package-locks/integration-vue3 - pip install `echo dist/*.whl`[dev,documentation,flask,pytest] + pip install `echo dist/*.whl`[all] + pip install `echo packages/solara-server/dist/*.whl`[all] + pip install `echo packages/pytest-ipywidgets/dist/*.whl`[all] + pip install `echo packages/solara-meta/dist/*.whl`[dev,documentation] pip install `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] pip install "jupyterlab<4" "voila~=${{ matrix.voila }}" "playwright==1.41.2" "pydantic<2" "ipywidgets~=${{ matrix.ipywidgets }}" pip install jupyter_core jupyter-packaging pip install --pre ipyvue ipyvuetify - pip freeze --exclude solara --exclude solara-enterprise > ${{ env.LOCK_FILE_LOCATION }} + pip freeze --exclude solara --exclude solara-ui --exclude solara-server --exclude pytest-ipywidgets --exclude solara-enterprise > ${{ env.LOCK_FILE_LOCATION }} git diff --quiet || echo "HAS_DIFF=true" >> "$GITHUB_OUTPUT" - name: Install if: github.event_name != 'schedule' && steps.prepare.outputs.LOCKS_EXIST == 'true' run: | pip install -r ${{ env.LOCK_FILE_LOCATION }} - pip install `echo dist/*.whl`[dev,documentation,flask,pytest] + pip install `echo dist/*.whl`[all] + pip install `echo packages/solara-server/dist/*.whl`[all] + pip install `echo packages/pytest-ipywidgets/dist/*.whl`[all] + pip install `echo packages/solara-meta/dist/*.whl`[dev,documentation] pip install `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] - name: Install playwright @@ -432,17 +467,23 @@ jobs: if: github.event_name == 'schedule' || steps.prepare.outputs.LOCKS_EXIST == 'false' run: | mkdir -p .ci-package-locks/unit - pip install `echo dist/*.whl`[dev,extra] + pip install `echo dist/*.whl`[all] + pip install `echo packages/solara-server/dist/*.whl`[all] + pip install `echo packages/pytest-ipywidgets/dist/*.whl`[all] + pip install `echo packages/solara-meta/dist/*.whl`[dev,extra] pip install `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] pip install "jupyterlab<4" diskcache redis "ipywidgets~=${{ matrix.ipywidgets }}" - pip freeze --exclude solara --exclude solara-enterprise > ${{ env.LOCK_FILE_LOCATION }} + pip freeze --exclude solara --exclude solara-ui --exclude solara-server --exclude pytest-ipywidgets--exclude solara-enterprise > ${{ env.LOCK_FILE_LOCATION }} git diff --quiet || echo "HAS_DIFF=true" >> "$GITHUB_OUTPUT" - name: Install if: github.event_name != 'schedule' && steps.prepare.outputs.LOCKS_EXIST == 'true' run: | pip install -r ${{ env.LOCK_FILE_LOCATION }} - pip install `echo dist/*.whl`[dev,extra] + pip install `echo dist/*.whl`[all] + pip install `echo packages/solara-server/dist/*.whl`[all] + pip install `echo packages/pytest-ipywidgets/dist/*.whl`[all] + pip install `echo packages/solara-meta/dist/*.whl`[dev,extra] pip install `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] - name: Start Redis @@ -498,7 +539,6 @@ jobs: release: needs: [build, code-quality, test-install, integration-test, integration-test-vue3, unit-test] - if: startsWith(github.event.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: @@ -516,10 +556,16 @@ jobs: - name: Install build tools run: pip install hatch - - name: Install solara + - name: Install solara-ui run: pip install dist/*.whl - - name: Test import + - name: Test import solara-ui + run: python -c "import solara" + + - name: Install solara-server + run: pip install `echo packages/solara-server/dist/*.whl`[starlette] + + - name: Test import of solara-server run: python -c "import solara; import solara.server.starlette" - name: Install solara-enterprise @@ -528,14 +574,19 @@ jobs: - name: Test import solara-enterprise run: python -c "import solara_enterprise" - - uses: actions/setup-node@v4 - with: - node-version: 20 - - - name: Build assets - run: (cd packages/assets; hatch build) + - name: Publish solara-meta to PyPI + if: startsWith(github.event.ref, 'refs/tags/v') + env: + HATCH_INDEX_USER: __token__ + HATCH_INDEX_AUTH: ${{ secrets.pypi_password }} + run: | + cd packages/solara-meta + openssl sha256 dist/* + hatch publish + openssl sha256 dist/* - name: Publish solara-enterprise to PyPI + if: startsWith(github.event.ref, 'refs/tags/v') env: HATCH_INDEX_USER: __token__ HATCH_INDEX_AUTH: ${{ secrets.pypi_enterprise }} @@ -545,20 +596,37 @@ jobs: hatch publish openssl sha256 dist/* - - name: Publish solara to PyPI + - name: Publish solara-assets to PyPI + if: startsWith(github.event.ref, 'refs/tags/v') env: HATCH_INDEX_USER: __token__ - HATCH_INDEX_AUTH: ${{ secrets.pypi_password }} + HATCH_INDEX_AUTH: ${{ secrets.pypi_assets }} run: | + cd packages/assets openssl sha256 dist/* hatch publish openssl sha256 dist/* - - name: Publish solara-assets to PyPI + - name: Publish solara-ui to PyPI + if: startsWith(github.event.ref, 'refs/tags/v') env: HATCH_INDEX_USER: __token__ - HATCH_INDEX_AUTH: ${{ secrets.pypi_assets }} - run: (cd packages/assets; openssl sha256 dist/*; hatch publish; openssl sha256 dist/*) + HATCH_INDEX_AUTH: ${{ secrets.pypi_ui }} + run: | + openssl sha256 dist/* + hatch publish + openssl sha256 dist/* + + - name: Publish solara-server to PyPI + if: startsWith(github.event.ref, 'refs/tags/v') + env: + HATCH_INDEX_USER: __token__ + HATCH_INDEX_AUTH: ${{ secrets.pypi_server }} + run: | + cd packages/solara-server + openssl sha256 dist/* + hatch publish + openssl sha256 dist/* - name: remove assets run: rm -rf packages/assets/dist diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d6c3243fa..fa12d7b6b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,4 +28,4 @@ repos: pass_filenames: false args: [--explicit-package-bases, .] additional_dependencies: [types-requests, types-markdown, types-PyYAML, types-filelock, types-cachetools, types-redis, types-python-dateutil, types-pycurl, reacton, types-six, types-decorator, ipython, ipykernel] - exclude: tests/unit/solara_test_apps/multipage/04-a_directory/* + exclude: tests/unit/solara_test_apps/multipage/04-a_directory/*|nogit diff --git a/mypy.ini b/mypy.ini index b6c98ecca..f10eacef1 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,5 +1,5 @@ [mypy] check_untyped_defs = True ignore_missing_imports = True -exclude=04-a_directory +exclude=04-a_directory|nogit no_implicit_optional = False diff --git a/packages/assets/LICENSE b/packages/pytest-ipywidgets/LICENSE similarity index 100% rename from packages/assets/LICENSE rename to packages/pytest-ipywidgets/LICENSE diff --git a/packages/pytest-ipywidgets/README.md b/packages/pytest-ipywidgets/README.md new file mode 100644 index 000000000..a875b4aad --- /dev/null +++ b/packages/pytest-ipywidgets/README.md @@ -0,0 +1,41 @@ +Test ipywidgets with playwright and pytest. + + +# Installation + +```bash +pip install "pytest-ipywidgets[all]" +``` + +*(Note that the optional `[all]` installs all dependencies, including compatible versions of notebook, jupyterlab and voila.)* + +# Usage + +## Using solara-server (in-process) + +If you want to test your ipywidgets with playwright in-process, you can use the `solara_test` fixture, use `display` to +show your widget in the browser. + +```python +import ipywidgets as widgets +import playwright.sync_api +from IPython.display import display + +def test_widget_button_solara(solara_test, page_session: playwright.sync_api.Page): + # this all runs in-process + button = widgets.Button(description="Click Me!") + + def change_description(obj): + button.description = "Tested event" + + button.on_click(change_description) + display(button) + button_sel = page_session.locator("text=Click Me!") + button_sel.wait_for() + button_sel.click() + page_session.locator("text=Tested event").wait_for() +``` + +# Testing in the main Jupyter Environments (Notebook, Lab, Voila & Solara) + +See https://solara.dev/documentation/advanced/howto/testing for more information. diff --git a/packages/pytest-ipywidgets/pyproject.toml b/packages/pytest-ipywidgets/pyproject.toml new file mode 100644 index 000000000..e8c7ac42c --- /dev/null +++ b/packages/pytest-ipywidgets/pyproject.toml @@ -0,0 +1,56 @@ +[build-system] +requires = ["hatchling==1.22.2"] +build-backend = "hatchling.build" + + +[project] +name = "pytest-ipywidgets" +readme = "README.md" +authors = [{name = "Maarten A. Breddels", email = "maartenbreddels@gmail.com"}] +license = {file = "LICENSE"} +classifiers = ["License :: OSI Approved :: MIT License"] +dynamic = ["description"] +version = "1.30.1" +dependencies = [ + "solara-ui==1.30.1", + "solara-server[starlette]==1.30.1", + "pytest", + "playwright; python_version > '3.6'", + "pytest-playwright; python_version > '3.6'", + "pillow", + "pixelmatch", +] + +[project.urls] +Home = "https://github.com/widgetti/solara/tree/master/packages/pytest-ipywidgets" +Documentation = "https://solara.dev" + +[project.optional-dependencies] +all = [ + "pytest-ipywidgets[voila]", + "pytest-ipywidgets[jupyterlab]", + "pytest-ipywidgets[notebook]", +] +# currently empty, but in the future we want to make the core package not depend +# on solara, but now we can have the docs future compatible. +solara = [ +] + +voila = [ + "voila", +] +jupyterlab = [ + "jupyterlab<4", +] +notebook = [ + "notebook<7", +] + +[project.entry-points.pytest11] +solara = "solara.test.pytest_plugin" + +[tool.hatch.build.targets.wheel] +include = ["LICENSE"] + +[tool.hatch.build.targets.sdist] +include = ["LICENSE"] diff --git a/packages/assets/.gitignore b/packages/solara-assets/.gitignore similarity index 100% rename from packages/assets/.gitignore rename to packages/solara-assets/.gitignore diff --git a/packages/solara-assets/LICENSE b/packages/solara-assets/LICENSE new file mode 100644 index 000000000..ac0f63fe7 --- /dev/null +++ b/packages/solara-assets/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 Maarten A. Breddels + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/assets/RELEASE.md b/packages/solara-assets/RELEASE.md similarity index 100% rename from packages/assets/RELEASE.md rename to packages/solara-assets/RELEASE.md diff --git a/packages/assets/download_cdn_test.py b/packages/solara-assets/download_cdn_test.py similarity index 100% rename from packages/assets/download_cdn_test.py rename to packages/solara-assets/download_cdn_test.py diff --git a/packages/assets/hatch_build.py b/packages/solara-assets/hatch_build.py similarity index 100% rename from packages/assets/hatch_build.py rename to packages/solara-assets/hatch_build.py diff --git a/packages/assets/pyproject.toml b/packages/solara-assets/pyproject.toml similarity index 100% rename from packages/assets/pyproject.toml rename to packages/solara-assets/pyproject.toml diff --git a/packages/assets/solara_assets/__init__.py b/packages/solara-assets/solara_assets/__init__.py similarity index 100% rename from packages/assets/solara_assets/__init__.py rename to packages/solara-assets/solara_assets/__init__.py diff --git a/packages/solara-enterprise/pyproject.toml b/packages/solara-enterprise/pyproject.toml index db301dc20..6e877aa44 100644 --- a/packages/solara-enterprise/pyproject.toml +++ b/packages/solara-enterprise/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["hatchling"] +requires = ["hatchling==1.22.2"] build-backend = "hatchling.build" [project] @@ -11,7 +11,8 @@ license = {file = "LICENSE"} classifiers = ["License :: Free for non-commercial use"] dynamic = ["version", "description"] dependencies = [ - "solara==1.30.1", + "solara-ui==1.30.1", + "solara-server==1.30.1", ] [project.optional-dependencies] diff --git a/packages/solara-meta/LICENSE b/packages/solara-meta/LICENSE new file mode 100644 index 000000000..ac0f63fe7 --- /dev/null +++ b/packages/solara-meta/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 Maarten A. Breddels + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/solara-meta/README.md b/packages/solara-meta/README.md new file mode 100644 index 000000000..1fa1d6502 --- /dev/null +++ b/packages/solara-meta/README.md @@ -0,0 +1,3 @@ +A meta packages that installs all the necessary dependencies to get started with Solara. + +See https://solara.dev/documentation/getting_started/installing for more information. diff --git a/packages/solara-meta/main.README.md b/packages/solara-meta/main.README.md new file mode 100644 index 000000000..1b7d1ae12 --- /dev/null +++ b/packages/solara-meta/main.README.md @@ -0,0 +1,106 @@ +**A Pure Python, React-style Framework for Scaling Your Jupyter and Web Apps** + +[![solara logo](https://solara.dev/static/assets/images/logo.svg)](https://solara.dev) + +Come chat with us on [Discord](https://discord.solara.dev) to ask questions or share your thoughts or creations! + +[![Discord Shield](https://discordapp.com/api/guilds/1106593685241614489/widget.png?style=banner2)](https://discord.solara.dev) + + + +## Introducing Solara + +While there are many Python web frameworks out there, most are designed for small data apps or use paradigms unproven for larger scale. Code organization, reusability, and state tend to suffer as apps grow in complexity, resulting in either spaghetti code or offloading to a React application. + +Solara addresses this gap. Using a React-like API, we don't need to worry about scalability. React has already proven its ability to support the world's largest web apps. + +Solara uses a pure Python implementation of React (Reacton), creating ipywidget-based applications. These apps work both inside the Jupyter Notebook and as standalone web apps with frameworks like FastAPI. This paradigm enables component-based code and incredibly simple state management. + +By building on top of ipywidgets, we automatically leverage an existing ecosystem of widgets and run on many platforms, including JupyterLab, Jupyter Notebook, Voilà, Google Colab, DataBricks, JetBrains Datalore, and more. + +We care about developer experience. Solara will give your hot code reloading and type hints for faster development. + +## Installation + +Run: +``` +pip install solara +``` + +Or follow the [Installation instructions](https://solara.dev/documentation/getting_started/installing) for more detailed instructions. + +## First script + +Put the following Python snippet in a file (we suggest `sol.py`), or put it in a Jupyter notebook cell: + +```python +import solara + +# Declare reactive variables at the top level. Components using these variables +# will be re-executed when their values change. +sentence = solara.reactive("Solara makes our team more productive.") +word_limit = solara.reactive(10) + + +@solara.component +def Page(): + # Calculate word_count within the component to ensure re-execution when reactive variables change. + word_count = len(sentence.value.split()) + + solara.SliderInt("Word limit", value=word_limit, min=2, max=20) + solara.InputText(label="Your sentence", value=sentence, continuous_update=True) + + # Display messages based on the current word count and word limit. + if word_count >= int(word_limit.value): + solara.Error(f"With {word_count} words, you passed the word limit of {word_limit.value}.") + elif word_count >= int(0.8 * word_limit.value): + solara.Warning(f"With {word_count} words, you are close to the word limit of {word_limit.value}.") + else: + solara.Success("Great short writing!") + + +# The following line is required only when running the code in a Jupyter notebook: +Page() +``` + +Run from the command line in the same directory where you put your file (`sol.py`): + +```bash +$ solara run sol.py +Solara server is starting at http://localhost:8765 +``` + +Or copy-paste this to a Jupyter notebook cell and execute it (the `Page()` expression at the end +will cause it to automatically render the component in the notebook). + +See this snippet run live at https://solara.dev/documentation/getting_started + +## Demo + +The following demo app can be used to explore a dataset (buildin or upload yourself) using +a scatter plot. The plot can be interacted with to filter the dataset, and the filtered dataset can +be downloaded. + + * [Source code](https://github.com/widgetti/solara/blob/master/solara/website/pages/apps/scatter.py) + +### Running in solara-server + +The solara server is build on top of Starlette/FastAPI and runs standalone. Ideal for production use. + +![fastapi](https://global.discourse-cdn.com/standard11/uploads/jupyter/original/2X/9/9442fc70e2a1fcd201f4f900fa073698a1f8c937.gif) + + +### Running in Jupyter + +By building on top of ipywidgets, we automatically leverage an existing ecosystem of widgets and run on many platforms, including JupyterLab, Jupyter Notebook, Voilà, Google Colab, DataBricks, JetBrains Datalore, and more. This means our app can also run in Jupyter: + +![jupyter](https://global.discourse-cdn.com/standard11/uploads/jupyter/original/2X/8/8bc875c0c3845ae077168575a4f8a49cf1b35bc6.gif) + +## Resources + +Visit our main website or jump directly to the introduction + +[![Introduction](https://dabuttonfactory.com/button.png?t=Introduction&f=Open+Sans-Bold&ts=20&tc=fff&hp=45&vp=12&c=8&bgt=unicolored&bgc=f19f41)](https://solara.dev/documentation) +[![Quickstart](https://dabuttonfactory.com/button.png?t=Quickstart&f=Open+Sans-Bold&ts=20&tc=fff&hp=45&vp=12&c=8&bgt=unicolored&bgc=f19f41)](https://solara.dev/documentation/getting_started) + +*Note that the solara.dev website is created using Solara* diff --git a/packages/solara-meta/pyproject.toml b/packages/solara-meta/pyproject.toml new file mode 100644 index 000000000..a84e2b610 --- /dev/null +++ b/packages/solara-meta/pyproject.toml @@ -0,0 +1,84 @@ +[build-system] +requires = ["hatchling==1.22.2"] +build-backend = "hatchling.build" + + +[project] +name = "solara" +readme = "main.README.md" +authors = [{name = "Maarten A. Breddels", email = "maartenbreddels@gmail.com"}] +license = {file = "LICENSE"} +classifiers = ["License :: OSI Approved :: MIT License"] +dynamic = ["description"] +version = "1.30.1" +packages = [ + { include = "solara" } +] +dependencies = [ + "solara-ui[all]==1.30.1", + "solara-server[starlette,dev]==1.30.1" +] + +[project.urls] +Home = "https://www.github.com/widgetti/solara" +Documentation = "https://solara.dev" + +[project.optional-dependencies] +assets = [ + "solara-assets==1.30.1" +] + +documentation = [ + "bqplot", + "altair", + "folium", + "ipycanvas", + "ipyleaflet", + "matplotlib", + "vega_datasets", + "openai", + "plotly", + "vaex-core", + "vaex-hdf5", + "tiktoken", +] + +# for backwards compatibility to support solara[pytest] +pytest = [ + "pytest-ipywidgets[all]==1.30.1" +] + +# for backwards compatibility to support solara[dev] +dev = [ + "codespell", + "python-dotenv", + "bqplot", + "bqplot-image-gl", + "ipyreact; python_version > '3.6'", + "vaex-core", + "vaex-hdf5", + "vaex-jupyter", + "mypy", + "mdit-py-plugins", + "plotly", + "types-requests", + "types-markdown", + "types-PyYAML", + "pytest", + "pytest-mock", + "pytest-cov", + "pytest-timeout", + "pre-commit", + "ruff; python_version > '3.6'", + "bump2version", + "dask[dataframe]; python_version < '3.7'", + "playwright; python_version > '3.6'", + "pytest-playwright; python_version > '3.6'", + "polars", +] + +[tool.hatch.build.targets.wheel] +include = ["LICENSE"] + +[tool.hatch.build.targets.sdist] +include = ["LICENSE"] diff --git a/packages/solara-server/LICENSE b/packages/solara-server/LICENSE new file mode 100644 index 000000000..ac0f63fe7 --- /dev/null +++ b/packages/solara-server/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 Maarten A. Breddels + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/solara-server/README.md b/packages/solara-server/README.md new file mode 100644 index 000000000..88f9e04f0 --- /dev/null +++ b/packages/solara-server/README.md @@ -0,0 +1,15 @@ +The solara server enables running ipywidgets based applications without a real Jupyter kernel, allowing multiple "Virtual kernels" to share the same process for better performance and scalability. + +See https://solara.dev/documentation/advanced/understanding/solara-server for more details. + +## Installation + +```bash +pip install solara-server[starlette,dev] +``` + +## Usage + +```bash +$ solara run myapp.py +``` diff --git a/packages/solara-server/pyproject.toml b/packages/solara-server/pyproject.toml new file mode 100644 index 000000000..87e933887 --- /dev/null +++ b/packages/solara-server/pyproject.toml @@ -0,0 +1,56 @@ +[build-system] +requires = ["hatchling==1.22.2"] +build-backend = "hatchling.build" + + +[project] +name = "solara-server" +readme = "README.md" +authors = [{name = "Maarten A. Breddels", email = "maartenbreddels@gmail.com"}] +license = {file = "LICENSE"} +classifiers = ["License :: OSI Approved :: MIT License"] +version = "1.30.1" +dynamic = ["description"] +dependencies = [ + "solara-ui", + "jinja2", + "click>=7.1.0", + "rich_click", + "filelock", + "ipykernel", + "nbformat", + "jupyter_client>=7.0.0", +] + +[project.urls] +Home = "https://www.github.com/widgetti/solara" +Documentation = "https://solara.dev" + +[project.optional-dependencies] +all = [ + "solara-server[dev]", + "solara-server[starlette]", + "solara-server[flask]", +] +dev = [ + "watchfiles; python_version > '3.6'", + "watchdog", +] +starlette = [ + "uvicorn", + "websockets", + "starlette", +] +flask = [ + "flask", + "flask-sock", +] + +[project.scripts] +solara = "solara.__main__:main" + +[tool.hatch.build.targets.wheel] +include = ["LICENSE"] + +[tool.hatch.build.targets.sdist] +include = ["LICENSE"] diff --git a/packages/solara-vuetify-app/.bumpversion.cfg b/packages/solara-vuetify-app/.bumpversion.cfg index f4805a49d..5e87a5afb 100644 --- a/packages/solara-vuetify-app/.bumpversion.cfg +++ b/packages/solara-vuetify-app/.bumpversion.cfg @@ -12,4 +12,4 @@ message = Bump version solara-vuetify-app: {current_version} → {new_version} [bumpversion:file:../../release.sh] -[bumpversion:file:../assets/hatch_build.py] +[bumpversion:file:../solara-assets/hatch_build.py] diff --git a/packages/solara-vuetify3-app/.bumpversion.cfg b/packages/solara-vuetify3-app/.bumpversion.cfg index 99d25dbd2..2e519d1b8 100644 --- a/packages/solara-vuetify3-app/.bumpversion.cfg +++ b/packages/solara-vuetify3-app/.bumpversion.cfg @@ -12,4 +12,4 @@ message = Bump version solara-vuetify3-app: {current_version} → {new_version} [bumpversion:file:../../release.sh] -[bumpversion:file:../assets/hatch_build.py] +[bumpversion:file:../solara-assets/hatch_build.py] diff --git a/pyproject.toml b/pyproject.toml index 9a9432654..dc84ba473 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ [build-system] -requires = ["hatchling"] +requires = ["hatchling==1.22.2"] build-backend = "hatchling.build" [project] -name = "solara" +name = "solara-ui" readme = "README.md" authors = [{name = "Maarten A. Breddels", email = "maartenbreddels@gmail.com"}] license = {file = "LICENSE"} @@ -15,29 +15,17 @@ packages = [ ] dependencies = [ "reacton>=1.7.1", - "ipywidgets", - "cachetools", - "filelock", - "markdown", - "pymdown-extensions", - "humanize", - "ipyvuetify>=1.8.10", + "ipywidgets>=7.7", + "ipyvuetify>=1.6.10", "ipyvue>=1.9.0", - "jinja2", - "MarkupSafe", - "click>=7.1.0", - "rich_click", - "uvicorn", - "websockets", - "starlette", - "jupyter_client>=7.0.0", - "watchdog", "requests", - "nbformat", - "ipykernel", - "watchfiles; python_version > '3.6'", + "humanize", ] +[project.urls] +Home = "https://www.github.com/widgetti/solara" +Documentation = "https://solara.dev" + [tool.hatch.build.targets.wheel.shared-data] "prefix/etc/jupyter" = "etc/jupyter" @@ -49,6 +37,14 @@ path = "solara/__init__.py" [tool.hatch.build] ignore-vcs = true +[tool.hatch.build.targets.wheel] +include = [ + "solara", + "prefix", + "packages/solara-widget-manager/LICENSE.voila.txt", +] +exclude = ["packages"] + [tool.hatch.build.targets.sdist] # unclear from hatch docs, but README.md and LICENSE are included by default # even when we explicitly have an include list @@ -63,81 +59,28 @@ include = [ exclude = ["packages"] [project.optional-dependencies] -extra = [ - "pygments", - "numpy", - "pillow", +all = [ + "solara-ui[markdown]", + "solara-ui[cache]", + "solara-ui[extra]", +] + +markdown = [ + "markdown", + "pymdown-extensions", "pygments", "pygments==2.10; python_version < '3.7'", ] -dev = [ - "codespell", - "python-dotenv", - "bqplot", - "bqplot-image-gl", - "ipyreact; python_version > '3.6'", - "vaex-core", - "vaex-hdf5", - "vaex-jupyter", - "mypy", - "mdit-py-plugins", - "plotly", - "types-requests", - "types-markdown", - "types-PyYAML", - "pytest", - "pytest-mock", - "pytest-cov", - "pytest-timeout", - "pre-commit", - "ruff; python_version > '3.6'", - "bump2version", - "dask[dataframe]; python_version < '3.7'", - "playwright; python_version > '3.6'", - "pytest-playwright; python_version > '3.6'", - "polars", -] -assets = [ - "solara-assets==1.30.1" -] -flask = [ - "flask", - "flask-sock", + +cache = [ + "cachetools" ] -documentation = [ + +extra = [ "numpy", - "bqplot", - "altair", - "folium", - "ipycanvas", - "ipyleaflet", - "matplotlib", - "vega_datasets", - "openai", - "plotly", - "vaex-core", - "vaex-hdf5", - "tiktoken", -] -pytest = [ - "pytest", - "playwright; python_version > '3.6'", - "pytest-playwright; python_version > '3.6'", - "voila", - "jupyterlab", "pillow", - "pixelmatch", ] -[project.urls] -Home = "https://www.github.com/widgetti/solara" - -[project.scripts] -solara = "solara.__main__:main" - -[project.entry-points.pytest11] -solara = "solara.test.pytest_plugin" - [tool.ruff] fix = false line-length = 160 @@ -149,4 +92,4 @@ timeout = 180 [tool.codespell] -skip='equis-in-vidi.md,substiterat-vati.md,.*,solara/website/build,*.svg,highlight-dark.css,packages/**/dist/*,node_modules,packages/assets,package*.json,tsconfig.tsbuildinfo,*.csv' +skip='equis-in-vidi.md,substiterat-vati.md,.*,solara/website/build,*.svg,highlight-dark.css,packages/**/dist/*,node_modules,packages/solara-assets,package*.json,tsconfig.tsbuildinfo,*.csv' diff --git a/requirements.txt b/requirements.txt index a91553d46..d07a29acb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,3 @@ -ipyvuetify -reacton -bqplot -plotly -.[server,documentation] -./packages/solara-enterprise[all] -playwright -vega_datasets -altair +-e .[all] +-e ./packages/solara-server[all] +-e ./packages/solara-enterprise[all] diff --git a/solara/autorouting.py b/solara/autorouting.py index 1b3300646..292037787 100644 --- a/solara/autorouting.py +++ b/solara/autorouting.py @@ -37,6 +37,7 @@ def source_to_module(path: Path, initial_namespace={}) -> ModuleType: ast = compile(f.read(), path, "exec") exec(ast, mod.__dict__) elif path.suffix == ".ipynb": + # TODO: this is a dependency of solara-server, but this packages is in solara-ui import nbformat nb: nbformat.NotebookNode = nbformat.read(path, 4) diff --git a/solara/cache.py b/solara/cache.py index 10933eb1f..5ef4fd148 100644 --- a/solara/cache.py +++ b/solara/cache.py @@ -15,7 +15,13 @@ overload, ) -import cachetools +try: + import cachetools + + has_cachetools = True +except ModuleNotFoundError: + has_cachetools = False + import solara import solara.settings import solara.util @@ -39,9 +45,15 @@ Storage = MutableMapping[K, V] -class Memory(cachetools.LRUCache): - def __init__(self, max_items=solara.settings.cache.memory_max_items): - super().__init__(maxsize=max_items) +if has_cachetools: + + class Memory(cachetools.LRUCache): + def __init__(self, max_items=solara.settings.cache.memory_max_items): + super().__init__(maxsize=max_items) +else: + + class Memory(dict): # type: ignore + pass def _default_key(*args, **kwargs): diff --git a/solara/components/markdown.py b/solara/components/markdown.py index 6c6a03a16..fcb1b6ecc 100644 --- a/solara/components/markdown.py +++ b/solara/components/markdown.py @@ -7,9 +7,15 @@ from typing import Any, Dict, List, Union, cast import ipyvuetify as v -import pymdownx.emoji -import pymdownx.highlight -import pymdownx.superfences + +try: + import pymdownx.emoji + import pymdownx.highlight + import pymdownx.superfences + + has_pymdownx = True +except ModuleNotFoundError: + has_pymdownx = False import solara import solara.components.applayout @@ -271,7 +277,8 @@ def highlight_code(code, name, attrs): return v.VuetifyTemplate.element(template=_markdown_template(html)).key(hash) -_index = pymdownx.emoji.emojione(None, None) +if has_pymdownx: + _index = pymdownx.emoji.emojione(None, None) def _no_deep_copy_emojione(options, md): diff --git a/solara/lab/__init__.py b/solara/lab/__init__.py index 65ed389b9..e0c6b94e1 100644 --- a/solara/lab/__init__.py +++ b/solara/lab/__init__.py @@ -1,7 +1,7 @@ # isort: skip_file from .components import * # noqa: F401, F403 from .utils import cookies, headers # noqa: F401, F403 -from ..server.kernel_context import on_kernel_start # noqa: F401 +from ..lifecycle import on_kernel_start # noqa: F401 from ..tasks import task, use_task, Task, TaskResult # noqa: F401, F403 from ..toestand import computed # noqa: F401 diff --git a/solara/lifecycle.py b/solara/lifecycle.py new file mode 100644 index 000000000..fa03e6d28 --- /dev/null +++ b/solara/lifecycle.py @@ -0,0 +1,46 @@ +from types import FrameType, ModuleType +from typing import Callable, List, NamedTuple, Optional +from pathlib import Path +import inspect + + +class _on_kernel_callback_entry(NamedTuple): + callback: Callable[[], Optional[Callable[[], None]]] + callpoint: Optional[Path] + module: Optional[ModuleType] + cleanup: Callable[[], None] + + +_on_kernel_start_callbacks: List[_on_kernel_callback_entry] = [] + + +def _find_root_module_frame() -> Optional[FrameType]: + # basically the module where the call stack origined from + current_frame = inspect.currentframe() + root_module_frame = None + + while current_frame is not None: + if current_frame.f_code.co_name == "": + root_module_frame = current_frame + break + current_frame = current_frame.f_back + + return root_module_frame + + +def on_kernel_start(f: Callable[[], Optional[Callable[[], None]]]) -> Callable[[], None]: + root = _find_root_module_frame() + path: Optional[Path] = None + module: Optional[ModuleType] = None + if root is not None: + path_str = inspect.getsourcefile(root) + module = inspect.getmodule(root) + if path_str is not None: + path = Path(path_str) + + def cleanup(): + return _on_kernel_start_callbacks.remove(kce) + + kce = _on_kernel_callback_entry(f, path, module, cleanup) + _on_kernel_start_callbacks.append(kce) + return cleanup diff --git a/solara/server/app.py b/solara/server/app.py index 6dd251862..59f37363b 100644 --- a/solara/server/app.py +++ b/solara/server/app.py @@ -16,6 +16,7 @@ from reacton.core import Element, render import solara +import solara.lifecycle from solara.util import nested_get from . import kernel_context, patch, reload, settings @@ -252,7 +253,7 @@ def reload(self): # we need to remove callbacks that are added in the app code # which will be re-executed after the reload and we do not # want to keep executing the old ones. - for kc in kernel_context._on_kernel_start_callbacks.copy(): + for kc in solara.lifecycle._on_kernel_start_callbacks.copy(): callback, path, module, cleanup = kc will_reload = False if module is not None: diff --git a/solara/server/kernel_context.py b/solara/server/kernel_context.py index 9e6bd45ed..731b9f3b4 100644 --- a/solara/server/kernel_context.py +++ b/solara/server/kernel_context.py @@ -8,7 +8,6 @@ import dataclasses import enum -import inspect import logging import os import pickle @@ -16,8 +15,7 @@ import time import typing from pathlib import Path -from types import FrameType, ModuleType -from typing import Any, Callable, Dict, List, NamedTuple, Optional, cast +from typing import Any, Callable, Dict, List, Optional, cast import ipywidgets as widgets import reacton @@ -27,6 +25,7 @@ import solara.util from . import kernel, kernel_context, websocket +from .. import lifecycle from .kernel import Kernel, WebsocketStreamWrapper WebSocket = Any @@ -46,48 +45,6 @@ class PageStatus(enum.Enum): CLOSED = "closed" -class _on_kernel_callback_entry(NamedTuple): - callback: Callable[[], Optional[Callable[[], None]]] - callpoint: Optional[Path] - module: Optional[ModuleType] - cleanup: Callable[[], None] - - -_on_kernel_start_callbacks: List[_on_kernel_callback_entry] = [] - - -def _find_root_module_frame() -> Optional[FrameType]: - # basically the module where the call stack origined from - current_frame = inspect.currentframe() - root_module_frame = None - - while current_frame is not None: - if current_frame.f_code.co_name == "": - root_module_frame = current_frame - break - current_frame = current_frame.f_back - - return root_module_frame - - -def on_kernel_start(f: Callable[[], Optional[Callable[[], None]]]) -> Callable[[], None]: - root = _find_root_module_frame() - path: Optional[Path] = None - module: Optional[ModuleType] = None - if root is not None: - path_str = inspect.getsourcefile(root) - module = inspect.getmodule(root) - if path_str is not None: - path = Path(path_str) - - def cleanup(): - return _on_kernel_start_callbacks.remove(kce) - - kce = _on_kernel_callback_entry(f, path, module, cleanup) - _on_kernel_start_callbacks.append(kce) - return cleanup - - @dataclasses.dataclass class VirtualKernelContext: id: str @@ -119,7 +76,7 @@ class VirtualKernelContext: def __post_init__(self): with self: - for f, *_ in _on_kernel_start_callbacks: + for f, *_ in lifecycle._on_kernel_start_callbacks: cleanup = f() if cleanup: self.on_close(cleanup) diff --git a/solara/server/settings.py b/solara/server/settings.py index 9d4007603..970e4a066 100644 --- a/solara/server/settings.py +++ b/solara/server/settings.py @@ -8,7 +8,10 @@ from pathlib import Path from typing import Optional -from filelock import FileLock +try: + from filelock import FileLock +except ModuleNotFoundError: + FileLock = None # type: ignore import solara.util from solara.minisettings import BaseSettings @@ -184,7 +187,7 @@ class Config: # in this case, we would need to install solara-assets? pass -if telemetry.server_user_id == "not_set": +if telemetry.server_user_id == "not_set" and FileLock is not None: home = get_solara_home() server_user_id_file = home / "server_user_id.txt" try: diff --git a/solara/toestand.py b/solara/toestand.py index 1f74399cc..5f1862155 100644 --- a/solara/toestand.py +++ b/solara/toestand.py @@ -377,7 +377,7 @@ class Singleton(Reactive[S]): _storage: KernelStore[S] def __init__(self, factory: Callable[[], S], key=None): - import solara.server.kernel_context + import solara.lifecycle super().__init__(KernelStoreFactory(factory, key=key)) @@ -388,7 +388,7 @@ def cleanup(): return cleanup - solara.server.kernel_context.on_kernel_start(reset) + solara.lifecycle.on_kernel_start(reset) def __set__(self, obj, value): raise AttributeError("Can't set a singleton") @@ -398,6 +398,8 @@ class Computed(Reactive[S]): _storage: KernelStore[S] def __init__(self, f: Callable[[], S], key=None): + import solara.lifecycle + self.f = f def on_change(*ignore): @@ -423,7 +425,7 @@ def cleanup(): return cleanup - solara.server.kernel_context.on_kernel_start(reset) + solara.lifecycle.on_kernel_start(reset) def __repr__(self): value = super().__repr__() diff --git a/solara/website/pages/documentation/advanced/content/10-howto/30-testing.md b/solara/website/pages/documentation/advanced/content/10-howto/30-testing.md index ae38b7f07..167fe737f 100644 --- a/solara/website/pages/documentation/advanced/content/10-howto/30-testing.md +++ b/solara/website/pages/documentation/advanced/content/10-howto/30-testing.md @@ -4,15 +4,30 @@ description: Using solara you can test both the front and back end functionaliti --- # Testing with Solara -# Testing Application Logic + + +## Testing without a Browser We recommend using pytest to test the application logic of your Solara components. To get inspiration for writing tests that cover component logic and their interactions with existing components, refer to the [tests in the Solara repository](https://github.com/widgetti/solara/tree/master/tests). -# Testing with a Browser +## Testing with a Browser + +### Installation + +Solara is using the `pytest-ipywidgets` pytest plugin together with [Playwright for Python](https://playwright.dev/python/) to test your widgets, components or applications using a browser, for both unit as well as integration tests. + +To install `pytest-ipywidgets` and Playwright for Python, run the following commands: +``` +$ pip install "pytest-ipywidgets[solara]" # or "pytest-ipywidgets[all]" if you also want to test with Jupyter Lab, Jupiter Notebook and Voila. +$ playwright install chromium +``` + +### Testing widgets using Solara server -If you have custom components that depend on a connected browser because it is using JavaScript, we recommend using the Solara pytest plugin, which is installed by default when you install Solara. The plugin provides a fixture called `solara_test` that you can use to test your components. Here's an example: +The most convenient way to test a widget, is by including the `solara_test` fixture in your test function arguments. Here's an example: ```python +# file tests/ui/test_widget_button.py import ipywidgets as widgets import playwright.sync_api from IPython.display import display @@ -32,23 +47,16 @@ def test_widget_button_solara(solara_test, page_session: playwright.sync_api.Pag button_sel.click() page_session.locator("text=Tested event").wait_for() ``` +When this fixture is used, we can use the standard IPython display call to add your widget to the page. Using the `page_session` fixture, we can interact with the widget in the browser, +in this case we trigger a button click in the browser and check if the button description changes to "Tested event". -Run this test with pytest: +Run this test with pytest as follows: ```bash pytest tests/ui/test_widget_button.py --headed # remove --headed to run headless ``` -This require playwright to be installed: - -``` -$ pip install playwright pytest-playwright -# $ pip install "solara[pytest]" # if you haven't installed solara already -$ playwright install chromium -``` - -In this example, use the standard IPython display call to add your widget to the page. # Testing in the main Jupyter Environments diff --git a/solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md b/solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md index f2fb8ce9d..256ad6dcb 100644 --- a/solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +++ b/solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md @@ -7,6 +7,17 @@ description: Solara server enables running ipywidgets-based applications as stan The solara server enables running ipywidgets based applications without a real Jupyter kernel, allowing multiple "Virtual kernels" to share the same process for better performance and scalability. +## Installation + +To install the solara server, run: + +```bash +$ pip install "solara-server[starlette]" +$ # pip install solara # to get all solara packages +``` + +See [our installation guide](/documentation/getting_started/installing) for more information. + ## WebSocket in Solara Solara uses a WebSocket to transmit state and updates directly from the server to the browser. This ensures that the state remains centralized on the server, facilitating state transitions server-side and enabling live updates to be pushed directly to the browser. diff --git a/solara/website/pages/documentation/getting_started/content/02-installing.md b/solara/website/pages/documentation/getting_started/content/02-installing.md index 2663548b9..2737beeaa 100644 --- a/solara/website/pages/documentation/getting_started/content/02-installing.md +++ b/solara/website/pages/documentation/getting_started/content/02-installing.md @@ -83,3 +83,52 @@ $ tar zxfv solara-air-gapped.tar.gz # Install all wheels. $ pip install solara-air-gapped/*.whl ``` + +## Solara subpackages + +The `solara` package is a meta package that installs all the necessary dependencies to get started with Solara. By default, we install: + + * [`pip install "solara-ui[all]"`](https://pypi.org/project/solara-ui) + * [`pip install "solara-server[starlette,dev]"`](https://pypi.org/project/solara-ui) - + +Note that the solara (meta) package will pin exact versions of solara-ui and solara-server, which ensures you always get compatible version of the subpackages. +For more flexibility, and control over what you install, you can install the subpackages directly. + + +### The `solara-ui` package + +This package contains only the UI components, hooks and other utilities. This is the only package you need if you want to use Solara in a Jupyter environment. There are optional dependencies giving you +more control over what you want to install: + + * `pip install "solara-ui"` - Only the UI components, hooks and other utilities. + * `pip install "solara-ui[markdown]"` - The above, with support for markdown rendering. + * `pip install "solara-ui[cache]"` - The above, with support for [caching](https://solara.dev/docs/reference/caching) + * `solara-ui[all]` - Installs all optional dependencies. + +### The `solara-server` package + +This will let you run solara applications outside a Jupyter server. See [Understanding Solara Server](https://solara.dev/documentation/advanced/understanding/solara-server) for more details about solara server. + +For deployments, we recommend ``pip install "solara-server[starlette]"` which will install the starlette backend for solara server. For development, you can install the `dev` extra to get the development dependencies that enabled hot reloading. + +The `solara-server` packages supports the following optional dependencies: + + * `pip install "solara-server"` - Only the solara server code with required dependencies, this in general is not a functional server (it needs starlette or flask to run). + * `pip install "solara-server[starlette]"` - The solara server with the starlette backend. + * `pip install "solara-server[flask]"` - The solara server with the starlette backend and development dependencies. + * `pip install "solara-server[dev]"` - The solara server with dependencies for development for enabling hot reloading. + * `pip install "solara-server[all]"` - Installs all optional dependencies. + + + + +### The `pytest-ipywidgets` package + +This package is a plugin for pytest that lets you test ipywidgets with playwright. It is useful for testing your ipywidgets or solara applications in a (headless) browser. +See [Our testing documentation](https://solara.dev/docs/advanced/testing) for more information. + + * `pip install "pytest-ipywidgets"` - Minimal installation for testing ipywidgets. + * `pip install "pytest-ipywidgets[voila]"` - The above, with a compatible version of voila. + * `pip install "pytest-ipywidgets[jupyterlab]"` - The above, with a compatible version of jupyterlab. + * `pip install "pytest-ipywidgets[notebook]"` - The above, with a compatible version of notebook. + * `pip install "pytest-ipywidgets[all]"` - Installs all optional dependencies. diff --git a/tests/unit/reload_test.py b/tests/unit/reload_test.py index 3e57b87fe..1bf874db1 100644 --- a/tests/unit/reload_test.py +++ b/tests/unit/reload_test.py @@ -4,7 +4,7 @@ import pytest import solara.lab -import solara.server.kernel_context +import solara.lifecycle from solara.server import reload from solara.server.app import AppScript @@ -18,8 +18,8 @@ def test_script_reload_component(tmpdir, kernel_context, extra_include_path, no_ target = Path(tmpdir) / "kernel_start.py" shutil.copy(kernel_start_path, target) with extra_include_path(str(tmpdir)): - on_kernel_start_callbacks = solara.server.kernel_context._on_kernel_start_callbacks.copy() - callbacks_start = [k.callback for k in solara.server.kernel_context._on_kernel_start_callbacks] + on_kernel_start_callbacks = solara.lifecycle._on_kernel_start_callbacks.copy() + callbacks_start = [k.callback for k in solara.lifecycle._on_kernel_start_callbacks] if as_module: app = AppScript(f"{target.stem}") else: @@ -27,7 +27,7 @@ def test_script_reload_component(tmpdir, kernel_context, extra_include_path, no_ try: app.run() callback = app.routes[0].module.test_callback # type: ignore - callbacks = [k.callback for k in solara.server.kernel_context._on_kernel_start_callbacks] + callbacks = [k.callback for k in solara.lifecycle._on_kernel_start_callbacks] assert callbacks == [*callbacks_start, callback] prev = callbacks.copy() reload.reloader.reload_event_next.clear() @@ -36,13 +36,13 @@ def test_script_reload_component(tmpdir, kernel_context, extra_include_path, no_ reload.reloader.reload_event_next.wait() app.run() callback = app.routes[0].module.test_callback # type: ignore - callbacks = [k[0] for k in solara.server.kernel_context._on_kernel_start_callbacks] + callbacks = [k[0] for k in solara.lifecycle._on_kernel_start_callbacks] assert callbacks != prev assert callbacks == [*callbacks_start, callback] finally: app.close() - solara.server.kernel_context._on_kernel_start_callbacks.clear() - solara.server.kernel_context._on_kernel_start_callbacks.extend(on_kernel_start_callbacks) + solara.lifecycle._on_kernel_start_callbacks.clear() + solara.lifecycle._on_kernel_start_callbacks.extend(on_kernel_start_callbacks) def test_on_kernel_start_cleanup(kernel_context, no_kernel_context): @@ -50,6 +50,6 @@ def test_callback_cleanup(): pass cleanup = solara.lab.on_kernel_start(test_callback_cleanup) - assert test_callback_cleanup in [k.callback for k in solara.server.kernel_context._on_kernel_start_callbacks] + assert test_callback_cleanup in [k.callback for k in solara.lifecycle._on_kernel_start_callbacks] cleanup() - assert test_callback_cleanup not in [k.callback for k in solara.server.kernel_context._on_kernel_start_callbacks] + assert test_callback_cleanup not in [k.callback for k in solara.lifecycle._on_kernel_start_callbacks]