Add your description here
Project description
Moduvent - Python Event-Driven Framework
A lightweight, modular event system for Python applications with plugin architecture support.
Features
🎯 Simple and intuitive event subscription and emission
🧩 Dynamic module loading system for extensibility
📝 Comprehensive logging with Loguru integration
🏗️ Class-based event handlers with metaclass support
🔧 Type annotations throughout for better development experience
Installation
pip install moduvent
Quick Start
Everything below can be imporrted from the moduvent package.
Define a custom event
We say an event holds data that is relevant to a certain type of event. For example, a UserLoggedIn event might hold the user ID and timestamp of the login.
class UserLoggedIn(Event):
def __init__(self, user_id, timestamp):
self.user_id = user_id
self.timestamp = timestamp
Subscribe your events
Once you finished defining your events, you can subscribe some functions (both bound methods and unbound functions) to them using the subscribe decorator for unbound functions and subscribe_classmethod for bound methods.
# Unbound function
@subscribe(UserLoggedIn)
def handle_user_login(event):
"""Once a UserLoggedIn event is emitted, this function will be called."""
# use your event data!
print(f"User {event.user_id} logged in at {event.timestamp}")
# Bound method
class UserManager(EventAwareBase):
@subscribe_classmethod(UserLoggedIn)
def on_user_login(self, event):
"""Once a UserLoggedIn event is emitted, this method will be called."""
# use your event data here!
print(f"UserManager noticed login: {event.user_id}")
The regirstration of a bound method is realized by inherting from the EventAwareBase class, which provides a metaclass that automatically registers the class method as an event handler when the class is instantiated.
Emit events
if __name__ == "__main__":
emit(UserLoggedIn(user_id=123, timestamp="2023-01-01 12:00:00"))
# or anywhere else in your code
Unsubscribe events
You can unsubscribe subscriptions in many ways:
# Unsubscribe a function from an event type
unsubscribe(handle_user_login, UserLoggedIn)
# or
unsubscribe(a_user_manager_instance.handle_user_login, UserLoggedIn)
# Unsubscribe all functions from an instance
unsubscribe_instance(a_user_manager_instance)
# Unsubscribe a function from all event types
remove_function(handle_user_login)
# Unsubscribe all functions from an event type
clear_event_type(UserLoggedIn)
Module System
Moduvent includes a dynamic module loader for plugin architecture:
from moduvent import discover_modules
# Load all modules from the 'modules' directory (default)
discover_modules()
# Or specify a custom directory
discover_modules("plugins")
This will try to load all modules in the specified directory and register their event handlers if possible.
API Reference
Core Classes
-
Event: Base class for all events -
EventManager: Central event system coordinator -
EventAwareBase: Base class for event-handling components -
ModuleLoader: Dynamic module loader
Decorators
-
subscribe(*event_types): Decorator for functions to subscribe to events -
subscribe(*event_types): Decorator for functions to subscribe to events -
subscribe_classmethod(*event_types): Decorator for class methods
Functions
-
emit(event): Emit an event to all subscribers -
discover_modules(modules_dir="modules"): Discover and load modules from a directory -
unsubscribe(self, func: Callable[[Event], None], event_type: Type[Event]): Unsubscribe a function from an event type -
unsubscribe_instance(self, instance: object): Unsubscribe all functions from an instance -
remove_function(self, func: Callable[[Event], None]): Unsubscribe a function from all event types -
clear_event_type(self, event_type: Type[Event]): Unsubscribe all functions from an event type
Module Structure
Modules should be placed in a directory (default: modules) with a structure similar as the following:
modules/
analytics/
__init__.py
events.py
...
auth/
__init__.py
...
notifications/
__init__.py
...
Configuration
Moduvent uses loguru for logging, which can be configured using the logger object.
from moduvent import logger
# Intercept standard logging
logger.add(
"moduvent.log",
rotation="10 MB",
retention="10 days",
level="DEBUG"
)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file moduvent-0.1.0.tar.gz.
File metadata
- Download URL: moduvent-0.1.0.tar.gz
- Upload date:
- Size: 6.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bd5fdaaa54246bdbb70cfd085a694c5e75ea0f1a2bb223fb6636330b47110b48
|
|
| MD5 |
b417bfd5da0b49e295419e5977f9b28c
|
|
| BLAKE2b-256 |
de6cc126db7256a822ac611a3b61a94e2e3ee25154030a31903b06c47a8e23e5
|
File details
Details for the file moduvent-0.1.0-py3-none-any.whl.
File metadata
- Download URL: moduvent-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1074778a6965fe4c42053c4f1166ae9347b0fc594d45aa363b4018dd0d347a77
|
|
| MD5 |
82480d6678e777aabe6ebaf3dd94ecf5
|
|
| BLAKE2b-256 |
ef5d9f20fdf49a7ef0b08af1eb8fe8455e3ae2375f21579ab6965f026863c393
|