Skip to main content
Event patterns are shared across both APIs:
  • bus.on(pattern, handler) for subscriptions
  • bus.find(pattern, ...) for history/future lookup
Both accept the same pattern forms:
  • event class
  • string event type name
  • '*' wildcard (match everything)

Supported pattern forms

PatternMatchesBest for
Event class (UserActionEvent)One concrete event typeStrong typing end-to-end
String ('UserActionEvent')Events by type nameDynamic routing/config-driven keys
'*'All event typesGlobal observers, logging, bridges

.on(...) and .find(...) use the same pattern model

Use whichever operation you need, with the same pattern key:
  • subscribe: bus.on(UserActionEvent, handler)
  • find by class: await bus.find(UserActionEvent)
  • find by string: await bus.find('UserActionEvent')
  • wildcard subscribe/find: bus.on('*', ...), await bus.find('*', ...)

Examples

from typing import Any
from bubus import BaseEvent, EventBus

class UserActionEvent(BaseEvent[str]):
    action: str

bus = EventBus('AppBus')

async def on_typed(event: UserActionEvent) -> str:
    # event is strongly typed here
    return f'action:{event.action}'

def on_by_name(event: BaseEvent[Any]) -> None:
    # string patterns are looser; payload fields are not statically known
    print('by-name', event.event_type, getattr(event, 'action', None))
    # by-name UserActionEvent click

def on_any(event: BaseEvent[Any]) -> None:
    print('wildcard', event.event_type)
    # wildcard UserActionEvent

bus.on(UserActionEvent, on_typed)
bus.on('UserActionEvent', on_by_name)
bus.on('*', on_any)

await bus.emit(UserActionEvent(action='click')).event_result()

typed_match = await bus.find(UserActionEvent)          # UserActionEvent | None
named_match = await bus.find('UserActionEvent')        # BaseEvent[Any] | None
wildcard_match = await bus.find('*', future=5)         # BaseEvent[Any] | None

Why event classes are preferred for typing

Event classes preserve the most useful static typing:
  • handler input shape is specific (payload fields are known)
  • event result typing stays aligned with event_result_type / generic result type
  • .find(EventClass) returns the specific event type
String keys and '*' are intentionally looser:
  • Python: treat as BaseEvent[Any]
  • TypeScript: typed as base BaseEvent/unknown-oriented handler return checks
Use string/wildcard patterns when you need dynamic behavior. Use classes whenever you want strict payload/result type hints through handlers and lookups.