From 33ca05a3cb59d64a362a2d3a9e78501752b3c79c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Hamal=20Dvo=C5=99=C3=A1k?= <mordae@anilinux.org>
Date: Tue, 11 Mar 2025 16:28:18 +0100
Subject: [PATCH] Deal with errors inside Computed

---
 lazy_player/reactive.py | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

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