Skip to content

Commit

Permalink
Allow the Signal set_class to be customised
Browse files Browse the repository at this point in the history
This allows an easy way for receivers to be called in registration
order, as is often desired by users of the library.
  • Loading branch information
pgjones committed Nov 1, 2023
1 parent fe3ec89 commit 5ad0039
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 3 deletions.
18 changes: 18 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,24 @@ event loop the following example can be used:
await sig.send(_async_wrapper=wrapper)
Call receivers in order of registration
---------------------------------------

It can be advantageous to call a signal's receivers in the order they
were registered. To achieve this the storage class for receivers should
be changed from an (unordered) set to an ordered set,

.. code-block:: python
from blinker import Signal
from ordered_set import OrderedSet
Signal.set_class = OrderedSet
Please note that ``ordered_set`` is a PyPI package and is not
installed with blinker.


API Documentation
-----------------

Expand Down
10 changes: 8 additions & 2 deletions src/blinker/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class Signal:
#: without an additional import.
ANY = ANY

set_class: type[set] = set

@lazy_property
def receiver_connected(self) -> Signal:
"""Emitted after each :meth:`connect`.
Expand Down Expand Up @@ -103,8 +105,12 @@ def __init__(self, doc: str | None = None) -> None:
#: any receivers are connected to the signal.
self.receivers: dict[IdentityType, t.Callable | annotatable_weakref] = {}
self.is_muted = False
self._by_receiver: dict[IdentityType, set[IdentityType]] = defaultdict(set)
self._by_sender: dict[IdentityType, set[IdentityType]] = defaultdict(set)
self._by_receiver: dict[IdentityType, set[IdentityType]] = defaultdict(
self.set_class
)
self._by_sender: dict[IdentityType, set[IdentityType]] = defaultdict(
self.set_class
)
self._weak_senders: dict[IdentityType, annotatable_weakref] = {}

def connect(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class BaseFailure(BaseException):
pass


@pytest.mark.parametrize('exc_type', [Failure, BaseFailure])
@pytest.mark.parametrize("exc_type", [Failure, BaseFailure])
def test_temp_connection_failure(exc_type):
sig = Signal()

Expand Down

0 comments on commit 5ad0039

Please sign in to comment.