Skip to content

Commit c08d91a

Browse files
authored
Add session.clientdata; allow access to input names via dir() (#1832)
1 parent 05dc9f5 commit c08d91a

File tree

9 files changed

+421
-3
lines changed

9 files changed

+421
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
* `shiny create` includes new and improved `ui.Chat()` template options. Most of these templates leverage the new [`{chatlas}` package](https://posit-dev.github.io/chatlas/), our opinionated approach to interfacing with various LLM. (#1806)
1919

20+
* Client data values (e.g., url info, output sizes/styles, etc.) can now be accessed in the server-side Python code via `session.clientdata`. For example, `session.clientdata.url_search()` reactively reads the URL search parameters. (#1832)
21+
22+
* Available `input` ids can now be listed via `dir(input)`. This also works on the new `session.clientdata` object. (#1832)
23+
2024
### Bug fixes
2125

2226
* `ui.Chat()` now correctly handles new `ollama.chat()` return value introduced in `ollama` v0.4. (#1787)

docs/_quartodoc-core.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,19 +233,21 @@ quartodoc:
233233
path: Session
234234
summary:
235235
name: "Session"
236-
desc: ""
236+
desc: "Tools for managing user sessions and accessing session-related information."
237237
flatten: true
238238
contents:
239239
- session.get_current_session
240240
- session.require_active_session
241241
- session.session_context
242242
- reactive.get_current_context
243+
- session.ClientData
243244
- session.Session.send_custom_message
244245
- session.Session.send_input_message
245246
- session.Session.on_flush
246247
- session.Session.on_flushed
247248
- session.Session.on_ended
248249
- session.Session.dynamic_route
250+
- session.Session.close
249251
- input_handler.input_handlers
250252
- kind: page
251253
path: Renderer

docs/_quartodoc-express.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ quartodoc:
168168
- express.ui.panel_conditional
169169
- express.ui.insert_ui
170170
- express.ui.remove_ui
171+
- title: User Session
172+
desc: Tools for managing user sessions and accessing session-related information.
173+
contents:
174+
- session.Session
175+
- title: Client Data
176+
desc: Access (client-side) information about the user session (e.g., URL, output info, etc).
177+
contents:
178+
- session.ClientData
171179
- title: UI as HTML
172180
desc: Tools for creating HTML/CSS/JS
173181
contents:
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import textwrap
2+
3+
# pyright: reportUnknownMemberType=false, reportUnknownVariableType=false
4+
import matplotlib.pyplot as plt
5+
import numpy as np
6+
7+
from shiny import App, Inputs, Outputs, Session, render, ui
8+
9+
app_ui = ui.page_sidebar(
10+
ui.sidebar(
11+
ui.input_slider("obs", "Number of observations:", min=0, max=1000, value=500),
12+
open="closed",
13+
),
14+
ui.markdown(
15+
"""
16+
#### `session.clientdata` values
17+
18+
The following methods are available from the `session.clientdata` object and allow you
19+
to reactively read the client data values from the browser.
20+
"""
21+
),
22+
ui.output_text_verbatim("clientdatatext"),
23+
ui.output_plot("myplot"),
24+
)
25+
26+
27+
def server(input: Inputs, output: Outputs, session: Session):
28+
29+
@render.code
30+
def clientdatatext():
31+
return textwrap.dedent(
32+
f"""
33+
.url_hash() -> {session.clientdata.url_hash()}
34+
.url_hash_initial() -> {session.clientdata.url_hash_initial()}
35+
.url_hostname() -> {session.clientdata.url_hostname()}
36+
.url_pathname() -> {session.clientdata.url_pathname()}
37+
.url_port() -> {session.clientdata.url_port()}
38+
.url_protocol() -> {session.clientdata.url_protocol()}
39+
.url_search() -> {session.clientdata.url_search()}
40+
.pixelratio() -> {session.clientdata.pixelratio()}
41+
42+
.output_height("myplot") -> {session.clientdata.output_height("myplot")}
43+
.output_width("myplot") -> {session.clientdata.output_width("myplot")}
44+
.output_hidden("myplot") -> {session.clientdata.output_hidden("myplot")}
45+
.output_bg_color("myplot") -> {session.clientdata.output_bg_color("myplot")}
46+
.output_fg_color("myplot") -> {session.clientdata.output_fg_color("myplot")}
47+
.output_accent_color("myplot") -> {session.clientdata.output_accent_color("myplot")}
48+
.output_font("myplot") -> {session.clientdata.output_font("myplot")}
49+
50+
"""
51+
)
52+
53+
@render.plot
54+
def myplot():
55+
plt.figure()
56+
plt.hist(np.random.normal(size=input.obs())) # type: ignore
57+
plt.title("This is myplot")
58+
59+
60+
app = App(app_ui, server)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# pyright: reportUnknownMemberType=false, reportUnknownVariableType=false
2+
import matplotlib.pyplot as plt
3+
import numpy as np
4+
5+
from shiny.express import input, render, session, ui
6+
7+
with ui.sidebar(open="closed"):
8+
ui.input_slider("obs", "Number of observations:", min=0, max=1000, value=500)
9+
10+
ui.markdown(
11+
"""
12+
#### `session.clientdata` values
13+
14+
The following methods are available from the `session.clientdata` object and allow you
15+
to reactively read the client data values from the browser.
16+
"""
17+
)
18+
19+
20+
@render.code
21+
def clientdatatext():
22+
return f"""
23+
.url_hash() -> {session.clientdata.url_hash()}
24+
.url_hash_initial() -> {session.clientdata.url_hash_initial()}
25+
.url_hostname() -> {session.clientdata.url_hostname()}
26+
.url_pathname() -> {session.clientdata.url_pathname()}
27+
.url_port() -> {session.clientdata.url_port()}
28+
.url_protocol() -> {session.clientdata.url_protocol()}
29+
.url_search() -> {session.clientdata.url_search()}
30+
.pixelratio() -> {session.clientdata.pixelratio()}
31+
32+
.output_height("myplot") -> {session.clientdata.output_height("myplot")}
33+
.output_width("myplot") -> {session.clientdata.output_width("myplot")}
34+
.output_hidden("myplot") -> {session.clientdata.output_hidden("myplot")}
35+
.output_bg_color("myplot") -> {session.clientdata.output_bg_color("myplot")}
36+
.output_fg_color("myplot") -> {session.clientdata.output_fg_color("myplot")}
37+
.output_accent_color("myplot") -> {session.clientdata.output_accent_color("myplot")}
38+
.output_font("myplot") -> {session.clientdata.output_font("myplot")}
39+
"""
40+
41+
42+
@render.plot
43+
def myplot():
44+
plt.figure()
45+
plt.hist(np.random.normal(size=input.obs())) # type: ignore
46+
plt.title("This is myplot")

shiny/session/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Tools for working within a (user) session context.
33
"""
44

5-
from ._session import Session, Inputs, Outputs
5+
from ._session import ClientData, Inputs, Outputs, Session
66
from ._utils import ( # noqa: F401
77
get_current_session,
88
session_context as session_context,
@@ -13,6 +13,7 @@
1313
"Session",
1414
"Inputs",
1515
"Outputs",
16+
"ClientData",
1617
"get_current_session",
1718
"require_active_session",
1819
)

0 commit comments

Comments
 (0)