-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3870068
commit 0509cec
Showing
8 changed files
with
437 additions
and
207 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions | ||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions | ||
|
||
name: Python package and publish | ||
|
||
on: | ||
push: | ||
branches: [ master ] | ||
pull_request: | ||
branches: [ master ] | ||
release: | ||
types: # This configuration does not affect the page_build event above | ||
- created | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
python-version: [3.6] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.x' | ||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install flake8 pytest | ||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi | ||
- name: Lint with flake8 | ||
run: | | ||
# stop the build if there are Python syntax errors or undefined names | ||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics | ||
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide | ||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics | ||
- name: Build and publish | ||
env: | ||
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} | ||
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} | ||
run: | | ||
pip install setuptools wheel twine | ||
python setup.py sdist | ||
twine upload dist/* |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,102 +1,148 @@ | ||
## eventhandler | ||
#### A simple but effective event handler, based in calbacks, written in pure python 3. | ||
# eventhandler | ||
|
||
##### Is a simple and effective event handler class, based in callbacks for python 3 | ||
|
||
### Build Status: | ||
|
||
[![Build Status](https://travis-ci.org/davidvicenteranz/eventhandler.svg?branch=master)](https://travis-ci.org/davidvicenteranz/eventhandler) | ||
[![Coverage Status](https://coveralls.io/repos/github/davidvicenteranz/eventhandler/badge.svg)](https://coveralls.io/github/davidvicenteranz/eventhandler) | ||
[![PyPI version](https://badge.fury.io/py/eventhandler.svg)](https://badge.fury.io/py/eventhandler) | ||
[![Python package and publish](https://github.com/davidvicenteranz/eventhandler/workflows/Python%20package%20and%20publish/badge.svg?branch=master)](https://pypi.org/project/eventhandler/) | ||
|
||
**PyPI:** [Package Information](https://pypi.python.org/pypi/eventhandler) | ||
|
||
|
||
## Quick start | ||
Install the package | ||
###Install the package | ||
```shell | ||
$ pip install eventhandler | ||
``` | ||
|
||
|
||
## Usage example | ||
## Usage or how to implement it | ||
Lets see a simple example of a chat room controlled by a bot using event calls. | ||
```python | ||
from eventhandler import EventHandler | ||
|
||
class ChatRoom: | ||
"""Simulates a chatroom environment with event handler implementation.""" | ||
messages = [] # Holds user messages | ||
users = {'bot':[]} # Holds | ||
|
||
def __init__(self): | ||
"""Initialize de chat room.""" | ||
# Define posible events | ||
self.event_handler = EventHandler('on-newuser', 'on-message') | ||
# Bind callback function to events | ||
self.event_handler.bind('on-newuser', self.on_newuser_join) | ||
self.event_handler.bind('on-message', self.on_message) | ||
|
||
def user_list(self): | ||
"""Return a list of users.""" | ||
return [user for user in self.users.keys() if user != 'bot'] | ||
class ChatRoom: | ||
"""Simulates a chatroom environment with event handler implementation. | ||
def on_newuser_join(self, user): | ||
"""Print a message when a user join the chat room.""" | ||
print(f'{user} has joined the chat.') | ||
This is just a documented sample without pretensions. It is not a real class implementation. | ||
""" | ||
|
||
def on_message(self, user, msg): | ||
"""Print the user message""" | ||
def __init__(self): | ||
"""Initialize the chat room.""" | ||
self.__messages = [] # Stores users messages | ||
self.__users = {'bot': []} # Stores a dictionary with registered usernames | ||
|
||
# Define the event handler and make it public outside the class to let externals subscriptions to events. | ||
self.event_handler = EventHandler('onNewuser', 'onMessage') # Note that events names are cased sensitive. | ||
|
||
# Lets link some internal class methods to those events as callbacks. | ||
# You can set any number of unique events and any number of unique callbacks to fire per event, | ||
# Limits are available resources. | ||
self.event_handler.register_event('onNewUser') | ||
self.event_handler.register_event('onMessage') | ||
self.event_handler.link(self.__on_newuser_join, 'onNewuser') | ||
self.event_handler.link(self.__on_message, 'onMessage') | ||
|
||
# Now lets define this two methods to dispatch the events | ||
# Note this methods are not accesible outside class instance | ||
# This calbback will be called when onNewUser event happens | ||
def __on_newuser_join(self, user): | ||
"""Shout in the output telling new user has joined chat room, when onNewuser event happens.""" | ||
print(f'** ChatRoom info ** user {user} has joined the chat ** {len(self.user_list())} user/s **') | ||
|
||
# This callback will be called when onMessage event happens | ||
def __on_message(self, user, msg): | ||
"""Print the user message in the output, when onMessage event happens.""" | ||
print(f'{user} says:\t {msg}') | ||
|
||
def say(self, user, msg): | ||
"""Send a messega to the chat room.""" | ||
if not user in self.users: | ||
self.users[user] = [] | ||
self.event_handler.fire('on-newuser', user) | ||
|
||
# Now let's define the public methods of the chatroom to be used outside the class | ||
def user_list(self): | ||
"""Return a list of not bot users.""" | ||
return [user for user in self.__users.keys() if user != 'bot'] | ||
|
||
def say(self, user, msg=None): | ||
"""Let user (and bots) send a message to the chat room.""" | ||
if not user in self.__users: | ||
# if user is not registered fire onNewuser event and recibe it inside the class. | ||
self.__users[user] = [] | ||
self.event_handler.fire('onNewuser', user) | ||
if not msg: | ||
return | ||
if msg != '': | ||
self.messages.append((user, msg)) | ||
self.event_handler.fire('on-message', user, msg) | ||
# Enqueue the message and fire onMessage event to be received internally by __on_message method. | ||
self.__messages.append((user, msg)) | ||
self.event_handler.fire('onMessage', user, msg) | ||
|
||
|
||
class ChatBot: | ||
"""A basic bot chat that's can operate in a chatroom.""" | ||
|
||
def __init__(self, chatroom: ChatRoom, name: str = 'bot'): | ||
self.chatroom = chatroom | ||
self.name = name | ||
|
||
# Subscribe to external ChatRoom class events | ||
chatroom.event_handler.link(self.saludate_new_user, 'onNewuser') | ||
chatroom.event_handler.link(self.read_user_message, 'onMessage') | ||
|
||
# When chatroom fires the onNewUser event our bot will saludate. | ||
def saludate_new_user(self, user): | ||
"""Bot saludates the user.""" | ||
chat.say('bot', f'Hello {user}, welcome to the chat room.') | ||
|
||
# When chatroom fires the onNewMessage event process it and broadcast some output if needed. | ||
def read_user_message(self, user, msg): | ||
"""Read user messages and act in consequece.""" | ||
if user == 'bot': | ||
return | ||
|
||
# Intercept an answerable question | ||
if msg == f'Hey {self.name}, are there anyone here?': | ||
if len(self.chatroom.user_list()) < 1: | ||
self.chatroom.say(self.name, f'Nope {user}. Just you and me.') | ||
elif len(self.chatroom.user_list()) == 2: | ||
self.chatroom.say(self.name, f'Yes {user}. ' | ||
f'there are {len(self.chatroom.user_list()) - 1} non bots users in the room, you, and me.') | ||
else: | ||
self.chatroom.say(self.name, f'Yes {user}. ' | ||
f'there are {len(self.chatroom.user_list()) - 2} non bots users in the room, you, and me.') | ||
return | ||
|
||
# Create the chatroom | ||
chat = ChatRoom() | ||
|
||
# This is a external callback to bind in the chatroom event habdler | ||
def saludate_new_user(user): | ||
"""Bot saludates the user.""" | ||
chat.say('bot', f'Hello {user}, welcome to the chat room.') | ||
# Python program starts execution here | ||
if __name__ == '__main__': | ||
# Create the chatroom | ||
chat = ChatRoom() | ||
|
||
# This is a external callback to bind in the chatroom event habdler | ||
def response_to_user(user, msg): | ||
"""Bot responses to user.""" | ||
if user=='bot': | ||
return | ||
if msg == 'Hey bot, are there anyone here?': | ||
if len(chat.users.keys()) == 2: | ||
chat.say('bot', f'Nope {user}. Just you and me.') | ||
else: | ||
chat.say('bot', f'Yes {user}. there are {len(chat.users.keys())-1} users in the room.') | ||
|
||
# Bind the external callbacks | ||
chat.event_handler.bind('on-newuser', saludate_new_user) | ||
chat.event_handler.bind('on-message', response_to_user) | ||
|
||
# Chat simulation | ||
chat.say('sergio', 'Hello World!') | ||
chat.say('sergio', 'Hey bot, are there anyone here?') | ||
chat.say('david', 'Hello everybody!') | ||
chat.say('david', 'Hey bot, are there anyone here?') | ||
chat.say('sergio', 'Hi david!') | ||
# Now bot can control users and messages of the chat | ||
bot = ChatBot(chat) | ||
|
||
# Now the chat simulation. The first user interaction will send a message onNewuser event will be fired and | ||
# managed by the bot. All messages (onMessage event) will be reached by the bot. | ||
chat.say('sergio', 'Hello World!') | ||
chat.say('sergio', 'Hey bot, are there anyone here?') | ||
chat.say('david', 'Hello everybody!') | ||
chat.say('david', 'Hey bot, are there anyone here?') | ||
chat.say('sergio', 'Hi david!') | ||
chat.say('kate') | ||
chat.say('kate', 'Hey bot, are there anyone here?') | ||
``` | ||
**The avobe code must produce and output this:** | ||
```text | ||
sergio has joined the chat. | ||
** ChatRoom info ** user sergio has joined the chat ** 1 user/s ** | ||
bot says: Hello sergio, welcome to the chat room. | ||
sergio says: Hello World! | ||
sergio says: Hey bot, are there anyone here? | ||
bot says: Nope sergio. Just you and me. | ||
david has joined the chat. | ||
bot says: Yes sergio. there are -1 non bots users in the room, you, and me. | ||
** ChatRoom info ** user david has joined the chat ** 2 user/s ** | ||
bot says: Hello david, welcome to the chat room. | ||
david says: Hello everybody! | ||
david says: Hey bot, are there anyone here? | ||
bot says: Yes david. there are 2 users in the room. | ||
bot says: Yes david. there are 1 non bots users in the room, you, and me. | ||
sergio says: Hi david! | ||
** ChatRoom info ** user kate has joined the chat ** 3 user/s ** | ||
bot says: Hello kate, welcome to the chat room. | ||
kate says: Hey bot, are there anyone here? | ||
bot says: Yes kate. there are 1 non bots users in the room, you, and me. | ||
``` |
Oops, something went wrong.