use weakmethod, add signature

This commit is contained in:
Talley Lambert
2024-06-03 09:55:44 -04:00
parent 15228eb989
commit 0585197383
2 changed files with 11 additions and 10 deletions

View File

@@ -29,13 +29,14 @@ SOFTWARE.
from __future__ import annotations
import weakref
from concurrent.futures import Future
from contextlib import suppress
from enum import IntFlag, auto
from functools import wraps
from inspect import signature
from types import MethodType
from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, overload
from weakref import WeakKeyDictionary
from weakref import WeakKeyDictionary, WeakMethod
from qtpy.QtCore import QObject, Qt, QTimer, Signal
@@ -214,18 +215,14 @@ class QSignalDebouncer(GenericSignalThrottler):
def _weak_func(func: Callable[P, R]) -> Callable[P, R]:
if isinstance(func, MethodType):
# this is a bound method, we need to avoid strong references
owner = func.__self__
class_func = func.__func__
try:
instance_ref = weakref.ref(owner)
weak_method = WeakMethod(func)
except TypeError as e:
raise TypeError(REF_ERROR) from e
def weak_func(*args, **kwargs):
if (obj := instance_ref()) is None:
raise RuntimeError("Method called on dead object")
method = class_func.__get__(obj, type(obj))
return method(*args, **kwargs)
if method := weak_method():
return method(*args, **kwargs)
return weak_func
@@ -250,6 +247,9 @@ class ThrottledCallable(GenericSignalThrottler, Generic[P, R]):
func = func.__func__
max_args = get_max_args(func)
with suppress(TypeError, ValueError):
self.__signature__ = signature(func)
self._func = _weak_func(func)
self.__wrapped__ = self._func

View File

@@ -213,7 +213,7 @@ def test_qthrottled_does_not_prevent_gc(qtbot):
mock()
@qthrottled(timeout=1)
def tmethod(self) -> None:
def tmethod(self, x: int = 1) -> None:
mock()
thing = Thing()
@@ -225,6 +225,7 @@ def test_qthrottled_does_not_prevent_gc(qtbot):
thing.tmethod()
qtbot.waitUntil(thing.tmethod._future.done, timeout=2000)
assert mock.call_count == 2
del thing
gc.collect()
assert thing_ref() is None