Skip to content

Commit

Permalink
feat(examples): add pydantic and attrs examples
Browse files Browse the repository at this point in the history
  • Loading branch information
mickare committed Aug 16, 2024
1 parent 1ead54f commit 4e39e6e
Show file tree
Hide file tree
Showing 5 changed files with 361 additions and 34 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Feature overview:
- **Asynchronous** - Full support for asynchronous event handlers and context managers.
- **Priority Ordering** - Control the order in which event handlers are called.
- **Monitoring** - Use context managers to monitor event processing.
- **Compatible** - Works with almost anything, use: [dataclasses](https://docs.python.org/3/library/dataclasses.html), [Pydantic](examples/support_pydantic.py) or [attrs](examples/support_attrs.py).

```python
import asyncio
Expand Down
84 changes: 84 additions & 0 deletions examples/support_attrs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Copyright 2024 Michael Käser
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

# pylint: disable=duplicate-code
"""
Example of receiving events defined with attrs and handling with eventlib-py library.
See more: https://pypi.org/project/attrs/
Requirements:
- attrs
"""
from datetime import datetime
from typing import Iterator, Literal

from attrs import define

from eventlib import BaseEvent, emit, subscribe


@define
class ItemEvent(BaseEvent):
"""A generic item event."""

type: str
timestamp: datetime


@define
class CreatedItemEvent(ItemEvent):
"""Example event for a created item."""

type: Literal["created"]
name: str
value: int


@define
class DeletedItemEvent(ItemEvent):
"""Example event for a deleted item."""

type: Literal["deleted"]
name: str


@subscribe()
def on_created(event: CreatedItemEvent):
"""Handle created events"""
print("on_created:", repr(event))


@subscribe()
def on_deleted(event: DeletedItemEvent):
"""Handle deleted events"""
print("on_deleted:", repr(event))


EXAMPLE_EVENTS: list[dict] = [
{"type": "created", "timestamp": "2024-08-16T20:00:00", "name": "event_1", "value": 1},
{"type": "created", "timestamp": "2024-08-16T20:01:00", "name": "event_2", "value": 2},
{"type": "deleted", "timestamp": "2024-08-16T20:02:00", "name": "event_1"},
]
AnyEvent = CreatedItemEvent | DeletedItemEvent


def receive() -> Iterator[AnyEvent]:
"""Dummy receive method. This could be a Kafka, ServiceBus, RabbitMQ, or any other event receiver."""
for raw in EXAMPLE_EVENTS:
match raw["type"]:
case "created":
yield CreatedItemEvent(**raw)
case "deleted":
yield DeletedItemEvent(**raw)
case _:
raise RuntimeError("unknown event")


def example_attrs():
"""Example to an event using attrs and the eventlib-py library."""
for event in receive():
emit(event)


if __name__ == "__main__":
example_attrs()
76 changes: 76 additions & 0 deletions examples/support_pydantic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Copyright 2024 Michael Käser
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

# pylint: disable=duplicate-code
"""
Example of receiving events, validating them with Pydantic and handling with eventlib-py library.
See more: https://pypi.org/project/pydantic/
Requirements:
- pydantic
"""
from datetime import datetime
from typing import Annotated, Iterator, Literal

from pydantic import BaseModel, Field, TypeAdapter

from eventlib import BaseEvent, emit, subscribe


class ItemEvent(BaseEvent, BaseModel):
"""A generic item event."""

type: str
timestamp: datetime


class CreatedItemEvent(ItemEvent):
"""Example event for a created item."""

type: Literal["created"]
name: str
value: int


class DeletedItemEvent(ItemEvent):
"""Example event for a deleted item."""

type: Literal["deleted"]
name: str


@subscribe()
def on_created(event: CreatedItemEvent):
"""Handle created events"""
print("on_created:", repr(event))


@subscribe()
def on_deleted(event: DeletedItemEvent):
"""Handle deleted events"""
print("on_deleted:", repr(event))


EXAMPLE_EVENTS: list[dict] = [
{"type": "created", "timestamp": "2024-08-16T20:00:00", "name": "event_1", "value": 1},
{"type": "created", "timestamp": "2024-08-16T20:01:00", "name": "event_2", "value": 2},
{"type": "deleted", "timestamp": "2024-08-16T20:02:00", "name": "event_1"},
]
AnyEvent = Annotated[CreatedItemEvent | DeletedItemEvent, Field(discriminator="type")]
AnyEventAdapter: TypeAdapter[AnyEvent] = TypeAdapter(AnyEvent)


def receive() -> Iterator[AnyEvent]:
"""Dummy receive method. This could be a Kafka, ServiceBus, RabbitMQ, or any other event receiver."""
for raw in EXAMPLE_EVENTS:
yield AnyEventAdapter.validate_python(raw)


def example_pydantic():
"""Example to validate, parse and emit an event using pydantic and the eventlib-py library."""
for event in receive():
emit(event)


if __name__ == "__main__":
example_pydantic()
Loading

0 comments on commit 4e39e6e

Please sign in to comment.