Description
Hello TechnoBro, I have a maybe somewhat unusual proposal to make.
Some time ago, I wrote an adhoc event library for a GUI toolkit I created. Long story short, it went through some iterations and eventually came about to look much like Eventic, minus the async support, plus some other goodies.
Since it proved useful on its own, I now thought about splitting it out as its own package. While searching for a name, stumbled upon your project. Now, I could just ignore it and go ahead with my own, but I thought maybe it's better to join forces and make one great typed event library instead of two good ones. :-)
You can look at my module here: https://github.com/loehnertj/ascii_designer/blob/master/src/ascii_designer/event.py
I already took the effort of looking through both modules to make a rough comparison. Both do the same basic task of turning a method or function into an event forwarder that can be subscribed to. Funnily enough, the overall code structure is nearly the same. However you have some features I don't have (async support, with-subscription, .once) and I have some you don't have. Categorizing a bit, these are:
Docs, nonbreaking changes
- Extensive docstring, going into some particulars that I didn't see covered in your docs at first glance.
- using
functool.update_wrapper for improved introspetion of decorated function (copy docstring + signature e.g. for sphinx)
Stricter requirements for event signature, runtime checking
- upon invoke, calls the wrapped (empty) function to make sure that call has right signature
- event arguments must be marked positional-only or keyword-only, they cannot be ambigous. (opt-in, "strict mode") - The reasoning is that the subscriber otherwise cannot know how the emitter will pass the argument - by-position or by-name - this check enforces certainty.
- Forbid arguments with default values - again because meaning of these would not be well-defined. Applies to event signature, not to handler functions.
- explicit convention for
self argument (for method). In the current implementation it's forbidden, however with today's experience I'd rather make it mandatory but ignored, since this plays better with typecheckers.
- All these rules are checked upon construction of Event, using
inspect.signature.
Configurable exception policy
Requiring exception handling in subscribers is bad, because people (me included) keep forgetting it. In my version, exceptions in handlers are caught and handled. Exception policy can be configured by a decorator parameter @event(exceptions=...):
"log" (default) emits a logging.error message with the traceback.
"print" prints the exception (using traceback.print_exception).
"raise" raises any exception immediately. No subsequent listeners are
called. Event Invoker must be prepared for exceptions.
"group" calls all listeners, then raises an ExceptionGroup if any
failed. The error is always an ExceptionGroup, even in case of a single
error. Event invoker must catch it.
- (... note how there is no "silently discard it" option... ;-))
Canceling processing
Any event handler may raise a special CancelEvent exception in order to stop handling of the event at this point.
I think it would be cool to take all of this over into Eventic, to make it into something really great and not clutter PyPI more than necessary. :-) I'm also ready to do all the work on this. Since both modules are structured almost identical, I hope it should'nt be to hard, and mostly boil down to thoroughly unittesting everything.
However before starting to to churn out PR's, I'd rather hereby ask first,if you are interested in cooperating on that, or if you rather wouldn't. The latter is also OK. In this case I won't bother you further and publish my library separately. What do you say?
Best regards, Johannes
Description
Hello TechnoBro, I have a maybe somewhat unusual proposal to make.
Some time ago, I wrote an adhoc event library for a GUI toolkit I created. Long story short, it went through some iterations and eventually came about to look much like Eventic, minus the async support, plus some other goodies.
Since it proved useful on its own, I now thought about splitting it out as its own package. While searching for a name, stumbled upon your project. Now, I could just ignore it and go ahead with my own, but I thought maybe it's better to join forces and make one great typed event library instead of two good ones. :-)
You can look at my module here: https://github.com/loehnertj/ascii_designer/blob/master/src/ascii_designer/event.py
I already took the effort of looking through both modules to make a rough comparison. Both do the same basic task of turning a method or function into an event forwarder that can be subscribed to. Funnily enough, the overall code structure is nearly the same. However you have some features I don't have (async support, with-subscription, .once) and I have some you don't have. Categorizing a bit, these are:
Docs, nonbreaking changes
functool.update_wrapperfor improved introspetion of decorated function (copy docstring + signature e.g. for sphinx)Stricter requirements for event signature, runtime checking
selfargument (for method). In the current implementation it's forbidden, however with today's experience I'd rather make it mandatory but ignored, since this plays better with typecheckers.inspect.signature.Configurable exception policy
Requiring exception handling in subscribers is bad, because people (me included) keep forgetting it. In my version, exceptions in handlers are caught and handled. Exception policy can be configured by a decorator parameter
@event(exceptions=...):"log"(default) emits alogging.errormessage with the traceback."print"prints the exception (usingtraceback.print_exception)."raise"raises any exception immediately. No subsequent listeners arecalled. Event Invoker must be prepared for exceptions.
"group"calls all listeners, then raises anExceptionGroupif anyfailed. The error is always an
ExceptionGroup, even in case of a singleerror. Event invoker must catch it.
Canceling processing
Any event handler may raise a special
CancelEventexception in order to stop handling of the event at this point.I think it would be cool to take all of this over into Eventic, to make it into something really great and not clutter PyPI more than necessary. :-) I'm also ready to do all the work on this. Since both modules are structured almost identical, I hope it should'nt be to hard, and mostly boil down to thoroughly unittesting everything.
However before starting to to churn out PR's, I'd rather hereby ask first,if you are interested in cooperating on that, or if you rather wouldn't. The latter is also OK. In this case I won't bother you further and publish my library separately. What do you say?
Best regards, Johannes