Skip to content

Commit a9cd3b5

Browse files
committed
Add tests for WeakrefCallable
1 parent f037ed8 commit a9cd3b5

File tree

1 file changed

+128
-1
lines changed

1 file changed

+128
-1
lines changed

core/tests/test_handlers.py

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
import asyncio
2+
import gc
23
from unittest.mock import Mock
34

45
import pytest
56

6-
from toga.handlers import AsyncResult, NativeHandler, simple_handler, wrapped_handler
7+
from toga.handlers import (
8+
AsyncResult,
9+
NativeHandler,
10+
WeakrefCallable,
11+
simple_handler,
12+
wrapped_handler,
13+
)
714

815

916
class ExampleAsyncResult(AsyncResult):
@@ -742,3 +749,123 @@ def test_async_exception_cancelled_sync(event_loop):
742749

743750
# The callback wasn't called
744751
on_result.assert_not_called()
752+
753+
754+
def test_weakref_function_call():
755+
"""Test that WeakrefCallable correctly calls the wrapped function."""
756+
757+
def test_func(x, y=2):
758+
return x + y
759+
760+
wrc = WeakrefCallable(test_func)
761+
762+
# Test with positional arguments
763+
assert wrc(3) == 5
764+
765+
# Test with keyword arguments
766+
assert wrc(3, y=3) == 6
767+
768+
# Test with mixed arguments
769+
assert wrc(3, 4) == 7
770+
771+
772+
def test_weakref_method_call():
773+
"""Test that WeakrefCallable correctly calls a method."""
774+
775+
class TestClass:
776+
def __init__(self, value):
777+
self.value = value
778+
779+
def method(self, x):
780+
return self.value + x
781+
782+
obj = TestClass(5)
783+
wrc = WeakrefCallable(obj.method)
784+
785+
# Test method call
786+
assert wrc(3) == 8
787+
788+
789+
def test_weakref_lambda_call():
790+
"""Test that WeakrefCallable works with lambda functions."""
791+
# Store the lambda in a variable to prevent it from being garbage collected
792+
lambda_func = lambda x: x * 2 # noqa: E731
793+
wrc = WeakrefCallable(lambda_func)
794+
assert wrc(5) == 10
795+
796+
797+
def test_weakref_gc_function():
798+
"""Test that function is garbage collected properly."""
799+
800+
def create_function_wrapper():
801+
def temp_func(x):
802+
return x * 3
803+
804+
return WeakrefCallable(temp_func)
805+
806+
wrc = create_function_wrapper()
807+
808+
# Force garbage collection
809+
gc.collect()
810+
811+
# The function should be gone
812+
assert wrc.ref() is None
813+
814+
815+
def test_weakref_gc_method():
816+
"""Test that method and its object are garbage collected properly."""
817+
818+
class TempClass:
819+
def method(self, x):
820+
return x * 4
821+
822+
def create_method_wrapper():
823+
obj = TempClass()
824+
return WeakrefCallable(obj.method), obj
825+
826+
wrc, obj_ref = create_method_wrapper()
827+
828+
# Object still exists, method should work
829+
assert wrc(2) == 8
830+
831+
# Delete the reference to the object
832+
del obj_ref
833+
834+
# Force garbage collection
835+
gc.collect()
836+
837+
# The method reference should be gone
838+
assert wrc.ref() is None
839+
840+
841+
def test_weakref_callable_object():
842+
"""Test that WeakrefCallable works with callable objects."""
843+
844+
class CallableObject:
845+
def __call__(self, x):
846+
return x * 5
847+
848+
obj = CallableObject()
849+
wrc = WeakrefCallable(obj)
850+
851+
# Test call
852+
assert wrc(2) == 10
853+
854+
855+
def test_weakref_none_result_when_function_gone():
856+
"""Test that calling the wrapper after the target is collected doesn't error."""
857+
858+
def create_function_wrapper():
859+
def temp_func(x):
860+
return x * 3
861+
862+
return WeakrefCallable(temp_func)
863+
864+
wrc = create_function_wrapper()
865+
866+
# Force garbage collection
867+
gc.collect()
868+
869+
# Calling the wrapper should not raise an error
870+
result = wrc(10)
871+
assert result is None

0 commit comments

Comments
 (0)