Skip to content

Commit

Permalink
working
Browse files Browse the repository at this point in the history
  • Loading branch information
tlambert03 committed Feb 17, 2025
1 parent b8af6b6 commit 4f02ab7
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 17 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ docstring-code-format = true
[tool.pytest.ini_options]
minversion = "6.0"
testpaths = ["tests"]
asyncio_default_fixture_loop_scope = "function"
filterwarnings = [
"error",
"ignore:The distutils package is deprecated:DeprecationWarning:",
Expand Down
51 changes: 36 additions & 15 deletions src/psygnal/_weak_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
)
from warnings import warn

from ._async import _AsyncBackend, get_async_backend
from ._async import get_async_backend
from ._mypyc import mypyc_attr

if TYPE_CHECKING:
import toolz
from typing_extensions import TypeAlias, TypeGuard # py310

from ._async import _AsyncBackend

RefErrorChoice: TypeAlias = Literal["raise", "warn", "ignore"]

__all__ = ["WeakCallback", "weak_callback"]
Expand Down Expand Up @@ -137,12 +139,27 @@ def _on_delete(weak_cb):
)

if isinstance(cb, FunctionType):
# NOTE: I know it looks like this should be easy to express in much shorter
# syntax ... but mypyc will likely fail at runtime.
# Make sure to test compiled version if you change this.
if strong_func:
cls = StrongCoroutineFunction if is_coro else StrongFunction
return cls(cb, max_args, args, kwargs, priority=priority)
if is_coro:
return StrongCoroutineFunction(
cb, max_args, args, kwargs, priority=priority
)
return StrongFunction(cb, max_args, args, kwargs, priority=priority)
else:
wcls = WeakCoroutineFunction if is_coro else WeakFunction
return wcls(
if is_coro:
return WeakCoroutineFunction(
cb,
max_args,
args,
kwargs,
finalize,
on_ref_error=on_ref_error,
priority=priority,
)
return WeakFunction(
cb, max_args, args, kwargs, finalize, on_ref_error, priority=priority
)

Expand All @@ -158,8 +175,12 @@ def _on_delete(weak_cb):
return WeakSetitem(
obj, key, max_args, finalize, on_ref_error, priority=priority
)
mcls = WeakCoroutineMethod if is_coro else WeakMethod
return mcls(

if is_coro:
return WeakCoroutineMethod(
cb, max_args, args, kwargs, finalize, on_ref_error, priority=priority
)
return WeakMethod(
cb, max_args, args, kwargs, finalize, on_ref_error, priority=priority
)

Expand Down Expand Up @@ -239,7 +260,7 @@ def __init__(

self.priority: int = priority

def cb(self, args: tuple[Any, ...] = ()) -> Any:
def cb(self, args: tuple[Any, ...] = ()) -> None:
"""Call the callback with `args`. Args will be spread when calling the func."""
raise NotImplementedError()

Expand Down Expand Up @@ -368,7 +389,7 @@ def __init__(
if args:
self._object_repr = f"{self._object_repr}{(*args,)!r}".replace(")", " ...)")

def cb(self, args: tuple[Any, ...] = ()) -> Any:
def cb(self, args: tuple[Any, ...] = ()) -> None:
if self._max_args is not None:
args = args[: self._max_args]
self._f(*self._args, *args, **self._kwargs)
Expand Down Expand Up @@ -408,7 +429,7 @@ def __init__(
if args:
self._object_repr = f"{self._object_repr}{(*args,)!r}".replace(")", " ...)")

def cb(self, args: tuple[Any, ...] = ()) -> Any:
def cb(self, args: tuple[Any, ...] = ()) -> None:
f = self._f()
if f is None:
raise ReferenceError("weakly-referenced object no longer exists")
Expand Down Expand Up @@ -459,7 +480,7 @@ def slot_repr(self) -> str:
func_name = getattr(self._func_ref(), "__name__", "<method>")
return f"{self._obj_module}.{obj.__class__.__qualname__}.{func_name}"

def cb(self, args: tuple[Any, ...] = ()) -> Any:
def cb(self, args: tuple[Any, ...] = ()) -> None:
obj = self._obj_ref()
func = self._func_ref()
if obj is None or func is None:
Expand Down Expand Up @@ -598,11 +619,11 @@ def dereference(self) -> partial | None:
return None if obj is None else partial(obj.__setitem__, self._itemkey)


# --------------------------- Coroutines --------------------
# --------------------------- Coroutines ---------------------------


class WeakCoroutineFunction(WeakFunction):
def cb(self, args: tuple[Any, ...] = ()) -> Any:
def cb(self, args: tuple[Any, ...] = ()) -> None:
if self._f() is None:
raise ReferenceError("weakly-referenced object no longer exists")
if self._max_args is not None:
Expand All @@ -614,15 +635,15 @@ def cb(self, args: tuple[Any, ...] = ()) -> Any:
class StrongCoroutineFunction(StrongFunction):
"""Wrapper around a strong coroutine function reference."""

def cb(self, args: tuple[Any, ...] = ()) -> Any:
def cb(self, args: tuple[Any, ...] = ()) -> None:
if self._max_args is not None:
args = args[: self._max_args]

cast("_AsyncBackend", get_async_backend())._put((self, args))


class WeakCoroutineMethod(WeakMethod):
def cb(self, args: tuple[Any, ...] = ()) -> Any:
def cb(self, args: tuple[Any, ...] = ()) -> None:
if self._obj_ref() is None or self._func_ref() is None:
raise ReferenceError("weakly-referenced object no longer exists")

Expand Down
4 changes: 2 additions & 2 deletions tests/test_coroutines.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
@pytest.mark.parametrize(
"type_",
[
"coroutinefunc",
# "coroutinefunc",
"weak_coroutinefunc",
"coroutinemethod",
# "coroutinemethod",
],
)
@pytest.mark.asyncio
Expand Down

0 comments on commit 4f02ab7

Please sign in to comment.