From 0b6ce6b9b9b2b713da99c9d950ff11ae73df4545 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 30 Oct 2023 12:50:52 -0400 Subject: [PATCH 1/6] All `server` to take only `input` as `output` and `session` are no longer needed. --- shiny/_app.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/shiny/_app.py b/shiny/_app.py index a174800fd..6e541a183 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,30 @@ 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: Optional[ + Callable[[Inputs], None] | Callable[[Inputs, Outputs, Session], 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): + def _server(input: Inputs, output: Outputs, session: Session): pass - server = _server + self.server = _server + else: + if len(signature(server).parameters) == 1: + + def _server(input: Inputs, output: Outputs, session: Session): + # Only has 1 parameter, ignore output, session + server(input) # pyright: ignore[reportGeneralTypeIssues] - self.server = server + self.server = _server + else: + # Pass through all three arguments + self.server = server # pyright: ignore[reportGeneralTypeIssues] self._debug: bool = debug From ab278f8338cbfb29a9f58143fc9cd62cd2cdfc00 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 18 Dec 2023 17:03:25 -0500 Subject: [PATCH 2/6] Clearer intent of server function typing --- shiny/_app.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shiny/_app.py b/shiny/_app.py index 6e541a183..747c24e95 100644 --- a/shiny/_app.py +++ b/shiny/_app.py @@ -102,9 +102,9 @@ def server(input: Inputs, output: Outputs, session: Session): def __init__( self, ui: Tag | TagList | Callable[[Request], Tag | TagList] | Path, - server: Optional[ - Callable[[Inputs], None] | 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, From 098eabdf00f20ed94e7531e66d4664b47c1ead1d Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 18 Dec 2023 17:04:18 -0500 Subject: [PATCH 3/6] Abstract server param typing to make tighter init method --- shiny/_app.py | 51 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/shiny/_app.py b/shiny/_app.py index 747c24e95..9565ed643 100644 --- a/shiny/_app.py +++ b/shiny/_app.py @@ -5,7 +5,7 @@ import secrets from inspect import signature from pathlib import Path -from typing import Any, Callable, Optional, cast +from typing import Any, Callable, Optional, TypeGuard, cast import starlette.applications import starlette.exceptions @@ -110,22 +110,15 @@ def __init__( debug: bool = False, ) -> None: if server is None: - - def _server(input: Inputs, output: Outputs, session: Session): - pass - - self.server = _server + self.server = noop_server + elif has_only_input(server): + self.server = ignore_output_session_server(server) + elif has_input_output_session(server): + self.server = server else: - if len(signature(server).parameters) == 1: - - def _server(input: Inputs, output: Outputs, session: Session): - # Only has 1 parameter, ignore output, session - server(input) # pyright: ignore[reportGeneralTypeIssues] - - self.server = _server - else: - # Pass through all three arguments - self.server = server # pyright: ignore[reportGeneralTypeIssues] + raise ValueError( + "`server` must have 1 (Inputs) or 3 parameters (Inputs, Outputs, Session)" + ) self._debug: bool = debug @@ -458,3 +451,29 @@ def file_response_handler(req: Request) -> FileResponse: file_response_handler, name="shiny-app-static-assets-" + mount_point, ) + + +def noop_server(input: Inputs, output: Outputs, session: Session) -> None: + pass + + +def ignore_output_session_server( + 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 + + +def has_only_input( + x: Callable[[Inputs], None] | Callable[[Inputs, Outputs, Session], None] +) -> TypeGuard[Callable[[Inputs], None]]: + return len(signature(x).parameters) == 1 + + +def has_input_output_session( + x: Callable[[Inputs], None] | Callable[[Inputs, Outputs, Session], None] +) -> TypeGuard[Callable[[Inputs, Outputs, Session], None]]: + return len(signature(x).parameters) == 3 From e2d6b000e40e4bac7bef7cbc029ef84b5124897d Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Mon, 18 Dec 2023 17:25:23 -0500 Subject: [PATCH 4/6] Move TypeGuard import --- shiny/_app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shiny/_app.py b/shiny/_app.py index 9565ed643..dd7268ac7 100644 --- a/shiny/_app.py +++ b/shiny/_app.py @@ -5,7 +5,7 @@ import secrets from inspect import signature from pathlib import Path -from typing import Any, Callable, Optional, TypeGuard, cast +from typing import Any, Callable, Optional, cast import starlette.applications import starlette.exceptions @@ -28,6 +28,7 @@ from ._connection import Connection, StarletteConnection from ._error import ErrorMiddleware from ._shinyenv import is_pyodide +from ._typing_extensions import TypeGuard from ._utils import guess_mime_type, is_async_callable from .html_dependencies import jquery_deps, require_deps, shiny_deps from .http_staticfiles import FileResponse, StaticFiles From 7e5bae2814cb7926b9e352d63c7a90b925c92f6d Mon Sep 17 00:00:00 2001 From: Winston Chang Date: Tue, 19 Dec 2023 15:51:47 -0600 Subject: [PATCH 5/6] Code updates --- shiny/_app.py | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/shiny/_app.py b/shiny/_app.py index 09fbc2a57..740e1a73a 100644 --- a/shiny/_app.py +++ b/shiny/_app.py @@ -111,11 +111,13 @@ def __init__( debug: bool = False, ) -> None: if server is None: - self.server = noop_server - elif has_only_input(server): - self.server = ignore_output_session_server(server) - elif has_input_output_session(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)" @@ -454,11 +456,11 @@ def file_response_handler(req: Request) -> FileResponse: ) -def noop_server(input: Inputs, output: Outputs, session: Session) -> None: +def noop_server_fn(input: Inputs, output: Outputs, session: Session) -> None: pass -def ignore_output_session_server( +def wrap_server_fn_with_output_session( server: Callable[[Inputs], None] ) -> Callable[[Inputs, Outputs, Session], None]: def _server(input: Inputs, output: Outputs, session: Session): @@ -466,15 +468,3 @@ def _server(input: Inputs, output: Outputs, session: Session): server(input) return _server - - -def has_only_input( - x: Callable[[Inputs], None] | Callable[[Inputs, Outputs, Session], None] -) -> TypeGuard[Callable[[Inputs], None]]: - return len(signature(x).parameters) == 1 - - -def has_input_output_session( - x: Callable[[Inputs], None] | Callable[[Inputs, Outputs, Session], None] -) -> TypeGuard[Callable[[Inputs, Outputs, Session], None]]: - return len(signature(x).parameters) == 3 From 5c9b84eab9af6339c1fea698d13de90f98f6104c Mon Sep 17 00:00:00 2001 From: Winston Chang Date: Tue, 19 Dec 2023 16:01:57 -0600 Subject: [PATCH 6/6] Remove unused import --- shiny/_app.py | 1 - 1 file changed, 1 deletion(-) diff --git a/shiny/_app.py b/shiny/_app.py index 740e1a73a..b0890f313 100644 --- a/shiny/_app.py +++ b/shiny/_app.py @@ -28,7 +28,6 @@ from ._connection import Connection, StarletteConnection from ._error import ErrorMiddleware from ._shinyenv import is_pyodide -from ._typing_extensions import TypeGuard from ._utils import guess_mime_type, is_async_callable from .html_dependencies import jquery_deps, require_deps, shiny_deps from .http_staticfiles import FileResponse, StaticFiles