Skip to content

Commit

Permalink
setting up persistent cache for REST API
Browse files Browse the repository at this point in the history
  • Loading branch information
jonrkarr committed Jun 11, 2019
1 parent 54b5769 commit 03c8105
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 59 deletions.
140 changes: 82 additions & 58 deletions bpforms/rest.py
Expand Up @@ -9,19 +9,25 @@
from wc_utils.util.chem import OpenBabelUtils
import bpforms
import bpforms.util
import diskcache
import flask
import flask_restplus
import flask_restplus.errors
import flask_restplus.fields
import functools
import math
import methodtools
import os
import urllib.parse
import warnings


# setup app
app = flask.Flask(__name__)

# setup cache
cache_dir = os.path.expanduser('~/.cache/bpforms')
if not os.path.isdir(cache_dir):
os.makedirs(cache_dir)
cache = diskcache.FanoutCache(cache_dir)


class PrefixMiddleware(object):
def __init__(self, app, prefix=''):
Expand Down Expand Up @@ -184,7 +190,6 @@ def get(self):
class AlpabetResource(flask_restplus.Resource):
""" Get alphabets """

@methodtools.lru_cache()
def get(self, id):
""" Get an alphabet """
"""
Expand All @@ -194,23 +199,30 @@ def get(self, id):
Returns:
:obj:`dict`: dictionary representation of an alphabet
"""
try:
alphabet_obj = bpforms.util.get_alphabet(id)
except ValueError as error:
flask_restplus.abort(400, 'Invalid alphabet "{}"'.format(id))
return get_alphabet(id)

alphabet_dict = alphabet_obj.to_dict()

for code, monomer in alphabet_obj.monomers.items():
monomer_dict = alphabet_dict['monomers'][code]
monomer_dict['binds_backbone'], \
monomer_dict['binds_left'], \
monomer_dict['binds_right'], \
monomer_dict['formula'], \
monomer_dict['mol_wt'], \
monomer_dict['charge'] = get_monomer_properties(id, monomer)
@cache.memoize(typed=False, expire=30 * 24 * 60 * 60)
def get_alphabet(id):
""" Get an alphabet
return alphabet_dict
Args:
id (:obj:`str`): id of alphabet
Returns:
:obj:`dict`: dictionary representation of an alphabet
"""
try:
alphabet_obj = bpforms.util.get_alphabet(id)
except ValueError as error:
flask_restplus.abort(400, 'Invalid alphabet "{}"'.format(id))

alphabet_dict = alphabet_obj.to_dict()

for code, monomer in alphabet_obj.monomers.items():
alphabet_dict['monomers'][code] = get_monomer_properties(id, code)

return alphabet_dict


@alphabet_ns.route("/<string:alphabet>/<string:monomer>/", defaults={'format': 'json'})
Expand All @@ -223,54 +235,66 @@ def get(self, id):
class MonomerResource(flask_restplus.Resource):
""" Get information about a monomer """

@methodtools.lru_cache(maxsize=2 ** 14)
def get(self, alphabet, monomer, format):
""" Get an alphabet """
""" Get a monomeric form """
"""
Returns:
:obj:`object`: dictionary representation of an monomer or SVG-encoded image of a monomer
"""
try:
alphabet_obj = bpforms.util.get_alphabet(alphabet)
except ValueError as error:
flask_restplus.abort(400, 'Invalid alphabet "{}"'.format(alphabet))

monomer = urllib.parse.unquote(monomer)
monomer_obj = alphabet_obj.monomers.get(monomer, None)
if monomer_obj is None:
flask_restplus.abort(400, 'Monomer "{}" not in alphabet "{}"'.format(monomer, alphabet))

if format == 'json':
monomer_dict = monomer_obj.to_dict(alphabet=alphabet_obj)
monomer_dict['binds_backbone'], \
monomer_dict['binds_left'], \
monomer_dict['binds_right'], \
monomer_dict['formula'], \
monomer_dict['mol_wt'], \
monomer_dict['charge'] = get_monomer_properties(alphabet, monomer_obj)
return monomer_dict

elif format == 'svg':
return flask.Response(monomer_obj.get_image(width=250, height=150), mimetype='image/svg+xml')
return get_monomer(alphabet, monomer, format)

else:
flask_restplus.abort(400, 'Invalid format "{}"'.format(format))

@cache.memoize(typed=False, expire=30 * 24 * 60 * 60)
def get_monomer(alphabet, monomer, format):
""" Get a monomeric form
Args:
alphabet (:obj:`str`): id of the alphabet
monomer (:obj:`str`): code of a monomeric form
format (:obj:`str`): output format (e.g. "json" or "svg")
Returns:
:obj:`object`: dictionary representation of an monomer or SVG-encoded image of a monomer
"""
try:
alphabet_obj = bpforms.util.get_alphabet(alphabet)
except ValueError as error:
flask_restplus.abort(400, 'Invalid alphabet "{}"'.format(alphabet))

monomer = urllib.parse.unquote(monomer)
monomer_obj = alphabet_obj.monomers.get(monomer, None)
if monomer_obj is None:
flask_restplus.abort(400, 'Monomer "{}" not in alphabet "{}"'.format(monomer, alphabet))

@functools.lru_cache(maxsize=2 ** 14)
def get_monomer_properties(alphabet_id, monomer):
""" Calculate properties of a monomeric form
if format == 'json':
return get_monomer_properties(alphabet, monomer)

elif format == 'svg':
return flask.Response(monomer_obj.get_image(width=250, height=150), mimetype='image/svg+xml')

else:
flask_restplus.abort(400, 'Invalid format "{}"'.format(format))


@cache.memoize(typed=False, expire=30 * 24 * 60 * 60)
def get_monomer_properties(alphabet, monomer):
""" Get properties of a monomeric form
Args:
alphabet_id (:obj:`str`): id of an alphabet
monomer (:obj:`bpforms.Monomer`): monomeric form
alphabet (:obj:`str`): id of an alphabet
monomer (:obj:`str`): code of monomeric form
Returns:
:obj:`dict`: properties of monomeric form
"""
form_obj = bpforms.util.get_form(alphabet_id)()
return (
len(monomer.backbone_bond_atoms) > 0,
form_obj.can_monomer_bind_left(monomer),
form_obj.can_monomer_bind_right(monomer),
dict(monomer.get_formula()),
monomer.get_mol_wt(),
monomer.get_charge(),
)
alphabet_obj = bpforms.util.get_alphabet(alphabet)
form_obj = bpforms.util.get_form(alphabet)()
monomer_obj = alphabet_obj.monomers.get(monomer, None)
monomer_dict = monomer_obj.to_dict(alphabet=alphabet_obj)
monomer_dict['binds_backbone'] = len(monomer_obj.backbone_bond_atoms) > 0
monomer_dict['binds_left'] = form_obj.can_monomer_bind_left(monomer_obj)
monomer_dict['binds_right'] = form_obj.can_monomer_bind_right(monomer_obj)
monomer_dict['formula'] = dict(monomer_obj.get_formula())
monomer_dict['mol_wt'] = monomer_obj.get_mol_wt()
monomer_dict['charge'] = monomer_obj.get_charge()
return monomer_dict
2 changes: 1 addition & 1 deletion requirements.txt
Expand Up @@ -2,8 +2,8 @@ attrdict
beautifulsoup4
cement >= 3.0.0
configobj
diskcache
lark_parser >= 0.6.6
methodtools
openbabel
requests
requests_cache
Expand Down

0 comments on commit 03c8105

Please sign in to comment.