mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
replace weaksets in reactive
This commit is contained in:
@@ -284,6 +284,7 @@ class MessagePump(metaclass=MessagePumpMeta):
|
|||||||
await timer.stop()
|
await timer.stop()
|
||||||
self._timers.clear()
|
self._timers.clear()
|
||||||
await self._message_queue.put(events.Unmount(sender=self))
|
await self._message_queue.put(events.Unmount(sender=self))
|
||||||
|
Reactive._reset_object(self)
|
||||||
await self._message_queue.put(None)
|
await self._message_queue.put(None)
|
||||||
if self._task is not None and asyncio.current_task() != self._task:
|
if self._task is not None and asyncio.current_task() != self._task:
|
||||||
# Ensure everything is closed before returning
|
# Ensure everything is closed before returning
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from inspect import isawaitable
|
from inspect import isawaitable
|
||||||
from typing import TYPE_CHECKING, Any, Callable, Generic, Type, TypeVar, Union
|
from typing import TYPE_CHECKING, Any, Callable, Generic, Type, TypeVar, Union
|
||||||
from weakref import WeakSet
|
|
||||||
|
|
||||||
from . import events
|
from . import events
|
||||||
from ._callback import count_parameters, invoke
|
from ._callback import count_parameters, invoke
|
||||||
@@ -102,6 +101,7 @@ class Reactive(Generic[ReactiveType]):
|
|||||||
Args:
|
Args:
|
||||||
obj (Reactable): An object with Reactive descriptors
|
obj (Reactable): An object with Reactive descriptors
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not hasattr(obj, "__reactive_initialized"):
|
if not hasattr(obj, "__reactive_initialized"):
|
||||||
startswith = str.startswith
|
startswith = str.startswith
|
||||||
for key in obj.__class__.__dict__:
|
for key in obj.__class__.__dict__:
|
||||||
@@ -116,6 +116,16 @@ class Reactive(Generic[ReactiveType]):
|
|||||||
setattr(obj, name, default_value)
|
setattr(obj, name, default_value)
|
||||||
setattr(obj, "__reactive_initialized", True)
|
setattr(obj, "__reactive_initialized", True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _reset_object(cls, obj: object) -> None:
|
||||||
|
"""Reset reactive structures on object (to avoid reference cycles).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj (object): A reactive object.
|
||||||
|
"""
|
||||||
|
getattr(obj, "__watchers", {}).clear()
|
||||||
|
getattr(obj, "__computes", []).clear()
|
||||||
|
|
||||||
def __set_name__(self, owner: Type[MessageTarget], name: str) -> None:
|
def __set_name__(self, owner: Type[MessageTarget], name: str) -> None:
|
||||||
|
|
||||||
# Check for compute method
|
# Check for compute method
|
||||||
@@ -224,8 +234,7 @@ class Reactive(Generic[ReactiveType]):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Check for watchers set via `watch`
|
# Check for watchers set via `watch`
|
||||||
watcher_name = f"__{name}_watchers"
|
watchers: list[Callable] = getattr(obj, "__watchers", {}).get(name, [])
|
||||||
watchers = getattr(obj, watcher_name, ())
|
|
||||||
for watcher in watchers:
|
for watcher in watchers:
|
||||||
obj.post_message_no_wait(
|
obj.post_message_no_wait(
|
||||||
events.Callback(
|
events.Callback(
|
||||||
@@ -312,11 +321,11 @@ def watch(
|
|||||||
callback (Callable[[Any], object]): A callable to call when the attribute changes.
|
callback (Callable[[Any], object]): A callable to call when the attribute changes.
|
||||||
init (bool, optional): True to call watcher initialization. Defaults to True.
|
init (bool, optional): True to call watcher initialization. Defaults to True.
|
||||||
"""
|
"""
|
||||||
watcher_name = f"__{attribute_name}_watchers"
|
|
||||||
current_value = getattr(obj, attribute_name, None)
|
if not hasattr(obj, "__watchers"):
|
||||||
if not hasattr(obj, watcher_name):
|
setattr(obj, "__watchers", {})
|
||||||
setattr(obj, watcher_name, WeakSet())
|
watchers: dict[str, list[Callable]] = getattr(obj, "__watchers")
|
||||||
watchers = getattr(obj, watcher_name)
|
watchers.setdefault(attribute_name, []).append(callback)
|
||||||
watchers.add(callback)
|
|
||||||
if init:
|
if init:
|
||||||
|
current_value = getattr(obj, attribute_name, None)
|
||||||
Reactive._check_watchers(obj, attribute_name, current_value)
|
Reactive._check_watchers(obj, attribute_name, current_value)
|
||||||
|
|||||||
Reference in New Issue
Block a user