Skip to content

Commit 06f1670

Browse files
fix: deprecated internal scope argument and always remember the context on subscribe
In use_reactive, the subscribe did not pass a context, so it was None. We now always store the context for listeners, and we also rename the scope to context.
1 parent 37666e4 commit 06f1670

File tree

1 file changed

+39
-24
lines changed

1 file changed

+39
-24
lines changed

solara/toestand.py

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -154,39 +154,52 @@ def _get_scope_key(self):
154154
raise NotImplementedError
155155

156156
def subscribe(self, listener: Callable[[T], None], scope: Optional[ContextManager] = None):
157+
if scope is not None:
158+
warnings.warn("scope argument should not be used, it was only for internal use")
159+
del scope
157160
scope_id = self._get_scope_key()
158-
self.listeners[scope_id].add((listener, scope))
161+
rc = reacton.core.get_render_context(required=False)
162+
kernel = solara.server.kernel_context.get_current_context() if solara.server.kernel_context.has_current_context() else nullcontext()
163+
context = Context(rc, kernel)
164+
165+
self.listeners[scope_id].add((listener, context))
159166

160167
def cleanup():
161-
self.listeners[scope_id].remove((listener, scope))
168+
self.listeners[scope_id].remove((listener, context))
162169

163170
return cleanup
164171

165172
def subscribe_change(self, listener: Callable[[T, T], None], scope: Optional[ContextManager] = None):
173+
if scope is not None:
174+
warnings.warn("scope argument should not be used, it was only for internal use")
175+
del scope
166176
scope_id = self._get_scope_key()
167-
self.listeners2[scope_id].add((listener, scope))
177+
rc = reacton.core.get_render_context(required=False)
178+
kernel = solara.server.kernel_context.get_current_context() if solara.server.kernel_context.has_current_context() else nullcontext()
179+
context = Context(rc, kernel)
180+
self.listeners2[scope_id].add((listener, context))
168181

169182
def cleanup():
170-
self.listeners2[scope_id].remove((listener, scope))
183+
self.listeners2[scope_id].remove((listener, context))
171184

172185
return cleanup
173186

174187
def fire(self, new: T, old: T):
175188
logger.info("value change from %s to %s, will fire events", old, new)
176189
scope_id = self._get_scope_key()
177-
scopes = set()
178-
for listener, scope in self.listeners[scope_id].copy():
179-
scopes.add(scope)
180-
for listener2, scope in self.listeners2[scope_id].copy():
181-
scopes.add(scope)
182-
if scopes:
183-
for scope in scopes:
184-
with scope or nullcontext():
185-
for listener, scope_listener in self.listeners[scope_id].copy():
186-
if scope == scope_listener:
190+
contexts = set()
191+
for listener, context in self.listeners[scope_id].copy():
192+
contexts.add(context)
193+
for listener2, context in self.listeners2[scope_id].copy():
194+
contexts.add(context)
195+
if contexts:
196+
for context in contexts:
197+
with context or nullcontext():
198+
for listener, context_listener in self.listeners[scope_id].copy():
199+
if context == context_listener:
187200
listener(new)
188-
for listener2, scope_listener in self.listeners2[scope_id].copy():
189-
if scope == scope_listener:
201+
for listener2, context_listener in self.listeners2[scope_id].copy():
202+
if context == context_listener:
190203
listener2(new, old)
191204

192205
def update(self, _f=None, **kwargs):
@@ -847,7 +860,7 @@ class AutoSubscribeContextManagerBase:
847860
def __init__(self):
848861
self.subscribed = {}
849862

850-
def update_subscribers(self, change_handler, scope=None):
863+
def update_subscribers(self, change_handler):
851864
assert self.reactive_used is not None
852865
reactive_used = self.reactive_used
853866
# remove subfields for which we already listen to it's root reactive value
@@ -863,7 +876,7 @@ def update_subscribers(self, change_handler, scope=None):
863876

864877
for reactive in added:
865878
if reactive not in self.subscribed:
866-
unsubscribe = reactive.subscribe_change(change_handler, scope=scope)
879+
unsubscribe = reactive.subscribe_change(change_handler)
867880
self.subscribed[reactive] = unsubscribe
868881
for reactive in removed:
869882
unsubscribe = self.subscribed[reactive]
@@ -892,12 +905,16 @@ def __init__(self, render_context, kernel_context):
892905
self.kernel_context = kernel_context
893906

894907
def __enter__(self):
895-
self.render_context.__enter__()
908+
if self.render_context is not None:
909+
self.render_context.__enter__()
896910
self.kernel_context.__enter__()
897911

898912
def __exit__(self, exc_type, exc_val, exc_tb):
899-
# this will trigger a render
900-
res1 = self.render_context.__exit__(exc_type, exc_val, exc_tb)
913+
if self.render_context is not None:
914+
# this will trigger a render
915+
res1 = self.render_context.__exit__(exc_type, exc_val, exc_tb)
916+
else:
917+
res1 = None
901918
# pop the current context from the stack
902919
res2 = self.kernel_context.__exit__(exc_type, exc_val, exc_tb)
903920
return res1 or res2
@@ -929,9 +946,7 @@ def force_update(new_value, old_value):
929946
super().__enter__()
930947

931948
def update_subscribers():
932-
rc = reacton.core.get_render_context(required=True)
933-
kernel = solara.server.kernel_context.get_current_context() if solara.server.kernel_context.has_current_context() else nullcontext()
934-
self.update_subscribers(force_update, scope=Context(rc, kernel))
949+
self.update_subscribers(force_update)
935950

936951
solara.use_effect(update_subscribers, None)
937952

0 commit comments

Comments
 (0)