Deal with errors inside Computed

This commit is contained in:
Jan Hamal Dvořák 2025-03-11 16:28:18 +01:00
parent 5503e48db8
commit 33ca05a3cb

View file

@ -1,19 +1,23 @@
from __future__ import annotations from __future__ import annotations
import sys
import traceback
from contextvars import ContextVar from contextvars import ContextVar
from typing import Any, Callable, ClassVar, Generic, Self, TypeVar from typing import Any, Callable, ClassVar, Generic, Self, TypeVar
from weakref import WeakSet from weakref import WeakSet
__all__ = ["Ref", "Computed", "update_all_computed"] __all__ = ["Ref", "Computed", "Watcher", "update_all_computed"]
T = TypeVar("T") T = TypeVar("T")
class Ref(Generic[T]): class Ref(Generic[T]):
_error: Exception | None
_users: WeakSet[Computed[Any]] _users: WeakSet[Computed[Any]]
_value: T _value: T
def __init__(self, initial: T): def __init__(self, initial: T):
self._error = None
self._value = initial self._value = initial
self._users = WeakSet() self._users = WeakSet()
@ -24,6 +28,9 @@ class Ref(Generic[T]):
if computed is not None: if computed is not None:
self._users.add(computed) self._users.add(computed)
if self._error is not None:
raise self._error
return self._value return self._value
@value.setter @value.setter
@ -47,6 +54,7 @@ class Computed(Ref[T]):
_update: Callable[[], T] _update: Callable[[], T]
def __init__(self, update: Callable[[], T]): def __init__(self, update: Callable[[], T]):
self._error = None
self._update = update self._update = update
self._users = WeakSet() self._users = WeakSet()
self.update() self.update()
@ -56,6 +64,10 @@ class Computed(Ref[T]):
try: try:
self.value = self._update() self.value = self._update()
self._error = None
except Exception as err:
self._error = err
traceback.print_exception(err, file=sys.stderr)
finally: finally:
self._stack.reset(token) self._stack.reset(token)