Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
version: 2
jobs:
build:
docker:
- image: circleci/python:3.6.1

working_directory: ~/workspace

steps:
- checkout

- restore_cache:
keys:
- v1-dependencies-{{ checksum "requirements.txt" }}
- v1-dependencies-

- run:
name: install dependencies
command: |
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
pip install -r test-requirements.txt

- save_cache:
paths:
- ./venv
key: v1-dependencies-{{ checksum "requirements.txt" }}

- run:
name: run tests
command: |
. venv/bin/activate
pytest

- run:
name: run linters
command: |
. venv/bin/activate
flake8 --statistics confobo
pylint --rcfile=.pylintrc confobo
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@
__pycache__/
.cache/
venv/
secret.py
23 changes: 23 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[MESSAGES CONTROL]
disable=
missing-docstring,
too-few-public-methods

[REPORTS]
reports=no
score=yes

[FORMAT]
expected-line-ending-format=LF
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
indent-after-paren=4
indent-string=' '

[VARIABLES]
init-import=no

[CLASSES]
valid-classmethod-first-arg=cls

[IMPORTS]
allow-wildcard-with-all=no
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bot: python3 main.py
17 changes: 11 additions & 6 deletions confobo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
from functools import partial

import telepot
from telepot.loop import MessageLoop
from functools import partial

from .command.handlers import on_chat_message, on_callback_query
from .secret import API_KEY
from confobo.command.handlers import on_chat_message, on_callback_query
from confobo.secret import API_KEY

bot = telepot.Bot(API_KEY)

loop = MessageLoop(bot, {'chat': partial(on_chat_message, bot=bot),
'callback_query': partial(on_callback_query, bot=bot)})
def get_message_loop():
bot = telepot.Bot(API_KEY)
loop = MessageLoop(bot, {
'chat': partial(on_chat_message, bot=bot),
'callback_query': partial(on_callback_query, bot=bot)
})

return loop
2 changes: 0 additions & 2 deletions confobo/command/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
from .decorators import command, pass_user_data, bindings
from .execution import execute_command
4 changes: 2 additions & 2 deletions confobo/command/decorators.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .model import Command
from confobo.command.model import Command

bindings = {}

Expand All @@ -18,4 +18,4 @@ def wrapper(*args, **kwargs):
r = c(*args, **kwargs)
return r

return wrapper
return wrapper
11 changes: 6 additions & 5 deletions confobo/command/errors.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
from .model import Command
from confobo.command.model import Command


class NoSuchCommandError(Exception):

message = 'Sorry, didn\'t get that. Command \'{cmd_text}\' is not something I know of.' \
' Use /help to list available commands.'
_message = 'Sorry, didn\'t get that. Command "{cmd_text}" is not ' \
'something I know of. Use /help to list available commands.'

def __init__(self, cmd_text: str):
self.cmd_text = cmd_text

def __str__(self):
return self.message.format(cmd_text=self.cmd_text)
return self._message.format(cmd_text=self.cmd_text)

def __repr__(self):
return str(self)


class WrongArgsNumberError(Exception):

message = 'Sorry, you passed a wrong number of arguments to {cmd}. See /help for reference.'
_message = 'Sorry, you passed a wrong number of arguments to {cmd}. ' \
'See /help for reference.'

def __init__(self, cmd: Command, n: int):
self.cmd = cmd
Expand Down
4 changes: 2 additions & 2 deletions confobo/command/execution.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .errors import NoSuchCommandError, WrongArgsNumberError
from .decorators import bindings
from confobo.command.decorators import bindings
from confobo.command.errors import NoSuchCommandError, WrongArgsNumberError
from confobo.config import SEPARATOR


Expand Down
4 changes: 2 additions & 2 deletions confobo/command/handlers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from telepot import glance

from .execution import execute_command
from .errors import NoSuchCommandError, WrongArgsNumberError
from confobo.command.errors import NoSuchCommandError, WrongArgsNumberError
from confobo.command.execution import execute_command


def on_chat_message(msg, bot):
Expand Down
9 changes: 6 additions & 3 deletions confobo/command/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ def __init__(self, f, text: str, desc: str = None):
self.desc = desc
sig = inspect.signature(f)
self.max_args = len(sig.parameters)
self.min_args = len([p for p in sig.parameters.values() if p.default is inspect._empty])
self.min_args = len([p for p in sig.parameters.values()
if p.default is inspect._empty])
self.args = list(sig.parameters.keys())
self._needs_user_data = False

Expand All @@ -19,7 +20,8 @@ def info(self):
if sep != ' ':
sep += ' '
args = ' [{}]'.format(sep.join(self.args)) if self.args else ''
return '{cmd}{args}: {desc}'.format(cmd=self.text, args=args, desc=self.desc)
command = '{cmd}{args}: {desc}'
return command.format(cmd=self.text, args=args, desc=self.desc)

@property
def needs_user_data(self):
Expand All @@ -30,7 +32,8 @@ def needs_user_data(self, value: bool):
if not value:
raise NotImplemented()
if 'user_data' not in self.args:
raise TypeError('{}() must take a parameter named \'user_data\''.format(self.f.__name__))
error_message = '{}() must take a parameter named \'user_data\''
raise TypeError(error_message.format(self.f.__name__))
self.max_args -= 1
self.min_args -= 1
self.args.remove('user_data')
Expand Down
1 change: 0 additions & 1 deletion confobo/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
from . import schedule, subscriptions, voting
6 changes: 5 additions & 1 deletion confobo/controllers/voting.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ def vote(user: User, choice: int, event: Event) -> bool:

:return: True if the vote was saved, False otherwise
"""

if LOWEST_VOTE <= choice <= HIGHEST_VOTE:
return voting.save_vote(user, choice, event)
else:
raise BadVoteValueError('You can give from {} to {} stars, not {}'.format(LOWEST_VOTE, HIGHEST_VOTE, choice))
error_message = 'You can give from {} to {} stars, not {}'
raise BadVoteValueError(error_message.format(LOWEST_VOTE,
HIGHEST_VOTE,
choice))
1 change: 0 additions & 1 deletion confobo/persistence/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
from . import schedule, subscriptions, voting
1 change: 1 addition & 0 deletions confobo/persistence/schedule.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
CONFERENCE_DAYS = ('2017-06-01', '2017-06-02')


def get_conference_days():
return CONFERENCE_DAYS
4 changes: 4 additions & 0 deletions confobo/secret.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import os


API_KEY = os.environ.get('API_KEY')
3 changes: 2 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import time
from confobo import loop
from confobo import get_message_loop
from confobo.command import command, bindings, pass_user_data
from confobo.controllers.voting import vote, BadVoteValueError
from confobo.controllers.schedule import get_schedule, NoSuchDayError
Expand Down Expand Up @@ -58,6 +58,7 @@ def help_me():


if __name__ == '__main__':
loop = get_message_loop()
loop.run_as_thread()

while True:
Expand Down
3 changes: 1 addition & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
pytest
telepot
telepot==12.2
3 changes: 3 additions & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
flake8>=3.4.1
pylint>=1.7.2
pytest>=3.2.1
5 changes: 2 additions & 3 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest
from confobo.config import SEPARATOR
from confobo.command import command, execute_command, pass_user_data
from confobo.command.decorators import command, pass_user_data
from confobo.command.execution import execute_command
from confobo.command.errors import WrongArgsNumberError, NoSuchCommandError

msg_example = {'message_id': 1,
Expand Down Expand Up @@ -53,5 +54,3 @@ def f_no_user_data():

with pytest.raises(TypeError):
pass_user_data(f_no_user_data)


29 changes: 15 additions & 14 deletions tests/test_controllers.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,39 @@
import pytest
from unittest.mock import Mock

from confobo.models.event import Event
from confobo.models.user import User
from confobo import controllers
import pytest

from confobo.models import event, user
from confobo.controllers import schedule, subscriptions, voting
from confobo import persistence


@pytest.fixture(scope="module")
@pytest.fixture(scope='module')
def fixture_user():
return User(1)
return user.User(1)


@pytest.fixture(scope="module")
@pytest.fixture(scope='module')
def fixture_event():
return Event(1)
return event.Event(1)


def test_vote(fixture_user, fixture_event):
persistence.voting.save_vote = Mock(return_value=True)
vote_acceptable = 4
vote_unacceptable = 6

assert controllers.voting.vote(fixture_user, vote_acceptable, fixture_event) is True
assert controllers.voting.vote(fixture_user, vote_unacceptable, fixture_event) is False
assert voting.vote(fixture_user, vote_acceptable, fixture_event) is True
with pytest.raises(voting.BadVoteValueError):
voting.vote(fixture_user, vote_unacceptable, fixture_event)


def test_remove_subs(fixture_user):
persistence.subscriptions.remove_all = Mock(return_value=True)

assert controllers.subscriptions.remove_all(fixture_user) is True
assert subscriptions.unsubscribe_user(fixture_user) is True


def test_schedule():
assert controllers.schedule.get_schedule('2017-06-01') == '2017-06-01'
with pytest.raises(controllers.schedule.NoSuchDayError):
controllers.schedule.get_schedule('2020-06-04')
assert schedule.get_schedule('2017-06-01') == 'Schedule for 2017-06-01'
with pytest.raises(schedule.NoSuchDayError):
schedule.get_schedule('2020-06-04')