i have written an event system in which functions and metheodes can register as listeners for events. i use a decorator for this. The whole thing worked without problems for functions, but it doesn't work for methods. The core of the system is an eventDispatcher singleton class, which also contains the following code for the decorator:
def register(self, event_type: str):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
self._listeners[event_type].append(func)
return wrapper
return decorator
here the application on a method:
class MidiOutput:
def __init__(self, out_port: str):
pass
@EventDispatcher.register("play_note")
def on_play_note(self, event):
pass
as a result i get the following error message:
@EventDispatcher.register("output_changed")
TypeError: EventDispatcher.register() missing 1 required positional argument: 'event_type'
what can i do to be able to use the decorator for methods as well?
I've been able to replicate your issue and fix it simply.
Here is my fixed code:
from functools import wraps
class EventDispatcher:
def __init__(self):
self._listeners = {
"play_note": []
}
def register(self, event_type: str):
"""
Register a decorator that can be used to register a listener for the specified event type.
:param event_type: The event type to listen for.
:return: A decorator that can be used to register a listener for the specified event type.
"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
self._listeners[event_type].append(func)
return wrapper
return decorator
DispatcherInstance = EventDispatcher()
class MidiOutput:
def __init__(self, out_port: str):
pass
@DispatcherInstance.register("play_note")
def on_play_note(self, event):
print("works ok")
There is a little bit of guesswork involved with the init
method (which was not provided).
But apart from that all I do is instantiate the EventDispatcher
class in an object called DispatcherInstance
on line 28:
DispatcherInstance = EventDispatcher()
And then use that specific instance to call the register
method as a wrapper on the MidiOutput
definition.
Now while this does fix your issue, it is worth noting that doing so requires creating an EventDispatcher object. Thus any code calling this file, will create that object.
So I would keep that object as simple as possible if this is the fix you chose to implement.