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
Metadata
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 | Provenance | Actions |
|---|---|---|---|---|
| kevent-1.0.0.tar.gz | 8.7 kB | Without provenance | Details for kevent-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| kevent-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for kevent-1.0.0-py3-none-any.whl |
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}
|
Security for kevent 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.