Skip to content

Commit eed7a71

Browse files
nanomadedenhaus
andauthored
Fix OnChangedDict behaviour with recent python versions (#894)
Co-authored-by: Robert Resch <robert@resch.dev>
1 parent ed3f30d commit eed7a71

3 files changed

Lines changed: 48 additions & 3 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit dae72c105649e1a9a954bb576f210ed28fd38208

deebot_client/util/__init__.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ class OnChangedDict(dict[_KT, _VT]):
8181
"pop",
8282
"popitem",
8383
"update",
84-
"__setitem__",
85-
"__delitem__",
8684
)
8785

8886
def __init__(
@@ -91,6 +89,16 @@ def __init__(
9189
super().__init__(iterable)
9290
self._on_change = on_change
9391

92+
# This is needed as __getattribute__ won't be invoked for implicit special method lookup
93+
def __setitem__(self, key: _KT, value: _VT) -> None:
94+
self._on_change()
95+
super().__setitem__(key, value)
96+
97+
# This is needed as __getattribute__ won't be invoked for implicit special method lookup
98+
def __delitem__(self, key: _KT) -> None:
99+
self._on_change()
100+
return super().__delitem__(key)
101+
94102
def __getattribute__(self, name: str, /) -> Any:
95103
if name in OnChangedDict._MODIFYING_FUNCTIONS:
96104
self._on_change()

tests/util/test_init.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import asyncio
44
from typing import Any
55

6-
from deebot_client.util import cancel, create_task
6+
from deebot_client.util import OnChangedDict, cancel, create_task
77

88

99
async def test_create_task_and_cancel() -> None:
@@ -35,3 +35,39 @@ async def sleep(delay: float) -> None:
3535
for task in _tasks:
3636
assert task.cancelled()
3737
assert task.done()
38+
39+
40+
def test_on_changed_dict() -> None:
41+
callback_count = 0
42+
43+
def increase_counter() -> None:
44+
nonlocal callback_count
45+
callback_count += 1
46+
47+
sut: OnChangedDict[str, int] = OnChangedDict(increase_counter)
48+
49+
sut["test"] = 1001
50+
assert callback_count == 1
51+
assert sut["test"] == 1001
52+
53+
sut.update({"test": 1002, "test2": 2001, "test3": 3001, "test4": 4001})
54+
assert sut["test"] == 1002
55+
assert callback_count == 2
56+
57+
del sut["test"]
58+
assert "test" not in sut
59+
assert callback_count == 3
60+
61+
assert sut.pop("test2") == 2001
62+
assert "test2" not in sut
63+
assert callback_count == 4
64+
65+
(popped_key, popped_value) = sut.popitem()
66+
assert popped_key == "test4"
67+
assert popped_value == 4001
68+
assert "test4" not in sut
69+
assert callback_count == 5
70+
71+
sut.clear()
72+
assert sut == {}
73+
assert callback_count == 6

0 commit comments

Comments
 (0)