Skip to content

Commit 6e2ca05

Browse files
committed
Merge branch 'main' into drop_fn_session_param
* main: (26 commits) api!: Merge RendererBase class into Renderer (#1032) chore(render.display): Improve error message (#1020) `express.ui.page_opts(title = ...)` now always generates a header (#1016) api!: `Renderer.auto_output_ui()` drops `id` arg. Make `RendererBase.output_id` a non-namespaced value. (#1030) fix(page_sidebar): Add semicolon to end style declaration (#1027) chore: Remove experimental from app (#1028) chore: Expose `render.renderer.RendererBaseT` and do not require `| None` when defining Renderer types (#1026) bug: Restore legacy renderers while packages transition (#1023) Update deploy test apps to use render.code Update changelog Provide useful message in Express when `input` was not imported (#994) Calculate coordinate mapping after drawing figure (#999) Remove `express.ui.output_*` functions, add `shiny.express.render` (#1018) fix: Do not allow for renderer's to be given to reactive effects (#1017) Truncate the requirements.txt file before deploys (#998) Update changelog Fixes for flake8 (#1012) Pin starlette version below 0.35 (#1009) Remove shiny express warning Cause RecallContextManagers to run when used without `with` (#992) ...
2 parents fbe499d + 96a6279 commit 6e2ca05

File tree

69 files changed

+1374
-873
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1374
-873
lines changed

CHANGELOG.md

+24-4
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
## [UNRELEASED]
1010

11+
### Breaking Changes
12+
13+
* Closed #938: `page_sidebar()` and `page_navbar()` now use `fillable=False` by default. (#990)
14+
15+
### New features
16+
17+
* Added `@render.download` as a replacement for `@session.download`, which is now deprecated. (#977)
18+
19+
* Added `ui.output_code()`, which is currently an alias for `ui.output_text_verbatim()`. (#997)
20+
21+
* Added `@render.code`, which is an alias for `@render.text`, but in Express mode, it displays the result using `ui.output_code()`. (#997)
22+
1123
### Bug fixes
1224

1325
* CLI command `shiny create`... (#965)
1426
* has added a `-d`/`--dir` flag for saving to a specific output directory
1527
* will raise an error if if will overwrite existing files
1628
* prompt users to install `requirements.txt`
29+
1730
* Fixed `js-react` template build error. (#965)
1831

32+
* Fixed #1007: Plot interaction with plotnine provided incorrect values. (#999)
33+
1934
### Developer features
2035

2136
* Output renderers should now be created with the `shiny.render.renderer.Renderer` class. This class should contain either a `.transform(self, value)` method (common) or a `.render(self)` (rare). These two methods should return something can be converted to JSON. In addition, `.default_ui(self, id)` should be implemented by returning `htmltools.Tag`-like content for use within Shiny Express. To make your own output renderer, please inherit from the `Renderer[IT]` class where `IT` is the type (excluding `None`) required to be returned from the App author. (#964)
37+
* Legacy renderers that will be removed in the near future:
38+
* `shiny.render.RenderFunction`
39+
* `shiny.render.RenderFunctionAsync`
40+
* `shiny.render.transformer.OutputRenderer`
41+
* `shiny.render.transformer.OutputRendererSync`
42+
* `shiny.render.transformer.OutputRendererAsync`
2243

23-
* `shiny.render.RenderFunction` and `shiny.render.RenderFunctionAsync` have been removed. They were deprecated in v0.6.0. Instead, please use `shiny.render.renderer.Renderer`. (#964)
24-
25-
* When transforming values within `shiny.render.transformer.output_transformer` transform function, `shiny.render.transformer.resolve_value_fn` is no longer needed as the value function given to the output transformer is now **always** an asynchronous function. `resolve_value_fn(fn)` method has been deprecated. Please change your code from `value = await resolve_value_fn(_fn)` to `value = await _fn()`. (#964)
2644

27-
* `shiny.render.OutputRendererSync` and `shiny.render.OutputRendererAsync` helper classes have been removed in favor of an updated `shiny.render.OutputRenderer` class. Now, the app's output value function will be transformed into an asynchronous function for simplified, consistent execution behavior. If redesigning your code, instead please create a new renderer that inherits from `shiny.render.renderer.Renderer`. (#964)
45+
### Other changes
2846

47+
* Pinned Starlette to version <0.35.0; versions 0.35.0 and 0.35.1 caused problems when deploying on Posit Connect. (#1009
48+
)
2949

3050
## [0.6.1.1] - 2023-12-22
3151

docs/_quartodoc.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ quartodoc:
158158
- ui.output_table
159159
- ui.output_data_frame
160160
- ui.output_text
161+
- ui.output_code
161162
- ui.output_text_verbatim
162163
- ui.output_ui
163164
- render.plot
@@ -176,10 +177,10 @@ quartodoc:
176177
desc: ""
177178
contents:
178179
- render.renderer.Renderer
179-
- render.renderer.RendererBase
180180
- render.renderer.Jsonifiable
181181
- render.renderer.ValueFn
182182
- render.renderer.AsyncValueFn
183+
- render.renderer.RendererT
183184
- title: Reactive programming
184185
desc: ""
185186
contents:

examples/annotation-export/app.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def annotations():
109109
df = df.loc[df["annotation"] != ""]
110110
return df
111111

112-
@session.download(filename="data.csv")
112+
@render.download(filename="data.csv")
113113
def download():
114114
yield annotated_data().to_csv()
115115

examples/cpuinfo/app.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def collect_cpu_samples():
140140
combined_data = combined_data[:, -MAX_SAMPLES:]
141141
cpu_history.set(combined_data)
142142

143-
@reactive.Effect(priority=100)
143+
@reactive.effect(priority=100)
144144
@reactive.event(input.reset)
145145
def reset_history():
146146
cpu_history.set(None)

setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ setup_requires =
3434
install_requires =
3535
typing-extensions>=4.0.1
3636
uvicorn>=0.16.0
37-
starlette>=0.17.1
37+
starlette>=0.17.1,<0.35.0
3838
websockets>=10.0
3939
python-multipart
4040
htmltools>=0.5.1

shiny/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""A package for building reactive web applications."""
22

3-
__version__ = "0.6.1.9000"
3+
__version__ = "0.6.1.9006"
44

55
from ._shinyenv import is_pyodide as _is_pyodide
66

shiny/_utils.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ def _step(fut: Optional["asyncio.Future[None]"] = None):
393393
assert fut.done()
394394
try:
395395
fut.result()
396-
except BaseException as e:
396+
except BaseException as e: # noqa: B036
397397
exc = e
398398

399399
if result_future.cancelled():
@@ -419,7 +419,7 @@ def _step(fut: Optional["asyncio.Future[None]"] = None):
419419
except (KeyboardInterrupt, SystemExit) as e:
420420
result_future.set_exception(e)
421421
raise
422-
except BaseException as e:
422+
except BaseException as e: # noqa: B036
423423
result_future.set_exception(e)
424424
else:
425425
# If we get here, the coro didn't finish. Schedule it for completion.

shiny/api-examples/Renderer/app.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import Literal
3+
from typing import Literal, Optional
44

55
from shiny import App, Inputs, Outputs, Session, ui
66
from shiny.render.renderer import Renderer, ValueFn
@@ -28,15 +28,15 @@ class render_capitalize(Renderer[str]):
2828
Whether to render a placeholder value. (Defaults to `True`)
2929
"""
3030

31-
def default_ui(self, id: str):
31+
def auto_output_ui(self):
3232
"""
3333
Express UI for the renderer
3434
"""
35-
return ui.output_text_verbatim(id, placeholder=self.placeholder)
35+
return ui.output_text_verbatim(self.output_name, placeholder=self.placeholder)
3636

3737
def __init__(
3838
self,
39-
_fn: ValueFn[str | None] | None = None,
39+
_fn: Optional[ValueFn[str]] | None = None,
4040
*,
4141
to_case: Literal["upper", "lower", "ignore"] = "upper",
4242
placeholder: bool = True,
@@ -68,7 +68,7 @@ def __init__(
6868
self.to_case = to_case
6969

7070
async def render(self) -> str | None:
71-
value = await self.value_fn()
71+
value = await self.fn()
7272
if value is None:
7373
# If `None` is returned, then do not render anything.
7474
return None
@@ -94,11 +94,11 @@ class render_upper(Renderer[str]):
9494
Note: This renderer is equivalent to `render_capitalize(to="upper")`.
9595
"""
9696

97-
def default_ui(self, id: str):
97+
def auto_output_ui(self):
9898
"""
9999
Express UI for the renderer
100100
"""
101-
return ui.output_text_verbatim(id, placeholder=True)
101+
return ui.output_text_verbatim(self.output_name, placeholder=True)
102102

103103
async def transform(self, value: str) -> str:
104104
"""

shiny/api-examples/download/app.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import matplotlib.pyplot as plt
88
import numpy as np
99

10-
from shiny import App, Inputs, Outputs, Session, ui
10+
from shiny import App, Inputs, Outputs, Session, render, ui
1111

1212

1313
def make_example(id: str, label: str, title: str, desc: str, extra: Any = None):
@@ -77,7 +77,7 @@ def make_example(id: str, label: str, title: str, desc: str, extra: Any = None):
7777

7878

7979
def server(input: Inputs, output: Outputs, session: Session):
80-
@session.download()
80+
@render.download()
8181
def download1():
8282
"""
8383
This is the simplest case. The implementation simply returns the name of a file.
@@ -88,12 +88,12 @@ def download1():
8888
path = os.path.join(os.path.dirname(__file__), "mtcars.csv")
8989
return path
9090

91-
@session.download(filename="image.png")
91+
@render.download(filename="image.png")
9292
def download2():
9393
"""
9494
Another way to implement a file download is by yielding bytes; either all at
9595
once, like in this case, or by yielding multiple times. When using this
96-
approach, you should pass a filename argument to @session.download, which
96+
approach, you should pass a filename argument to @render.download, which
9797
determines what the browser will name the downloaded file.
9898
"""
9999

@@ -107,7 +107,7 @@ def download2():
107107
plt.savefig(buf, format="png")
108108
yield buf.getvalue()
109109

110-
@session.download(
110+
@render.download(
111111
filename=lambda: f"新型-{date.today().isoformat()}-{np.random.randint(100,999)}.csv"
112112
)
113113
async def download3():
@@ -116,7 +116,8 @@ async def download3():
116116
yield "新,1,2\n"
117117
yield "型,4,5\n"
118118

119-
@session.download(id="download4", filename="failuretest.txt")
119+
@output(id="download4")
120+
@render.download(filename="failuretest.txt")
120121
async def _():
121122
yield "hello"
122123
raise Exception("This error was caused intentionally")

shiny/api-examples/download_button/app.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
import asyncio
2+
import random
23
from datetime import date
34

4-
import numpy as np
5-
6-
from shiny import App, Inputs, Outputs, Session, ui
5+
from shiny import App, Inputs, Outputs, Session, render, ui
76

87
app_ui = ui.page_fluid(
98
ui.download_button("downloadData", "Download"),
109
)
1110

1211

1312
def server(input: Inputs, output: Outputs, session: Session):
14-
@session.download(
15-
filename=lambda: f"新型-{date.today().isoformat()}-{np.random.randint(100,999)}.csv"
13+
@render.download(
14+
filename=lambda: f"新型-{date.today().isoformat()}-{random.randint(100,999)}.csv"
1615
)
1716
async def downloadData():
1817
await asyncio.sleep(0.25)

shiny/api-examples/download_link/app.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
import asyncio
2+
import random
23
from datetime import date
34

4-
import numpy as np
5-
6-
from shiny import App, Inputs, Outputs, Session, ui
5+
from shiny import App, Inputs, Outputs, Session, render, ui
76

87
app_ui = ui.page_fluid(
98
ui.download_link("downloadData", "Download"),
109
)
1110

1211

1312
def server(input: Inputs, output: Outputs, session: Session):
14-
@session.download(
15-
filename=lambda: f"新型-{date.today().isoformat()}-{np.random.randint(100,999)}.csv"
13+
@render.download(
14+
filename=lambda: f"新型-{date.today().isoformat()}-{random.randint(100,999)}.csv"
1615
)
1716
async def downloadData():
1817
await asyncio.sleep(0.25)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import matplotlib.pyplot as plt
2+
import numpy as np
3+
4+
from shiny import reactive, render
5+
from shiny.express import input, ui
6+
7+
ui.input_slider("n", "Number of observations", min=0, max=1000, value=500)
8+
ui.input_action_button("go", "Go!", class_="btn-success")
9+
10+
11+
@render.plot(alt="A histogram")
12+
# Use reactive.event() to invalidate the plot only when the button is pressed
13+
# (not when the slider is changed)
14+
@reactive.event(input.go, ignore_none=False)
15+
def plot():
16+
np.random.seed(19680801)
17+
x = 100 + 15 * np.random.randn(input.n())
18+
fig, ax = plt.subplots()
19+
ax.hist(x, bins=30, density=True)
20+
return fig

shiny/express/__init__.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,23 @@
44
# console.
55
from ..session import Inputs as _Inputs, Outputs as _Outputs, Session as _Session
66
from ..session import _utils as _session_utils
7+
from .. import render
78
from . import ui
89
from ._is_express import is_express_app
910
from ._output import ( # noqa: F401
10-
ui_kwargs,
1111
suspend_display,
1212
output_args, # pyright: ignore[reportUnusedImport]
1313
)
1414
from ._run import wrap_express_app
1515
from .display_decorator import display_body
1616

17+
1718
__all__ = (
19+
"render",
1820
"input",
1921
"output",
2022
"session",
2123
"is_express_app",
22-
"ui_kwargs",
2324
"suspend_display",
2425
"wrap_express_app",
2526
"ui",

0 commit comments

Comments
 (0)