Skip to content

Commit be3d618

Browse files
committed
Better sizing logic, e2e tests
1 parent 792c7d3 commit be3d618

File tree

6 files changed

+388
-90
lines changed

6 files changed

+388
-90
lines changed

shiny/render/_render.py

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from typing import (
1616
TYPE_CHECKING,
1717
Any,
18+
Callable,
19+
Literal,
1820
Optional,
1921
ParamSpec,
2022
Protocol,
@@ -34,7 +36,12 @@
3436
from .. import ui as _ui
3537
from .._namespaces import ResolvedId
3638
from ..types import ImgData
37-
from ._try_render_plot import try_render_matplotlib, try_render_pil, try_render_plotnine
39+
from ._try_render_plot import (
40+
PlotSizeInfo,
41+
try_render_matplotlib,
42+
try_render_pil,
43+
try_render_plotnine,
44+
)
3845
from .transformer import (
3946
TransformerMetadata,
4047
ValueFn,
@@ -139,9 +146,6 @@ async def PlotTransformer(
139146
height: Optional[float] = None,
140147
**kwargs: object,
141148
) -> ImgData | None:
142-
import matplotlib as mpl
143-
import matplotlib.pyplot as plt
144-
145149
is_userfn_async = is_async_callable(_fn)
146150
name = _meta.name
147151
session = _meta.session
@@ -154,18 +158,25 @@ async def PlotTransformer(
154158
pixelratio: float = typing.cast(
155159
float, inputs[ResolvedId(".clientdata_pixelratio")]()
156160
)
157-
if width is None:
158-
width = typing.cast(
159-
float, inputs[ResolvedId(f".clientdata_output_{name}_width")]()
160-
)
161-
if height is None:
162-
height = typing.cast(
163-
float, inputs[ResolvedId(f".clientdata_output_{name}_height")]()
164-
)
165161

166-
mpl.rcParams["figure.dpi"] = ppi * pixelratio
167-
mpl.rcParams["figure.figsize"] = [width / ppi, height / ppi]
168-
plt.close() # type: ignore
162+
# Do NOT call this unless you actually are going to respect the container dimension
163+
# you're asking for. It takes a reactive dependency. If the client hasn't reported
164+
# the requested dimension, you'll get a SilentException.
165+
def container_size(dimension: Literal["width", "height"]) -> Callable[[], float]:
166+
def container_size_fn() -> float:
167+
result = inputs[ResolvedId(f".clientdata_output_{name}_{dimension}")]()
168+
return typing.cast(float, result)
169+
170+
return container_size_fn
171+
172+
plot_size_info = PlotSizeInfo(
173+
container_size_px_fn=(
174+
container_size("width"),
175+
container_size("height"),
176+
),
177+
user_specified_size_px=(width, height),
178+
pixelratio=pixelratio,
179+
)
169180

170181
# Call the user function to get the plot object.
171182
x = await resolve_value_fn(_fn)
@@ -190,11 +201,8 @@ async def PlotTransformer(
190201
if "plotnine" in sys.modules:
191202
ok, result = try_render_plotnine(
192203
x,
193-
width,
194-
height,
195-
pixelratio,
196-
ppi,
197-
alt,
204+
plot_size_info=plot_size_info,
205+
alt=alt,
198206
**kwargs,
199207
)
200208
if ok:
@@ -203,10 +211,7 @@ async def PlotTransformer(
203211
if "matplotlib" in sys.modules:
204212
ok, result = try_render_matplotlib(
205213
x,
206-
width,
207-
height,
208-
pixelratio=pixelratio,
209-
ppi=ppi,
214+
plot_size_info=plot_size_info,
210215
allow_global=not is_userfn_async,
211216
alt=alt,
212217
**kwargs,
@@ -217,11 +222,9 @@ async def PlotTransformer(
217222
if "PIL" in sys.modules:
218223
ok, result = try_render_pil(
219224
x,
220-
width,
221-
height,
222-
pixelratio,
223-
ppi,
224-
alt,
225+
plot_size_info=plot_size_info,
226+
ppi=ppi,
227+
alt=alt,
225228
**kwargs,
226229
)
227230
if ok:

0 commit comments

Comments
 (0)