Skip to content

Commit 25f81f3

Browse files
committed
Move context manager from AsyncValueFn's call to Outputs's call
1 parent 45afeea commit 25f81f3

File tree

3 files changed

+24
-24
lines changed

3 files changed

+24
-24
lines changed

shiny/render/_express.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def __call__(self, fn: ValueFn[None]) -> Self:
6767
if fn is None: # pyright: ignore[reportUnnecessaryComparison]
6868
raise TypeError("@render.express requires a function when called")
6969

70-
async_fn = AsyncValueFn(fn, self)
70+
async_fn = AsyncValueFn(fn)
7171
if async_fn.is_async():
7272
raise TypeError(
7373
"@render.express does not support async functions. Use @render.ui instead."

shiny/render/renderer/_renderer.py

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
from contextlib import contextmanager
43
from typing import (
54
TYPE_CHECKING,
65
Any,
@@ -163,7 +162,7 @@ def __call__(self, _fn: ValueFn[IT]) -> Self:
163162
raise TypeError("Value function must be callable")
164163

165164
# Set value function with extra meta information
166-
self.fn = AsyncValueFn(_fn, self)
165+
self.fn = AsyncValueFn(_fn)
167166

168167
# Copy over function name as it is consistent with how Session and Output
169168
# retrieve function names
@@ -348,7 +347,6 @@ class AsyncValueFn(Generic[IT]):
348347
def __init__(
349348
self,
350349
fn: Callable[[], IT | None] | Callable[[], Awaitable[IT | None]],
351-
renderer: Renderer[Any],
352350
):
353351
if isinstance(fn, AsyncValueFn):
354352
raise TypeError(
@@ -357,14 +355,12 @@ def __init__(
357355
self._is_async = is_async_callable(fn)
358356
self._fn = wrap_async(fn)
359357
self._orig_fn = fn
360-
self._renderer = renderer
361358

362359
async def __call__(self) -> IT | None:
363360
"""
364361
Call the asynchronous function.
365362
"""
366-
with self._current_renderer():
367-
return await self._fn()
363+
return await self._fn()
368364

369365
def is_async(self) -> bool:
370366
"""
@@ -405,19 +401,3 @@ def get_sync_fn(self) -> Callable[[], IT | None]:
405401
)
406402
sync_fn = cast(Callable[[], IT], self._orig_fn)
407403
return sync_fn
408-
409-
@contextmanager
410-
def _current_renderer(self):
411-
from ...session import get_current_session
412-
413-
session = get_current_session()
414-
if session is None:
415-
yield
416-
return
417-
418-
old_renderer = session._current_renderer
419-
try:
420-
session._current_renderer = self._renderer
421-
yield
422-
finally:
423-
session._current_renderer = old_renderer

shiny/session/_session.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
AsyncIterable,
2323
Awaitable,
2424
Callable,
25+
Generator,
2526
Iterable,
2627
Literal,
2728
Optional,
@@ -550,6 +551,9 @@ def __init__(
550551

551552
self.user: str | None = None
552553
self.groups: list[str] | None = None
554+
555+
self._current_renderer = None
556+
553557
credentials_json: str = ""
554558
if "shiny-server-credentials" in self.http_conn.headers:
555559
credentials_json = self.http_conn.headers["shiny-server-credentials"]
@@ -1817,8 +1821,13 @@ async def output_obs():
18171821
)
18181822

18191823
try:
1820-
value = await renderer.render()
1824+
# Temporarily set the renderer so `clientdata.output_*()` can access it without an `id`
1825+
with self._session_renderer(session, renderer):
1826+
# Call the app's renderer function
1827+
value = await renderer.render()
1828+
18211829
session._outbound_message_queues.set_value(output_name, value)
1830+
18221831
except SilentOperationInProgressException:
18231832
session._send_progress(
18241833
"binding", {"id": output_name, "persistent": True}
@@ -1894,3 +1903,14 @@ def _should_suspend(self, name: str) -> bool:
18941903
return self._outputs[name].suspend_when_hidden and self._session._is_hidden(
18951904
name
18961905
)
1906+
1907+
@contextlib.contextmanager
1908+
def _session_renderer(
1909+
self, session: Session, renderer: Renderer[Any]
1910+
) -> Generator[None, None, None]:
1911+
old_renderer = session._current_renderer
1912+
try:
1913+
session._current_renderer = renderer
1914+
yield
1915+
finally:
1916+
session._current_renderer = old_renderer

0 commit comments

Comments
 (0)