kevent
Русский | English
kevent is a small, typed event system for Python applications. It provides a base Event type, declarative listeners, middleware hooks, and a lightweight handler that dispatches events by concrete type and by generic fallback.
What It Does
Eventis the base class for application eventsListenerbinds one event class to one callbacklistener()is a decorator for declarative listener registrationMiddlewareruns before listeners receive an eventEventHandlerstores listeners, runs middleware, and dispatches events
Quick Start
from kevent import Event, EventHandler, Middleware, listener
class UserLoggedIn(Event):
def __init__(self, username: str) -> None:
self.username = username
class TraceMiddleware(Middleware):
def __init__(self) -> None:
self.trace: list[str] = []
def process(self, event: Event) -> Event | None:
self.trace.append(type(event).__name__)
return event # Continue propagation
def on_login(event: UserLoggedIn) -> None:
print(f"welcome:{event.username}")
def on_any(event: Event) -> None:
print(f"received:{type(event).__name__}")
handler = EventHandler()
handler.add_middleware(TraceMiddleware())
handler.subscribe(listener(UserLoggedIn)(on_login))
handler.subscribe(listener(Event)(on_any))
handler.publish(UserLoggedIn("aria"))
CLI
Run a built-in demo that shows middleware and listener dispatch:
kevent demo "hello"
Expected output:
middleware:DemoEvent
listener:hello
fallback:DemoEvent
Installation
uv sync --dev
Development
Run tests:
just test
Run linting and type checks:
just check
Format code:
just fmt
Build release artifacts:
just build
Project Layout
kevent/
__init__.py
cli.py
event.py
handler.py
listener.py
middleware.py
examples/
quickstart.py
tests/
test_event_system.py
Notes
- The package has no runtime dependencies
- The public API is exported from kevent/init.py
- The CLI entry point is
kevent = "kevent.cli:main" - MRO-based dispatch is O(n) where n is the depth of the event class hierarchy; for deeply nested events, consider flattening or using explicit event types
- By default, exceptions in listeners propagate; use
on_errorto implement custom error strategies (logging, recovery, etc.)
Event Hierarchy and Dispatch
EventHandler.publish() uses method resolution order (MRO) to dispatch events. If you register a listener for a base event class, it will receive all subclass instances:
class UserEvent(Event):
pass
class UserLoggedIn(UserEvent):
pass
def on_user_event(event: UserEvent) -> None:
print(f"user event: {type(event).__name__}")
handler = EventHandler()
handler.subscribe(listener(UserEvent)(on_user_event))
handler.publish(UserLoggedIn("alice")) # Matches UserEvent via MRO
Middleware and Flow Control
Middleware can observe events and optionally cancel propagation by returning None:
class ValidationMiddleware(Middleware):
def process(self, event: Event) -> Event | None:
if not is_valid(event):
return None # Prevent listeners from receiving this event
return event
handler = EventHandler()
handler.add_middleware(ValidationMiddleware())
handler.publish(event) # Listeners won't run if validation fails
Error Handling
Catch exceptions in listeners without losing other events:
def on_error(exc: Exception, event: Event, listener_obj) -> None:
print(f"Error in {listener_obj}: {exc}")
handler = EventHandler(on_error=on_error)
handler.subscribe(listener(Event)(on_event)) # If this raises, on_error is called
handler.publish(event) # Other listeners still execute
Monitoring Listeners
Check how many listeners are registered:
handler = EventHandler()
print(handler.handlers_count) # 0
handler.subscribe(listener(Event)(lambda e: None))
print(handler.handlers_count) # 1
Release files for kevent 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| kevent-1.0.0.tar.gz | 8.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kevent-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:16.6 kB
Release files / kevent-1.0.0.tar.gz
| Download URL | kevent-1.0.0.tar.gz |
|---|---|
| Size | 8.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e2aa6402d0b8eaa93d8ee569dd62161c3889773efeec9646fb6b4199135b7f61
|
|
BLAKE2b-256 checksum How to use checksums |
7ba3063471aefee6b299ffe276857de2b98fbfba0dac8f945b2a75c00dc556b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / kevent-1.0.0-py3-none-any.whl
| Download URL | kevent-1.0.0-py3-none-any.whl |
|---|---|
| Size | 7.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3a7c23c7d27b527ca30b47303d33e84cc6217647272ab7e6795fc9fbab74cdc9
|
|
BLAKE2b-256 checksum How to use checksums |
92e43d2c077185656297dfda8b25cc923afc565c9b43192c820e9e18b33dc6ee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|