Skip to main content

Lightweight notification package for custom subscribe-dispatch events

Project description

whine

Build Workflow License PyPI Version

Because every system time-to-time needs to whine about something

Introduction

whine is a very lightweight package for custom implementations of subscribing and dispatching event messages, using an observer-like pattern.

The whine.EventHandler provides the means to create event-subscribing and dispatching activities. It allows to separate the logic of responsability amongs the components, and bring them together.

Here is a breakdown of responsabilities, which are mentioned in the examples:

  • Dispatchers: provide the functionality of conveying a message of an event. Dispatch classes need to have a .emit_message method implemented, and their instances would be registered with the EventHandler.
  • Event functions: standalone functions, which compose your message text with any arguments (if needed). These functions would be used to subscribe to an EventHandler instance with an event name.
  • Event name: a value, used to represent the event, using a string (treat it as a constant).
  • Dispatch: an action when EventHandler.dispatch method is called with an event name - a message is then created using the event function, and dispatched using registered dispatchers.

Such approach separates the logic, between how an event notification is conveyed, how a message is composed, and a way how an event message is emitted. If any means of these components are changed, they would not need to be altered in one place, keeping the rest of the setup working as intended.

Use Cases

  • Use a notification platform for dispatching a message (eg: Telegram, Slack, e-mail, logging, etc.)
  • Create a function, that formats a message content (eg: failed scheduled task, new user registration). Since the functions are standalone, have the freedom of passing any parameters, those help to format the message value (eg: class instances).
  • Dispatch an event notification in a convenient place (eg: in an except block, post-action signals)

Installation

Requires Python 3.8+

pip install whine

Quick Start

from whine import EventHandler

events = EventHandler()

# Create a dispatcher class for processing messages
# Implement a `.emit_message` method in that class
# Use a decorator to automatically add to dispatchers
# There can be multiple dispatchers added to an EventHandler instance
@events.register
class SimpleDispatcher:
    def emit_message(self, message: str) -> None:
        print(message)

# Create a function, for processing a message, that returns a string
# The function can take any arguments it may need to form an event message
# Decorate an event function with the `.subscribe`, and provide an event name ('SIMPLE')
@events.subscribe("SIMPLE")
def simple_event(value) -> str:
    return f"Simple event for {value}"

# Trigger the event function, and pass any positional or keyword arguments
events.dispatch("SIMPLE", "my value")

# An output from the event function is then emitted by all registered dispatchers

More Examples

Logging and Telegram whiners

This example demonstrates an event handler, that uses Telegram and Logging dispatchers. A function is created and subscribed to, so a pre-defined message is created from a User instance. An event is dispatched when a user is created, so the message is emited to all dispatchers.

import os
import logging
import telebot
from whine import EventHandler
from dataclasses import dataclass

events = EventHandler()

@dataclass
class User:
    name: str

@events.register(os.environ["TELEGRAM_CHAT_ID"], os.environ["TELEGRAM_TOKEN"])
class TelegramDispatcher:
    def __init__(self, chat_id: int, token: str):
        self.chat_id = chat_id
        self.bot = telebot.TeleBot(token)

    def emit_message(self, message: str) -> None:
        self.bot.send_message(self.chat_id, message)

class LoggerDispatcher:
    def __init__(self, level: int = logging.WARNING):
        self.level = level
        self.logger = logging.getLogger(__name__)

    def emit_message(self, message: str) -> None:
        self.logger.log(self.level, message)

# @events.register  # can be used as a naked decorator (when init takes no args)
# Alternatively, create a dispatcher instance and add to the EventHandler
events.add_dispatcher(LoggerDispatcher())

@events.subscribe("NEW_USER")
def event_new_user(user: User) -> str:
    return f"A new user was created {user.name}, welcome them on the platform!"

# Explicitly added subscribtion to an event with a static lambda function
events.add_subscriber("BACKUP_COMPLETED", lambda: "The weekly backup was completed!")

def create_new_user(name: str) -> User:
    """User creation function, also dispatches an event"""
    user = User(name=name)
    events.dispatch("NEW_USER", user)  # an event is dispatched with a position arg
    return user

def weekly_backup():
    """Some function that performs backups"""
    ...  # some implementation
    events.dispatch("BACKUP_COMPLETED")  # an event is dispatched (no args)

Development

Install development dependencies:

# pip install pipenv
pipenv install --dev

Build docs:

pdoc --html --force -o docs whine

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

whine-0.1.0.tar.gz (6.1 kB view details)

Uploaded Source

Built Distribution

whine-0.1.0-py3-none-any.whl (5.6 kB view details)

Uploaded Python 3

File details

Details for the file whine-0.1.0.tar.gz.

File metadata

  • Download URL: whine-0.1.0.tar.gz
  • Upload date:
  • Size: 6.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.9.13

File hashes

Hashes for whine-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5a9aa14871722bdb2c3a38d532fba855b3e4c1fe16ba0779e7e92c8d726deee2
MD5 f3d49c9a6980ea384f5bdb61d711c59c
BLAKE2b-256 832209eb6a171b7e75f23c873143732575156ebe07c8ffff1458d007b1c33f37

See more details on using hashes here.

File details

Details for the file whine-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: whine-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 5.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.9.13

File hashes

Hashes for whine-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 22e410a3a2273c3c203005d124249d15af33b261c0aaf4b8c7f98d80e0c57da4
MD5 2fc14a9ded80d459f6dd734c877536da
BLAKE2b-256 271c82343dc0225022f4f5f30061a9bed7fe85c50fc3bcdab89bbeb057fdf827

See more details on using hashes here.

Supported by

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