Skip to content

Commit

Permalink
Merge pull request #83 from gunthercox/clean
Browse files Browse the repository at this point in the history
General code cleanup
  • Loading branch information
gunthercox committed Nov 28, 2015
2 parents 480c91b + dfd3bba commit b61f953
Show file tree
Hide file tree
Showing 14 changed files with 164 additions and 187 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
build
dist
database.db
settings.py
*.pyc
*.swp
*.egg-info
17 changes: 17 additions & 0 deletions chatterbot/adapters/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
class AdapterNotImplementedError(NotImplementedError):

def __init__(self, message="This method must be overridden in a subclass method."):
self.message = message

def __str__(self):
return self.message


class EmptyDatabaseException(Exception):

def __init__(self, message="The database currently contains no entries. At least one entry is expected. Make sure that you have read_only set to False."):
self.message = message

def __str__(self):
return self.message


class EmptyDatasetException(Exception):

def __init__(self, message="An empty collection of elements was received when at least one entry was expected."):
self.message = message

def __str__(self):
return self.message

9 changes: 5 additions & 4 deletions chatterbot/adapters/logic/closest_match.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from chatterbot.adapters.exceptions import EmptyDatasetException
from .logic import LogicAdapter
from fuzzywuzzy import process

Expand All @@ -10,15 +11,15 @@ def get(self, input_statement, statement_list, current_conversation=None):
Returns the closest matching statement from the list.
"""

# Check if the list is empty
if not statement_list:
raise EmptyDatasetException

# Get the text of each statement
text_of_all_statements = []
for statement in statement_list:
text_of_all_statements.append(statement.text)

# If the list is empty, return the statement
if not statement_list:
return input_statement

# Check if an exact match exists
if input_statement.text in text_of_all_statements:
return input_statement
Expand Down
9 changes: 5 additions & 4 deletions chatterbot/adapters/logic/closest_meaning.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from chatterbot.adapters.exceptions import EmptyDatasetException
from .logic import LogicAdapter

from nltk.corpus import wordnet
Expand Down Expand Up @@ -82,15 +83,15 @@ def get(self, input_statement, statement_list, current_conversation=None):
Returns the closest matching statement from the list.
"""

# Check if the list is empty
if not statement_list:
raise EmptyDatasetException

# Get the text of each statement
text_of_all_statements = []
for statement in statement_list:
text_of_all_statements.append(statement.text)

# Check if there is no options
if not statement_list:
return input_statement

# Check if an exact match exists
if input_statement.text in text_of_all_statements:
return input_statement
Expand Down
4 changes: 0 additions & 4 deletions chatterbot/adapters/storage/jsondatabase.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ def _all_kwargs_match_values(self, kwarguments, values):
if (kwarguments[kwarg] not in text_values) and (kwarguments[kwarg] not in values[key]):
return False

if identifier == "not":
if (key in values) and (kwarguments[kwarg] == values[key]):
return False

if kwarg in values:
if values[kwarg] != kwarguments[kwarg]:
return False
Expand Down
13 changes: 11 additions & 2 deletions chatterbot/chatterbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,25 @@ def get_response(self, input_text):
in_response_to field. Otherwise, the logic adapter may find a closest
matching statement that does not have a known response.
'''
for statement in all_statements:
# Copy the list of statements to prevent changing the size of the list while iterating over it
all_statements_copy = list(all_statements)
for statement in all_statements_copy:
response_exists = False
for s in all_statements:
for s in all_statements_copy:
if statement in s.in_response_to:
response_exists = True
break # Exit for loop since one exists

if not response_exists:
all_statements.remove(statement)

# It will not be possible to select a match from an empty list of statements
if not all_statements:
# Return a random response
# TODO Make sure that recent_statements & database are updated as needed
response = self.storage.get_random()
return self.io.process_response(response)

# Select the closest match to the input statement
closest_match = self.logic.get(
input_statement,
Expand Down
38 changes: 5 additions & 33 deletions tests/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import os


class UntrainedChatBotTestCase(TestCase):
class ChatBotTestCase(TestCase):

def setUp(self):
self.test_data_directory = 'test_data'
Expand All @@ -12,7 +12,10 @@ def setUp(self):
if not os.path.exists(self.test_data_directory):
os.makedirs(self.test_data_directory)

database_path = self.test_data_directory + '/' + self.test_database_name
database_path = os.path.join(
self.test_data_directory,
self.test_database_name
)

self.chatbot = ChatBot(
"Test Bot",
Expand Down Expand Up @@ -40,34 +43,3 @@ def tearDown(self):
self.chatbot.storage.drop()
self.remove_test_data()


class ChatBotTestCase(UntrainedChatBotTestCase):

def setUp(self):
super(ChatBotTestCase, self).setUp()
"""
Set up a database for testing.
"""
data1 = [
"african or european?",
"Huh? I... I don't know that.",
"How do you know so much about swallows?"
]

data2 = [
"Siri is adorable",
"Who is Seri?",
"Siri is my cat"
]

data3 = [
"What... is your quest?",
"To seek the Holy Grail.",
"What... is your favourite colour?",
"Blue."
]

self.chatbot.train(data1)
self.chatbot.train(data2)
self.chatbot.train(data3)

32 changes: 32 additions & 0 deletions tests/integration_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from .base_case import ChatBotTestCase


class ChatterBotStorageIntegrationTests(ChatBotTestCase):

def test_database_is_updated(self):
"""
Test that the database is updated when read_only is set to false.
"""
input_text = "What is the airspeed velocity of an unladen swallow?"
exists_before = self.chatbot.storage.find(input_text)

response = self.chatbot.get_response(input_text)
exists_after = self.chatbot.storage.find(input_text)

self.assertFalse(exists_before)
self.assertTrue(exists_after)

def test_database_is_not_updated_when_read_only(self):
"""
Test that the database is not updated when read_only is set to true.
"""
self.chatbot.storage.read_only = True

input_text = "Who are you? The proud lord said."
exists_before = self.chatbot.storage.find(input_text)

response = self.chatbot.get_response(input_text)
exists_after = self.chatbot.storage.find(input_text)

self.assertFalse(exists_before)
self.assertFalse(exists_after)
6 changes: 3 additions & 3 deletions tests/logic_adapter_tests/test_closest_match.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from unittest import TestCase
from chatterbot.adapters.exceptions import EmptyDatasetException
from chatterbot.adapters.logic import ClosestMatchAdapter
from chatterbot.conversation import Statement

Expand Down Expand Up @@ -27,7 +28,6 @@ def test_no_choices(self):
possible_choices = []
statement = Statement("What is your quest?")

close = self.adapter.get(statement, possible_choices)

self.assertEqual("What is your quest?", close)
with self.assertRaises(EmptyDatasetException):
self.adapter.get(statement, possible_choices)

6 changes: 3 additions & 3 deletions tests/logic_adapter_tests/test_closest_meaning.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from unittest import TestCase
from chatterbot.adapters.exceptions import EmptyDatasetException
from chatterbot.adapters.logic import ClosestMeaningAdapter
from chatterbot.conversation import Statement

Expand All @@ -12,9 +13,8 @@ def test_no_choices(self):
possible_choices = []
statement = Statement("Hello")

close = self.adapter.get(statement, possible_choices)

self.assertEqual("Hello", close)
with self.assertRaises(EmptyDatasetException):
self.adapter.get(statement, possible_choices)

def test_get_closest_statement(self):
possible_choices = [
Expand Down
52 changes: 0 additions & 52 deletions tests/storage_adapter_tests/test_jsondb_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,58 +288,6 @@ def test_filter_returns_statement_with_multiple_responses(self):

self.assertEqual(len(response.in_response_to), 2)

def test_not_filter_no_responses(self):
statement = Statement(
"You are welcome.",
in_response_to=[]
)
self.adapter.update(statement)
response = self.adapter.filter(
in_response_to__not=[]
)

self.assertEqual(
len(response),
0,
"A response was found when none should have been returned."
)

def test_not_filter_multiple_responses(self):
statements = [
Statement(
"You are welcome.",
in_response_to=[]
),
Statement(
"I like ducks.",
in_response_to=[]
),
Statement(
"Hello.",
in_response_to=[Response("Hi.")]
),
Statement(
"Hi.",
in_response_to=[Response("Hello.")]
),
Statement(
"Hey!",
in_response_to=[Response("Hello.")]
)
]

for statement in statements:
self.adapter.update(statement)

response = self.adapter.filter(
in_response_to__not=[]
)

self.assertEqual(len(response), 3)
self.assertIn("Hello.", response)
self.assertIn("Hi.", response)
self.assertIn("Hey!", response)


class ReadOnlyJsonDatabaseAdapterTestCase(BaseJsonDatabaseAdapterTestCase):

Expand Down
Loading

0 comments on commit b61f953

Please sign in to comment.