Skip to content

Commit

Permalink
api!: Merge RendererBase class into Renderer (#1032)
Browse files Browse the repository at this point in the history
  • Loading branch information
schloerke authored Jan 19, 2024
1 parent f723c2b commit 96a6279
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 245 deletions.
2 changes: 1 addition & 1 deletion docs/_quartodoc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,10 @@ quartodoc:
desc: ""
contents:
- render.renderer.Renderer
- render.renderer.RendererBase
- render.renderer.Jsonifiable
- render.renderer.ValueFn
- render.renderer.AsyncValueFn
- render.renderer.RendererT
- title: Reactive programming
desc: ""
contents:
Expand Down
2 changes: 1 addition & 1 deletion shiny/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""A package for building reactive web applications."""

__version__ = "0.6.1.9005"
__version__ = "0.6.1.9006"

from ._shinyenv import is_pyodide as _is_pyodide

Expand Down
25 changes: 11 additions & 14 deletions shiny/express/_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,20 @@
import contextlib
import sys
from contextlib import AbstractContextManager
from typing import Callable, Generator, TypeVar, overload
from typing import Callable, Generator, TypeVar, cast, overload

from .. import ui
from .._typing_extensions import ParamSpec
from ..render.renderer import RendererBase, RendererBaseT
from ..render.renderer import Renderer, RendererT

__all__ = ("suspend_display",)

P = ParamSpec("P")
R = TypeVar("R")
CallableT = TypeVar("CallableT", bound=Callable[..., object])


# TODO-barret-future; quartodoc entry?
def output_args(
**kwargs: object,
) -> Callable[[RendererBaseT], RendererBaseT]:
) -> Callable[[RendererT], RendererT]:
"""
Sets default UI arguments for a Shiny rendering function.
Expand All @@ -41,20 +38,20 @@ def output_args(
A decorator that sets the default UI arguments for a Shiny rendering function.
"""

def wrapper(renderer: RendererBaseT) -> RendererBaseT:
def wrapper(renderer: RendererT) -> RendererT:
renderer._auto_output_ui_kwargs = kwargs
return renderer

return wrapper


@overload
def suspend_display(fn: CallableT) -> CallableT:
def suspend_display(fn: RendererT) -> RendererT:
...


@overload
def suspend_display(fn: RendererBaseT) -> RendererBaseT:
def suspend_display(fn: CallableT) -> CallableT:
...


Expand All @@ -64,8 +61,8 @@ def suspend_display() -> AbstractContextManager[None]:


def suspend_display(
fn: Callable[P, R] | RendererBaseT | None = None
) -> Callable[P, R] | RendererBaseT | AbstractContextManager[None]:
fn: RendererT | CallableT | None = None,
) -> RendererT | CallableT | AbstractContextManager[None]:
"""Suppresses the display of UI elements in various ways.
If used as a context manager (`with suspend_display():`), it suppresses the display
Expand Down Expand Up @@ -99,12 +96,12 @@ def suspend_display(
if fn is None:
return suspend_display_ctxmgr()

# Special case for RendererBase; when we decorate those, we just mean "don't
# Special case for Renderer; when we decorate those, we just mean "don't
# display yourself"
if isinstance(fn, RendererBase):
if isinstance(fn, Renderer):
# By setting the class value, the `self` arg will be auto added.
fn.auto_output_ui = null_ui
return fn
return cast(RendererT, fn)

return suspend_display_ctxmgr()(fn)

Expand Down
8 changes: 4 additions & 4 deletions shiny/reactive/_reactives.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,9 +480,9 @@ def __init__(
self.__name__ = fn.__name__
self.__doc__ = fn.__doc__

from ..render.renderer import RendererBase
from ..render.renderer import Renderer

if isinstance(fn, RendererBase):
if isinstance(fn, Renderer):
raise TypeError(
"`@reactive.effect` can not be combined with `@render.xx`.\n"
+ "Please remove your call of `@reactive.effect`."
Expand Down Expand Up @@ -819,9 +819,9 @@ def decorator(user_fn: Callable[[], T]) -> Callable[[], T]:

# This is here instead of at the top of the .py file in order to avoid a
# circular dependency.
from ..render.renderer import RendererBase
from ..render.renderer import Renderer

if isinstance(user_fn, RendererBase):
if isinstance(user_fn, Renderer):
# At some point in the future, we may allow this condition, if we find an
# use case. For now we'll disallow it, for simplicity.
raise TypeError(
Expand Down
66 changes: 16 additions & 50 deletions shiny/render/_deprecated.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Generic

from .transformer._transformer import (
IT,
OT,
OutputRendererAsync,
OutputRendererSync,
TransformerMetadata,
ValueFn,
ValueFnAsync,
ValueFnSync,
empty_params,
)
from .._deprecated import ShinyDeprecationWarning
from .transformer._transformer import IT, OT, ValueFnAsync, ValueFnSync

# ======================================================================================
# Deprecated classes
Expand All @@ -24,56 +14,32 @@
# the .__call__ method is invoked, it calls the app-supplied function (which returns an
# `IT`), then converts the `IT` to an `OT`. Note that in many cases but not all, `IT`
# and `OT` will be the same.
class RenderFunction(Generic[IT, OT], OutputRendererSync[OT], ABC):
class RenderFunction(Generic[IT, OT]):
"""
Deprecated. Please use :func:`~shiny.render.renderer_components` instead.
Deprecated. Please use :class:`~shiny.render.renderer.Renderer` class instead.
"""

@abstractmethod
def __call__(self) -> OT:
...

@abstractmethod
async def run(self) -> OT:
...

def __init__(self, fn: ValueFnSync[IT]) -> None:
async def transformer(_meta: TransformerMetadata, _fn: ValueFn[IT]) -> OT:
ret = await self.run()
return ret

super().__init__(
value_fn=fn,
transform_fn=transformer,
params=empty_params(),
raise ShinyDeprecationWarning(
"Class `"
+ str(self.__class__.__name__)
+ "` inherits from the deprecated class `shiny.render.RenderFunction`. "
"Please update your renderer to use `shiny.render.renderer.Renderer` instead."
)
self._fn = fn


# The reason for having a separate RenderFunctionAsync class is because the __call__
# method is marked here as async; you can't have a single class where one method could
# be either sync or async.
class RenderFunctionAsync(Generic[IT, OT], OutputRendererAsync[OT], ABC):
class RenderFunctionAsync(Generic[IT, OT]):
"""
Deprecated. Please use :func:`~shiny.render.renderer_components` instead.
Deprecated. Please use :class:`~shiny.render.renderer.Renderer` class instead.
"""

@abstractmethod
async def __call__(self) -> OT: # pyright: ignore[reportIncompatibleMethodOverride]
...

@abstractmethod
async def run(self) -> OT:
...

def __init__(self, fn: ValueFnAsync[IT]) -> None:
async def transformer(_meta: TransformerMetadata, _fn: ValueFn[IT]) -> OT:
ret = await self.run()
return ret

super().__init__(
value_fn=fn,
transform_fn=transformer,
params=empty_params(),
raise ShinyDeprecationWarning(
"Class `"
+ str(self.__class__.__name__)
+ "` inherits from the deprecated class `shiny.render.RenderFunctionAsync`. "
"Please update your renderer to use `shiny.render.renderer.Renderer` instead."
)
self._fn = fn
6 changes: 2 additions & 4 deletions shiny/render/renderer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
from ._renderer import ( # noqa: F401
RendererBase,
Renderer,
ValueFn,
Jsonifiable,
RendererBaseT,
RendererT,
AsyncValueFn,
# IT, # pyright: ignore[reportUnusedImport]
)

__all__ = (
"RendererBase",
"Renderer",
"ValueFn",
"Jsonifiable",
"AsyncValueFn",
"RendererBaseT",
"RendererT",
)
Loading

0 comments on commit 96a6279

Please sign in to comment.