Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
"editor.formatOnSave": true,
"editor.tabSize": 4,
},
"python.analysis.diagnosticSeverityOverrides": {
"reportImportCycles": "none",
"reportUnusedFunction": "none",
"reportPrivateUsage": "none",
"reportUnnecessaryIsInstance": "none"
},
"editor.rulers": [
88
],
Expand Down
2 changes: 1 addition & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ History
0.0.0.9000 (2021-08-10)
------------------

* First release on PyPI.
* Initial version
79 changes: 43 additions & 36 deletions examples/bind_event/app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import asyncio
import shiny.ui_toolkit as st
from shiny import *
from htmltools import tags

ui = page_fluid(
ui = st.page_fluid(
tags.p(
"""
The first time you click the button, you should see a 1 appear below the button,
Expand All @@ -9,68 +12,72 @@
print the number of clicks in the console twice.
"""
),
navs_tab_card(
nav(
st.navs_tab_card(
st.nav(
"Sync",
input_action_button("btn", "Click me"),
output_ui("foo"),
st.input_action_button("btn", "Click me"),
st.output_ui("btn_value"),
),
nav(
st.nav(
"Async",
input_action_button("btn_async", "Click me"),
output_ui("foo_async"),
st.input_action_button("btn_async", "Click me"),
st.output_ui("btn_async_value"),
),
),
)


def server(session: ShinySession):
def server(input: Inputs, output: Outputs, session: Session):

# i.e., observeEvent(once=False)
@observe()
@event(lambda: session.input["btn"])
@reactive.effect()
@event(input.btn)
def _():
print("@observe() event: ", str(session.input["btn"]))
print("@effect() event: ", str(input.btn()))

# i.e., eventReactive()
@reactive()
@event(lambda: session.input["btn"])
@reactive.calc()
@event(input.btn)
def btn() -> int:
return session.input["btn"]
return input.btn()

@observe()
@reactive.effect()
def _():
print("@reactive() event: ", str(btn()))
print("@calc() event: ", str(btn()))

@session.output("foo")
@output()
@render_ui()
@event(lambda: session.input["btn"])
def _():
return session.input["btn"]
@event(input.btn)
def btn_value():
return str(input.btn())

# -----------------------------------------------------------------------------
# Async
# -----------------------------------------------------------------------------
@observe_async()
@event(lambda: session.input["btn_async"])
@reactive.effect_async()
@event(input.btn_async)
async def _():
print("@observe_async() event: ", str(session.input["btn_async"]))
await asyncio.sleep(0)
print("@effect_async() event: ", str(input.btn_async()))

@reactive_async()
@event(lambda: session.input["btn_async"])
async def btn_async() -> int:
return session.input["btn_async"]
@reactive.calc_async()
@event(input.btn_async)
async def btn_async_r() -> int:
await asyncio.sleep(0)
return input.btn_async()

@observe_async()
@reactive.effect_async()
async def _():
val = await btn_async()
print("@reactive_async() event: ", str(val))
val = await btn_async_r()
print("@calc_async() event: ", str(val))

@session.output("foo_async")
@output()
@render_ui()
@event(lambda: session.input["btn_async"])
async def _():
return session.input["btn_async"]
@event(btn_async_r)
async def btn_async_value():
val = await btn_async_r()
print("== " + str(val))
return str(val)


ShinyApp(ui, server).run()
app = App(ui, server, debug=True)
52 changes: 25 additions & 27 deletions examples/download/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,74 +4,77 @@
# Then point web browser to:
# http://localhost:8000/
import asyncio
from datetime import date
import os
import io
import matplotlib.pyplot as plt
import numpy as np
from datetime import date
from typing import Any

import shiny.ui_toolkit as st
from shiny import *
from htmltools import *

import matplotlib.pyplot as plt
import numpy as np


def make_example(id: str, label: str, title: str, desc: str, extra: Any = None):
return column(
3,
tags.div(
return st.column(
4,
div(
class_="card mb-4",
children=[
tags.div(title, class_="card-header"),
tags.div(
div(title, class_="card-header"),
div(
class_="card-body",
children=[
tags.p(desc, class_="card-text text-muted"),
p(desc, class_="card-text text-muted"),
extra,
download_button(id, label, class_="btn-primary"),
st.download_button(id, label, class_="btn-primary"),
],
),
],
),
)


ui = page_fluid(
tags.h1("Download examples"),
row(
ui = st.page_fluid(
st.row(
make_example(
"download1",
label="Download CSV",
title="Simple case",
desc="Downloads a pre-existing file, using its existing name on disk.",
),
),
row(
st.row(
make_example(
"download2",
label="Download plot",
title="Dynamic data generation",
desc="Downloads a PNG that's generated on the fly.",
extra=[
input_text("title", "Plot title", "Random scatter plot"),
input_slider("num_points", "Number of data points", 1, 100, 50),
st.input_text("title", "Plot title", "Random scatter plot"),
st.input_slider("num_points", "Number of data points", 1, 100, 50),
],
),
),
row(
st.row(
make_example(
"download3",
"Download",
"Dynamic filename",
"Demonstrates that filenames can be generated on the fly (and use Unicode characters!).",
),
),
row(
st.row(
make_example(
"download4",
"Download",
"Failed downloads",
"Throws an error in the download handler, download should not succeed.",
),
),
row(
st.row(
make_example(
"download5",
"Download",
Expand All @@ -82,7 +85,7 @@ def make_example(id: str, label: str, title: str, desc: str, extra: Any = None):
)


def server(session: ShinySession):
def server(input: Inputs, output: Outputs, session: Session):
@session.download()
def download1():
"""
Expand All @@ -107,7 +110,7 @@ def download2():
y = np.random.uniform(size=session.input["num_points"])
plt.figure()
plt.scatter(x, y)
plt.title(session.input["title"])
plt.title(input.title())
with io.BytesIO() as buf:
plt.savefig(buf, format="png")
yield buf.getvalue()
Expand All @@ -127,9 +130,4 @@ async def _():
raise Exception("This error was caused intentionally")


app = ShinyApp(ui, server)

if __name__ == "__main__":
app.run()
# Alternately, to listen on a TCP port:
# app.run(conn_type = "tcp")
app = App(ui, server)
60 changes: 30 additions & 30 deletions examples/dynamic_ui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,66 +4,66 @@
# Then point web browser to:
# http://localhost:8000/

import shiny.ui_toolkit as st
from shiny import *
from htmltools import *

# For plot rendering
import numpy as np
import matplotlib.pyplot as plt

ui = page_fluid(
layout_sidebar(
panel_sidebar(
h2("Dynamic UI"),
output_ui("ui"),
input_action_button("btn", "Trigger insert/remove ui"),
ui = st.page_fluid(
st.layout_sidebar(
st.panel_sidebar(
st.h2("Dynamic UI"),
st.output_ui("ui"),
st.input_action_button("btn", "Trigger insert/remove ui"),
),
panel_main(
output_text_verbatim("txt"),
output_plot("plot"),
st.panel_main(
st.output_text_verbatim("txt"),
st.output_plot("plot"),
),
),
)


def server(session: ShinySession):
@reactive()
def server(input: Inputs, output: Outputs, session: Session):
@reactive.calc()
def r():
if session.input["n"] is None:
if input.n() is None:
return
return session.input["n"] * 2
return input.n() * 2

@session.output("txt")
async def _():
@output()
@render_text()
async def txt():
val = r()
return f"n*2 is {val}, session id is {get_current_session().id}"
return f"n*2 is {val}, session id is {session.id}"

@session.output("plot")
@output()
@render_plot(alt="A histogram")
def _():
def plot():
np.random.seed(19680801)
x = 100 + 15 * np.random.randn(437)

fig, ax = plt.subplots()
ax.hist(x, session.input["n"], density=True)
ax.hist(x, input.n(), density=True)
return fig

@session.output("ui")
@output()
@render_ui()
def _():
return input_slider("This slider is rendered via @render_ui()", "N", 0, 100, 20)
def ui():
return st.input_slider(
"This slider is rendered via @render_ui()", "N", 0, 100, 20
)

@observe()
@reactive.effect()
def _():
btn = session.input["btn"]
btn = input.btn()
if btn % 2 == 1:
ui_insert(tags.p("Thanks for clicking!", id="thanks"), "body")
elif btn > 0:
ui_remove("#thanks")


app = ShinyApp(ui, server)

if __name__ == "__main__":
app.run()
# Alternately, to listen on a TCP port:
# app.run(conn_type = "tcp")
app = App(ui, server)
Loading