Skip to main content

Typed event system for small Python applications

Project description

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

  • Event is the base class for application events
  • Listener binds one event class to one callback
  • listener() is a decorator for declarative listener registration
  • Middleware runs before listeners receive an event
  • EventHandler stores 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_error to 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kevent-1.0.0.tar.gz (8.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kevent-1.0.0-py3-none-any.whl (7.8 kB view details)

Uploaded Python 3

File details

Details for the file kevent-1.0.0.tar.gz.

File metadata

  • Download URL: kevent-1.0.0.tar.gz
  • Upload date:
  • Size: 8.7 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for kevent-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e2aa6402d0b8eaa93d8ee569dd62161c3889773efeec9646fb6b4199135b7f61
MD5 5f6e4a6fba546e3c6b2391048a72b01e
BLAKE2b-256 7ba3063471aefee6b299ffe276857de2b98fbfba0dac8f945b2a75c00dc556b5

See more details on using hashes here.

File details

Details for the file kevent-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: kevent-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 7.8 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for kevent-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3a7c23c7d27b527ca30b47303d33e84cc6217647272ab7e6795fc9fbab74cdc9
MD5 6d61690d50c5a183038b60aa59bcc7a2
BLAKE2b-256 92e43d2c077185656297dfda8b25cc923afc565c9b43192c820e9e18b33dc6ee

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page