Skip to content

Commit 19ffaf0

Browse files
author
Andreas Bayer
committed
Added automatic unregistering of BindableProperty objects to avoid storing references in binding.bindable_properties until explicitly removed
1 parent 561c02b commit 19ffaf0

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

nicegui/binding.py

+16-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import asyncio
22
import time
3+
import weakref
34
from collections import defaultdict
45
from collections.abc import Mapping
56
from typing import Any, Callable, DefaultDict, Dict, Iterable, List, Optional, Set, Tuple, Union
@@ -10,7 +11,7 @@
1011
MAX_PROPAGATION_TIME = 0.01
1112

1213
bindings: DefaultDict[Tuple[int, str], List] = defaultdict(list)
13-
bindable_properties: Dict[Tuple[int, str], Any] = {}
14+
bindable_properties: Dict[Tuple[int, str], weakref.finalize] = {}
1415
active_links: List[Tuple[Any, str, Any, str, Callable[[Any], Any]]] = []
1516

1617

@@ -149,11 +150,19 @@ def __set__(self, owner: Any, value: Any) -> None:
149150
if has_attr and not value_changed:
150151
return
151152
setattr(owner, '___' + self.name, value)
152-
bindable_properties[(id(owner), self.name)] = owner
153+
self._register(owner)
153154
_propagate(owner, self.name)
154155
if value_changed and self._change_handler is not None:
155156
self._change_handler(owner, value)
156157

158+
def _register(self, owner: Any) -> None:
159+
registry_key = (id(owner), str(self.name))
160+
161+
def try_unregister() -> None:
162+
bindable_properties.pop(registry_key, None)
163+
164+
bindable_properties.setdefault(registry_key, weakref.finalize(owner, try_unregister))
165+
157166

158167
def remove(objects: Iterable[Any]) -> None:
159168
"""Remove all bindings that involve the given objects.
@@ -174,9 +183,11 @@ def remove(objects: Iterable[Any]) -> None:
174183
]
175184
if not binding_list:
176185
del bindings[key]
177-
for (obj_id, name), obj in list(bindable_properties.items()):
178-
if id(obj) in object_ids:
179-
del bindable_properties[(obj_id, name)]
186+
for registry_key, finalizer in list(bindable_properties.items()):
187+
obj_id, _ = registry_key
188+
if obj_id in object_ids:
189+
del bindable_properties[registry_key]
190+
finalizer.detach()
180191

181192

182193
def reset() -> None:

0 commit comments

Comments
 (0)