Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api!: Merge RendererBase class into Renderer #1032

Merged
merged 12 commits into from
Jan 19, 2024
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
Loading