PyListenerTool
A lightweight event listener system for Python classes that auto-generates documentation.
📦 Installation
pip install PyListenerTool
📜 Changelog
See CHANGELOG.md
✨ Features
- Decorator-based API: Use
@Listenerto transform any class into an event-driven system - Flexible Event Handling: Support both synchronous and asynchronous event handlers
- One-time Listeners: Register listeners that trigger only once
- Error Handling: Custom error callbacks for each listener
- Auto-documentation: Generate HTML or Markdown documentation for all events
- Thread-safe Async Support: Async handlers run in separate threads
- Event Discovery: Analyze classes to extract event information
🚀 QuickStart
Basic Usage
from PyListenerTool import Listener, extract_listeners
@Listener
class ChatRoom:
def __init__(self, name):
self.name = name
self._addListenerDoc("message", "Triggered when a message is received", "username: str", "message: str")
self._addListenerDoc("user_joined", "Triggered when a user joins the room", "username: str")
def send_message(self, username, message):
self._call("message", username, message)
def user_join(self, username):
self._call("user_joined", username)
# Create an instance
room = ChatRoom("Python Developers")
# Add listeners
@room.on("message")
def handle_message(username, message):
print(f"[{room.name}] {username}: {message}")
@room.on("user_joined", once=True)
def welcome_user(username):
print(f"Welcome {username} to {room.name}!")
# Trigger events
room.user_join("Alice")
room.send_message("Alice", "Hello World!")
room.send_message("Bob", "Hi everyone!")
Advanced Features
@Listener
class DataProcessor:
def __init__(self):
self._addListenerDoc("data_received", "Process incoming data", "data: dict", "timestamp: float")
self._addListenerDoc("error", "Handle processing errors", "error: Exception")
def process(self, data):
try:
# Process data
self._call("data_received", data, time.time())
except Exception as e:
self._call("error", e)
processor = DataProcessor()
# Async listener
@processor.on("data_received", is_async=True)
def handle_data_async(data, timestamp):
time.sleep(0.1)
print(f"Async processing: {data} at {timestamp}")
# Error handler
def log_error(error):
print(f"Error occurred: {error}")
@processor.on("error", on_error=log_error)
def handle_error(error):
# This will trigger log_error if an exception occurs
raise ValueError("Simulated error")
# One-time listener
@processor.on("data_received", once=True)
def initial_data_handler(data, timestamp):
print(f"First data received: {data}")
Documentation Generation
@Listener
class MyComponent:
def __init__(self):
self._addListenerDoc("start", "Component started", "config: dict")
self._addListenerDoc("stop", "Component stopped")
self._addListenerDoc("data", "Data processed", "data: list", "metadata: dict")
component = MyComponent()
# Generate HTML documentation
html_docs = component.buildListenerDocs("html")
with open("docs.html", "w", encoding="utf-8") as f:
f.write(html_docs)
# Generate Markdown documentation
md_docs = component.buildListenerDocs("markdown")
print(md_docs)
Event Discovery
# Analyze a class to discover all events
result = extract_listeners(ChatRoom)
print(f"Has @Listener decorator: {result['has_listener_decorator']}")
print(f"Events found: {result['events']}")
📖 API Reference
@Listener Decorator
Transforms a class into an event listener system. Adds the following methods:
addListener(event, func, is_async=False, once=False, on_error=None)
Register a listener for an event.
Parameters:
event(str): Event namefunc(callable): Callback functionis_async(bool): Whether the function is asynconce(bool): Whether to trigger only onceon_error(callable): Error callback function
_call(event, *args, **kwargs)
Trigger an event with arguments.
on(event_name, is_async=False, once=False, on_error=None)
Decorator version of addListener.
_addListenerDoc(event, desc, *cpd)
Add documentation for an event.
Parameters:
event(str): Event namedesc(str): Event description*cpd(str): Parameter descriptions
buildListenerDocs(model="html")
Generate documentation in HTML or Markdown format.
_buildListenerDocs_html() and _buildListenerDocs_md()
Internal methods for documentation generation.
extract_listeners(cls)
Analyze a class to extract listener information.
Returns: Dict with keys:
events: List of event names founderror: Any error during extraction
🔧 Requirements
- Python 3.7+
- No external dependencies
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin main) - Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🐛 Bug Reports and Feature Requests
If you encounter any bugs or have feature requests, please open an issue on the GitHub repository.
🙏 Acknowledgments
- Thanks to all contributors who have helped shape this project
- Inspired by event-driven patterns in various frameworks
🌟 Support
If you find this package useful, please consider giving it a star on GitHub!
Release files for PyListenerTool 26.3.10
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pylistenertool-26.3.10.tar.gz | 5.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pylistenertool-26.3.10-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 12.4 kB
Release files / pylistenertool-26.3.10.tar.gz
| Download URL | pylistenertool-26.3.10.tar.gz |
|---|---|
| Size | 5.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4ef8437626a4c2f80a07f554175452f1d30b6d182de3792a85954622539b164a
|
|
BLAKE2b-256 checksum How to use checksums |
0e745feebf0798435618f2a9857883ea66e1a6ea4cef399a52920f55c36587aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / pylistenertool-26.3.10-py3-none-any.whl
| Download URL | pylistenertool-26.3.10-py3-none-any.whl |
|---|---|
| Size | 6.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d9098c83258a0c7ddb29b492c2e93de2c36fb6607c1bd352a23bef3ef0c01307
|
|
BLAKE2b-256 checksum How to use checksums |
cb7c04bd41c337b83307fe128011f4aa3a99b59b1891f4506e37cf8a0d05459c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|