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

feat: Make MISSING_TYPE a None-alike object #1000

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions shiny/reactive/_poll.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from .. import _utils, reactive
from .._docstring import add_example
from ..types import MISSING, MISSING_TYPE
from ..types import MISSING, MISSING_TYPE, SilentException

if TYPE_CHECKING:
from ..session import Session
Expand Down Expand Up @@ -99,7 +99,9 @@ def poll(

with reactive.isolate():
last_value: reactive.Value[Any] = reactive.Value(poll_func())
last_error: reactive.Value[Optional[Exception]] = reactive.Value(None)
last_error: reactive.Value[Optional[Exception | MISSING_TYPE]] = reactive.Value(
None
)

@reactive.effect(priority=priority, session=session)
async def _():
Expand Down Expand Up @@ -166,7 +168,9 @@ def wrapper(fn: Callable[[], T]) -> Callable[[], T]:
async def result_async() -> T:
# If an error occurred, raise it
err = last_error.get()
if err is not None:
if isinstance(err, MISSING_TYPE):
raise SilentException
elif err is not None:
raise err

# Take dependency on polling result
Expand All @@ -189,7 +193,9 @@ async def result_async() -> T:
def result_sync() -> T:
# If an error occurred, raise it
err = last_error.get()
if err is not None:
if isinstance(err, MISSING_TYPE):
raise SilentException
elif err is not None:
raise err

# Take dependency on polling result
Expand Down
7 changes: 2 additions & 5 deletions shiny/reactive/_reactives.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ def __init__(
self._value_dependents: Dependents = Dependents()
self._is_set_dependents: Dependents = Dependents()

def __call__(self) -> T:
def __call__(self) -> T | MISSING_TYPE:
return self.get()

def get(self) -> T:
def get(self) -> T | MISSING_TYPE:
"""
Read the reactive value.

Expand All @@ -138,9 +138,6 @@ def get(self) -> T:

self._value_dependents.register()

if isinstance(self._value, MISSING_TYPE):
raise SilentException

return self._value

def set(self, value: T) -> bool:
Expand Down
17 changes: 12 additions & 5 deletions shiny/session/_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@
from ..reactive import Effect_, Value, effect, flush, isolate
from ..reactive._core import lock, on_flushed
from ..render.renderer import Jsonifiable, RendererBase, RendererBaseT
from ..types import SafeException, SilentCancelOutputException, SilentException
from ..types import (
MISSING_TYPE,
SafeException,
SilentCancelOutputException,
SilentException,
)
from ._utils import RenderedDeps, read_thunk_opt, session_context


Expand Down Expand Up @@ -344,13 +349,15 @@ def _is_hidden(self, name: str) -> bool:
# The .clientdata_output_{name}_hidden string is already a fully namespaced
# id; make that explicit by wrapping it in ResolvedId, otherwise self.input
# will throw an id validation error.
hidden_value_obj = cast(
Value[bool], self.input[ResolvedId(f".clientdata_output_{name}_hidden")]
)
hidden_value_obj = self.input[
ResolvedId(f".clientdata_output_{name}_hidden")
]
if isinstance(hidden_value_obj, MISSING_TYPE):
return True
if not hidden_value_obj.is_set():
return True

return hidden_value_obj()
return cast(bool, hidden_value_obj())

# ==========================================================================
# Message handlers
Expand Down
40 changes: 38 additions & 2 deletions shiny/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,45 @@
from matplotlib.figure import Figure


class MISSING_SILENT_EXCEPTION:
def __getattribute__(self, _: str) -> None:
raise SilentException

def __getitem__(self, _: str) -> None:
raise SilentException

def __setitem__(self, _: Any, __: Any) -> None:
raise SilentException

def __add__(self, _: Any) -> None:
raise SilentException

def __sub__(self, _: Any) -> None:
raise SilentException

def __mul__(self, _: Any) -> None:
raise SilentException

def __div__(self, _: Any) -> None:
raise SilentException


# Sentinel value - indicates a missing value in a function call.
class MISSING_TYPE:
pass
class MISSING_TYPE(MISSING_SILENT_EXCEPTION):
def __eq__(self, _: Any) -> bool:
return False

def __bool__(self) -> bool:
return False

def __len__(self) -> int:
return 0

def __repr__(self) -> str:
return "<MISSING>"

def __str__(self) -> str:
return ""


MISSING: MISSING_TYPE = MISSING_TYPE()
Expand Down
Loading