C#-style event handling mechanism for Python
Project description
C#-Style Event Handling Mechanism for Python
C# provides a very simple syntax using the observer pattern for its event handling system. The aim of this project is to implement the pattern in python as similarly as possible.
In C#, an "event" is a field or a property of the delegate type EventHandler
.
Since delegates in C# can be combined and removed with +=
and -=
operators,
event handlers can easily subscribe to or unsubscribe from the event using those operators.
Python does not support an addition of two Callable
types.
So the Event[P]
class is provided to mimic delegates:
from cs_events import Event
on_change = Event[object, str]()
Handlers can subscribe to and unsubscribe from the event with the same syntax:
def event_handler(o: object, s: str) -> None: ...
on_change += event_handler
on_change -= event_handler
An event can be raised by simply invoking it with the arguments:
on_change(obj, "value")
Since Event
acts just like a delegate from C#, it is not required to be bound to a class or an instance object.
This is the major difference to other packages that try to implement the C#-style event system, which usually revolve around a container object for events.
An example class with event fields may look like this:
class EventExample:
def __init__(self) -> None:
self.on_update: Event[str] = Event()
self.__value: str = ""
def update(self, value: str) -> None:
if self.__value != value:
self.__value = value
self.on_update(value)
obj = EventExample()
obj.on_update += lambda value: print(f"obj.{value=}")
obj.update("new value")
A class decorator @events
is provided as a shortcut for event fields:
from cs_events import Event, events
@events
class EventFieldsExample:
item_added: Event[object]
item_removed: Event[object]
item_updated: Event[object, str]
C# also provides event properties with add
and remove
accessors:
public event EventHandler<T> Changed
{
add => ...
remove => ...
}
This feature is useful for classes that do not actually own the events, but need to forward the subscriptions to the underlying object that do own the events.
The @event[P]
decorator and the accessors[P]
type are provided to support this feature:
from cs_events import accessors, event, EventHandler
class EventPropertyExample:
@event[str, object]
def on_change() -> accessors[str, object]:
def add(self: Self, value: EventHandler[str, object]) -> None:
...
def remove(self: Self, value: EventHandler[str, object]) -> None:
...
return add, remove
Furthermore, the EventHandlerCollection
interface is provided to support the functionalities of System.ComponentModel.EventHandlerList
class from C#, along with the two implementations EventHandlerList
and EventHandlerDict
using a linked list and a dictionary respectively. The behaviour of EventHandlerList
is exactly the same as of its counterpart from C#.
A typical usage of EventHandlerList
in C# can be translated directly into the python code:
class EventPropertyExample:
__event_change: Final = object()
@event # [str, object] is inferred
def on_change(): # -> accessors[str, object] is inferred
def add(self: Self, value: EventHandler[str, object]) -> None:
self.__events.add_handler(self.__event_change, value)
def remove(self: Self, value: EventHandler[str, object]) -> None:
self.__events.remove_handler(self.__event_change, value)
return add, remove
def __init__(self) -> None:
self.__events = EventHandlerList()
def perform_change(self, key: str, value: object) -> None:
e = self.__events[self.__event_change]
if e is not None:
e(key, value)
The class decorator @events
also provides a shortcut for event properties.
The above code can be shortened to:
@events(collection="__events", prefix="on_")
class EventPropertyExample:
on_change: event[object, str]
def __init__(self) -> None:
self.__events = EventHandlerList()
def perform_change(self, key: str, value: object) -> None:
self.__events.invoke("change", key, value)
Installation
Install using pip
:
pip install cs-events
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for cs_events-0.2.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b9e10a64c139e340063e238fb9db2dcdf3b5ca70b7335b4fdd4d3e16a00cb185 |
|
MD5 | 4be0d1da5c9f7e1fcdb7c5da15daf5e6 |
|
BLAKE2b-256 | 82bae040129936b91266b8a9cffba3a560afe08799a5af39527181311719d002 |