diff --git a/shiny/_app.py b/shiny/_app.py index 664a2238a..b0890f313 100644 --- a/shiny/_app.py +++ b/shiny/_app.py @@ -3,6 +3,7 @@ import copy import os import secrets +from inspect import signature from pathlib import Path from typing import Any, Callable, Optional, cast @@ -101,19 +102,25 @@ def server(input: Inputs, output: Outputs, session: Session): def __init__( self, ui: Tag | TagList | Callable[[Request], Tag | TagList] | Path, - server: Optional[Callable[[Inputs, Outputs, Session], None]], + server: Callable[[Inputs], None] + | Callable[[Inputs, Outputs, Session], None] + | None, *, static_assets: Optional["str" | "os.PathLike[str]" | dict[str, Path]] = None, debug: bool = False, ) -> None: if server is None: - - def _server(inputs: Inputs, outputs: Outputs, session: Session): - pass - - server = _server - - self.server = server + self.server = noop_server_fn + elif len(signature(server).parameters) == 1: + self.server = wrap_server_fn_with_output_session( + cast(Callable[[Inputs], None], server) + ) + elif len(signature(server).parameters) == 3: + self.server = cast(Callable[[Inputs, Outputs, Session], None], server) + else: + raise ValueError( + "`server` must have 1 (Inputs) or 3 parameters (Inputs, Outputs, Session)" + ) self._debug: bool = debug @@ -446,3 +453,17 @@ def file_response_handler(req: Request) -> FileResponse: file_response_handler, name="shiny-app-static-assets-" + mount_point, ) + + +def noop_server_fn(input: Inputs, output: Outputs, session: Session) -> None: + pass + + +def wrap_server_fn_with_output_session( + server: Callable[[Inputs], None] +) -> Callable[[Inputs, Outputs, Session], None]: + def _server(input: Inputs, output: Outputs, session: Session): + # Only has 1 parameter, ignore output, session + server(input) + + return _server