Skip to content

Commit

Permalink
Merge pull request #108 from Bookworm-project/new-exceptions
Browse files Browse the repository at this point in the history
New exceptions
  • Loading branch information
bmschmidt authored Aug 22, 2016
2 parents 9cc03e0 + defd7bb commit b2dd695
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 30 deletions.
2 changes: 2 additions & 0 deletions bookwormDB/CreateDatabase.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,13 @@ def grantPrivileges(self):
The Username for these privileges is pulled from the bookworm.cnf file.
"""

globalfile = Configfile("global")
globalfile.read_config_files()

username=globalfile.config.get("client","user")
password=globalfile.config.get("client","password")

self.db.query("GRANT SELECT ON %s.* TO '%s'@'localhost' IDENTIFIED BY '%s'" % (self.dbname,username,password))

def setVariables(self,originFile,anchorField="bookid",
Expand Down
8 changes: 7 additions & 1 deletion bookwormDB/SQLAPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import MySQLdb
import hashlib
import logging
from bwExceptions import BookwormException

"""
# There are 'fast' and 'full' tables for books and words;
# that's so memory tables can be used in certain cases for fast, hashed
Expand All @@ -28,7 +30,6 @@
"fullword": "words",
"read_default_file": "/etc/mysql/my.cnf"}


class DbConnect(object):
# This is a read-only account
def __init__(self, prefs=general_prefs['default'], database=None,
Expand Down Expand Up @@ -543,6 +544,11 @@ def build_wordstables(self):

needsBigrams = (self.max_word_length == 2 or re.search("words2", self.selections))
needsUnigrams = self.max_word_length == 1 or re.search("[^h][^a][^s]word", self.selections)

if self.max_word_length > 2:
err = dict(code=400, message="Phrase is longer than what Bookworm supports")
raise BookwormException(err)

needsTopics = bool(re.search("topic", self.selections)) or ("topic" in self.limits.keys())

if needsBigrams:
Expand Down
8 changes: 8 additions & 0 deletions bookwormDB/bin/dbbindings-flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ def index():
return "Need query or queryTerms argument"
return main(JSONinput)

@app.route('/debug')
def debug_api():
import logging
logging.basicConfig(level=logging.INFO)
JSONinput = request.args.get('queryTerms') or request.args.get('query')
if not JSONinput:
return "Need query or queryTerms argument"
return main(JSONinput)

@app.route('/debug/query')
def debug_query():
Expand Down
18 changes: 18 additions & 0 deletions bookwormDB/bwExceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'''
This is a stub exception to identify explicitly defined Bookworm Exception.
The intended usage is to raise the exception with a dict that has an error
message, and optionally a code that matches HTTP status codes. e.g.
raise BookwormException({"message": "I'm a teapot" code:418})
or more tidy for longer messages:
err = dict(message="I'm a teapot", code=418)
raise BookwormException(err)
Code should be an int, not a string.
'''


class BookwormException(Exception):
pass
75 changes: 46 additions & 29 deletions bookwormDB/general_API.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from collections import defaultdict
from SQLAPI import DbConnect
from SQLAPI import userquery
from bwExceptions import BookwormException
import re
import json
import logging
Expand All @@ -24,7 +25,6 @@

prefs = dict()


def calculateAggregates(df, parameters):

"""
Expand Down Expand Up @@ -235,8 +235,9 @@ def get_data_from_source(self):
for field in required_fields:
if field not in self.query:
logging.error("Missing field: %s" % field)
return Series({"status": "error", "message": "Bad query. "
"Missing \"%s\" field" % field, "code": 400})
err = dict(message="Bad query. Missing \"%s\" field" % field,
code=400)
raise BookwormException(err)

call1 = deepcopy(self.query)

Expand Down Expand Up @@ -272,13 +273,8 @@ def get_data_from_source(self):
This could use any method other than pandas_SQL:
You'd just need to name objects df1 and df2 as pandas dataframes
"""
try:
df1 = self.generate_pandas_frame(call1)
df2 = self.generate_pandas_frame(call2)
except:
logging.exception("Database error")
return Series({"status": "error", "message": "Database error. "
"Try checking field names."})
df1 = self.generate_pandas_frame(call1)
df2 = self.generate_pandas_frame(call2)

intersections = intersectingNames(df1, df2)

Expand Down Expand Up @@ -309,17 +305,15 @@ def execute(self):
fmt = self.query['format'] if 'format' in self.query else False
version = 2 if method == 'data' else 1

# What to do with multiple search_limits
if isinstance(self.query['search_limits'], list):
if version == 2 and fmt == "json":
return self.multi_execute(version=version)
elif version == 1 and method in ["json", "return_json"]:
return self.multi_execute(version=version)
else:
# Only return first search limit if not return in json
self.query['search_limits'] = self.query['search_limits'][0]

if version == 1:
# What to do with multiple search_limits
if isinstance(self.query['search_limits'], list):
if method in ["json", "return_json"]:
return self.multi_execute(version=version)
else:
# Only return first search limit if not return in json
self.query['search_limits'] = self.query['search_limits'][0]

form = method[7:] if method[:6] == 'return' else method
logging.warn("method == \"%s\" is deprecated. Use method=\"data\" "
"with format=\"%s\" instead." % (method, form))
Expand All @@ -339,20 +333,43 @@ def execute(self):
return pickleDumps(frame, protocol=-1)

elif version == 2:
if fmt == "json":
return self.return_json(version=2)
else:
err = dict(status="error", code="200",
message="Only format=json currently supported")
try:
# What to do with multiple search_limits
if isinstance(self.query['search_limits'], list):
if fmt == "json":
return self.multi_execute(version=version)
else:
# Only return first search limit if not return in json
self.query['search_limits'] = self.query['search_limits'][0]

if fmt == "json":
return self.return_json(version=2)
else:
err = dict(status="error", code=200,
message="Only format=json currently supported")
return json.dumps(err)
except BookwormException as e:
# Error status codes are HTTP codes
# http://www.restapitutorial.com/httpstatuscodes.html
err = e.args[0]
err['status'] = "error"
return json.dumps(err)
except:
# General Uncaught error.
logging.exception("Database error")
return json.dumps({"status": "error", "message": "Database error. "
"Try checking field names."})

# Temporary catch-all pushes to the old methods:
if method in ["returnPossibleFields", "search_results",
"return_books"]:
query = userquery(self.query)
if method == "return_books":
return query.execute()
return json.dumps(query.execute())
try:
query = userquery(self.query)
if method == "return_books":
return query.execute()
return json.dumps(query.execute())
except:
return "General error"

def multi_execute(self, version=1):
"""
Expand Down

0 comments on commit b2dd695

Please sign in to comment.