fix: prevent qthrottled and qdebounced from holding strong references with bound methods (#247)

* finish

* linting

* done

* use weakmethod, add signature

* add test for warning
This commit is contained in:
Talley Lambert
2024-06-03 10:24:03 -04:00
committed by GitHub
parent 7b1aefd119
commit 1f4d9081b9
4 changed files with 107 additions and 35 deletions

View File

@@ -1,3 +1,5 @@
import gc
import weakref
from unittest.mock import Mock
import pytest
@@ -116,7 +118,6 @@ def test_debouncer_method_definition(qtbot):
A.call2(32)
qtbot.wait(5)
assert a.count == 1
mock1.assert_called_once()
mock2.assert_called_once()
@@ -201,3 +202,36 @@ def test_ensure_throttled_sig_inspection(deco, qtbot):
mock.assert_called_once_with(1, 2)
assert func.__doc__ == "docstring"
assert func.__name__ == "func"
def test_qthrottled_does_not_prevent_gc(qtbot):
mock = Mock()
class Thing:
@qdebounced(timeout=1)
def dmethod(self) -> None:
mock()
@qthrottled(timeout=1)
def tmethod(self, x: int = 1) -> None:
mock()
thing = Thing()
thing_ref = weakref.ref(thing)
assert thing_ref() is not None
thing.dmethod()
qtbot.waitUntil(thing.dmethod._future.done, timeout=2000)
assert mock.call_count == 1
thing.tmethod()
qtbot.waitUntil(thing.tmethod._future.done, timeout=2000)
assert mock.call_count == 2
wm = thing.tmethod
assert isinstance(wm, ThrottledCallable)
del thing
gc.collect()
assert thing_ref() is None
with pytest.warns(RuntimeWarning, match="Method has been garbage collected"):
wm()
wm._set_future_result()