posit-dev / py-shinywidgets

Render ipywidgets inside a PyShiny app
MIT License
41 stars 2 forks source link

Support for pyvis #63

Open SamEdwardes opened 1 year ago

SamEdwardes commented 1 year ago

Description

Requesting support to be able to use the pyvis library with Shiny for Python https://pyvis.readthedocs.io/en/latest/index.html.

Here is an example where someone was able to register pyvis with ipywidgets https://github.com/WestHealth/pyvis/issues/93.

obkhan commented 1 year ago

+1 for requesting support of pyvis

cpsievert commented 1 year ago

Here is an example where someone was able to register pyvis with ipywidgets https://github.com/WestHealth/pyvis/issues/93.

It's important to note that, in that example, pyvis' Network() class isn't being rendered as an ipywidget. It's just displaying some non-ipywidgets HTML/JS, which means you can't programmatically read or modify traits of a Network() instance in the usual ipywidgets sense (i.e., modifying traits server-side will update the client-side state).

That being said, there's nothing preventing you from doing basically the same thing as that example with vanilla shiny (no shinywidgets necessary).

import os

from shiny import *
import networkx as nx
from pyvis.network import Network

# set up a static_assets folder for holding the Network()'s html file
DIR = os.path.dirname(os.path.abspath(__file__))
WWW = os.path.join(DIR, "www")

PYVIS_OUTPUT_ID = "pyvis"

ui_app = ui.page_fluid(
    ui.output_ui(PYVIS_OUTPUT_ID),
)

def server(input: Inputs, output: Outputs, session: Session):
    @output(id=PYVIS_OUTPUT_ID)
    @render.ui
    def _():
        G = nx.Graph()
        G.add_nodes_from([1, 2, 3])
        G.add_edges_from([[1, 2], [2, 3], [3, 1]])

        net = Network()
        net.from_nx(G)
        net.toggle_drag_nodes(False)

        net.generate_html(local=False)
        f = os.path.join(WWW, PYVIS_OUTPUT_ID + ".html")
        with open(f, "w") as f:
            f.write(net.html)

        return ui.tags.iframe(
            src=PYVIS_OUTPUT_ID + ".html",
            style="height:600px;width:100%;",
            scrolling="no",
            seamless="seamless",
            frameBorder="0",
        )

app = App(ui=ui_app, server=server, static_assets=WWW)
cpsievert commented 1 year ago

By the way, until pyvis gains support for the ipywidgets protocol, there's nothing really for shinywidgets to do, so I'll be adding a "wontfix" tag to reinforce that point.

It's also worth noting pyvis isn't the only "widget" library that's in this situation (see for example, https://github.com/rstudio/py-shinywidgets/issues/54)

SamEdwardes commented 1 year ago

Hi @cpsievert thank you for explaining. The iframe suggestion looks like a good solution. @obkhan maybe you should create an issue in the pyvis repo to propose the idea of pyvis support for jupyter widgets.