Pythonic implementations of Command and Event Buses
Zero-dependencies, flexible implementation of Command Bus. Python 3.6+ only
Basic usage of CommandBus
from typing import List
from pybuses import CommandBus
# Firstly, create command class
class MakeSandwich:
def __init__(self, ingredients: List[str]) -> None:
self.ingredients = ingredients
# Then create callable responsible for handling command.
# It must accept only one argument and is required to have type annotation for it.
def sandwich_maker(command: MakeSandwich) -> None:
print(f'Making sandwich with {command.ingredients}!')
# finally, register the handler by subscribing
command_bus = CommandBus()
command_bus.subscribe(sandwich_maker)
command_bus.handle(MakeSandwich(['cheese', 'ham']))
Middlewares
Middlewares are lightweight plugins that let us inject custom logic before and after given command was handled.
Context managers are for now the only supported way of defining middlewares. They simplify exception handling and specifying whether middleware logic should be executed before or after handling event.
import contextlib
from typing import (
Any,
Generator,
)
@contextlib.contextmanager
def example_middleware(command: Any) -> Generator:
print(f'Before handling {command}')
yield
print(f'After handling {command}')
command_bus = CommandBus([example_middleware])
command_bus.subscribe(sandwich_maker)
command_bus.handle(MakeSandwich(['cheese', 'ham']))
Basic usage of EventBus
from decimal import Decimal
from pybuses import EventBus
# Create event
class PaymentMade:
amount: Decimal
who: int
def __init__(self, amount: Decimal, who: int) -> None:
self.amount = amount
self.who = who
def handler(payment_made: PaymentMade) -> None:
print(f'Oh, cool! {payment_made.who} paid {payment_made.amount / 100}$!')
event_bus = EventBus()
event_bus.subscribe(handler)
event_bus.post(PaymentMade(Decimal('10.99'), 123))
Similarities & differences between Event- and CommandBus
EventBus can have 0 or many handlers subscribed to every event, while CommandBus must have exactly one handler for each command.
CommandBus supports middlewares while EventBus does not.
data classes compatible
Using dataclasses for building commands/events is supported
from dataclasses import dataclass
from typing import List
from pybuses import CommandBus
@dataclass
class MakeSandwich:
ingredients: List[str]
def handler(command: MakeSandwich) -> None:
print(f'dataclass-based command: {command}')
command_bus = CommandBus()
command_bus.subscribe(handler)
command_bus.handle(MakeSandwich(['ham', 'butter']))
attrs compatible
Using attrs for building commands/events is supported
import attr
from pybuses import CommandBus
@attr.s(frozen=True)
class Example:
number: int = attr.ib()
name: str = attr.ib()
def example_handler(command: Example) -> None:
print(f'Inside handler of {type(command)} - got {command}!')
command_bus = CommandBus()
command_bus.subscribe(example_handler)
command_bus.handle(Example(number=1, name='Sebastian'))
Metadata
Release files for pybuses 1.1.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 |
|---|---|---|---|---|
| pybuses-1.1.0.tar.gz | 4.5 kB | Without provenance | Details for pybuses-1.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pybuses-1.1.0-py3-none-any.whl | Python 3 | none | any | Details for pybuses-1.1.0-py3-none-any.whl |
Total release size: 11.5 kB
Release files / pybuses-1.1.0.tar.gz
| Download URL | pybuses-1.1.0.tar.gz |
|---|---|
| Size | 4.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ef69ba58be97d0747b47c29bdcb06621909fe00ae778b5da87fc995a09348e7a
|
|
BLAKE2b-256 checksum How to use checksums |
e19523f0e6b0c8f300eb8a6e26ea6b9921c5bcb78a2507cd08774788a220b1c0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/1.12.1 pkginfo/1.4.2 requests/2.18.4 setuptools/40.6.3 requests-toolbelt/0.8.0 tqdm/4.29.0 CPython/3.6.4
|
Release files / pybuses-1.1.0-py3-none-any.whl
| Download URL | pybuses-1.1.0-py3-none-any.whl |
|---|---|
| Size | 7.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3c28d261c69ece867fbb4af3cdb6a7ffb76425b6c8c0f2dc4aa7fdec78147dfd
|
|
BLAKE2b-256 checksum How to use checksums |
984b5dc1e0b60d2806c7fcdf108f852a09dcef03316d100c295a8087d7665b2f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/1.12.1 pkginfo/1.4.2 requests/2.18.4 setuptools/40.6.3 requests-toolbelt/0.8.0 tqdm/4.29.0 CPython/3.6.4
|
Security for pybuses 1.1.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.