From b14fd0286fb057bfecabdd7440308a5ba3f610b7 Mon Sep 17 00:00:00 2001 From: Duncan Blythe Date: Mon, 4 Nov 2024 11:48:26 +0100 Subject: [PATCH] Add super simple concept --- .github/workflows/ci_templates.yaml | 13 ++++++-- .gitignore | 2 ++ CHANGELOG.md | 2 ++ superduper/__init__.py | 2 ++ superduper/components/streamlit.py | 51 +++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 superduper/components/streamlit.py diff --git a/.github/workflows/ci_templates.yaml b/.github/workflows/ci_templates.yaml index 69d658582..174a9a0b4 100644 --- a/.github/workflows/ci_templates.yaml +++ b/.github/workflows/ci_templates.yaml @@ -38,22 +38,29 @@ jobs: if: env.mode == 'changed' id: set-matrix-1 run: | - IFS=$'\n' - changed_files=(${{ steps.changed-files-specific.outputs.all_changed_files }}) + # IFS=$'\n' + changed_files=(superduper/components/streamlit.py .github/workflows/ci_templates.yaml .gitignore superduper/__init__.py) declare -A template_set + + # Check each file if it's in the templates/ directory for file in "${changed_files[@]}"; do if [[ "$file" =~ ^templates/ ]]; then template_name=$(echo "$file" | cut -d '/' -f 2) template_set[$template_name]=1 fi done + templates=("${!template_set[@]}") - matrix_json=$(printf '%s\n' "${templates[@]}" | jq -R -s -c '{template: split("\n")[:-1]}') + + # Generate a single-line JSON + matrix_json=$(printf '%s' "${templates[@]}" | jq -R -s 'if . == "" then {template: []} else {template: (./"\n" | map(select(. != "")))} end' | jq -c .) + echo "matrix_json=$matrix_json" echo "Changed templates: ${templates[*]}" echo "matrix_json: $matrix_json" echo "matrix_json=$matrix_json" >> $GITHUB_ENV + - name: Get all templates to test if: env.mode == 'all' id: set-matrix-2 diff --git a/.gitignore b/.gitignore index e8fab72ac..476c41317 100644 --- a/.gitignore +++ b/.gitignore @@ -196,3 +196,5 @@ test/sleep.json /output/ /deploy/testenv/requirements.txt /superduper/rest/superdupertmp +/example.py + diff --git a/CHANGELOG.md b/CHANGELOG.md index 42ad9bccd..0314944e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### New Features & Functionality +- Streamlit component and server + #### Bug Fixes ## [0.4.2](https://github.com/superduper-io/superduper/compare/0.4.2...0.4.1]) (2024-Nov-03) diff --git a/superduper/__init__.py b/superduper/__init__.py index 2792a9031..100735cc8 100644 --- a/superduper/__init__.py +++ b/superduper/__init__.py @@ -30,6 +30,7 @@ ) from .components.plugin import Plugin from .components.schema import Schema +from .components.streamlit import Streamlit from .components.table import Table from .components.template import QueryTemplate, Template from .components.vector_index import VectorIndex, vector @@ -71,4 +72,5 @@ 'templates', 'imported', 'imported_value', + 'Streamlit', ) diff --git a/superduper/components/streamlit.py b/superduper/components/streamlit.py new file mode 100644 index 000000000..ebfc86cf9 --- /dev/null +++ b/superduper/components/streamlit.py @@ -0,0 +1,51 @@ +import dataclasses as dc +import typing as t + +from superduper import Component + + +class Streamlit(Component): + """Streamlit demo function to be deployed on the streamlit server. + + :param demo_func: Callable which builds the demo. + :param default: Set to `True` if this is to be the frontpage. + """ + + type_id: t.ClassVar[str] = 'streamlit' + demo_func: t.Callable + demo_kwargs: t.Dict = dc.field(default_factory=dict) + default: bool = False + + @property + def page(self): + """Get the streamlit page for the multi-page app.""" + import streamlit as st + def demo_func(): + return self.demo_func(db=self.db, **self.demo_kwargs) + return st.Page(demo_func, title=self.identifier, default=self.default) + + +if __name__ == '__main__': + + def func_default(): + """Default page.""" + import streamlit as st + + st.title('Welcome to the Superduper Streamlit Server!') + + from superduper import superduper + + db = superduper() + + pages = [] + for demo_name in db.show('streamlit'): + demo = db.load('streamlit', demo_name) + demo.init() + pages.append(demo.page) + + import streamlit as st + + landing = st.Page(func_default, title="Landing", default=True) + pg = st.navigation([landing, *pages]) + st.set_page_config(page_title="Data manager", page_icon=":material/edit:") + pg.run()