Skip to content

Instantly share code, notes, and snippets.

@stestagg
Last active December 15, 2015 05:59
Show Gist options
  • Save stestagg/5212720 to your computer and use it in GitHub Desktop.
Save stestagg/5212720 to your computer and use it in GitHub Desktop.
import functools
import flask
import inspect
import sys
import traceback
def infer_args(func):
argspec = inspect.getargspec(func)
if argspec.defaults is None:
defaults = {}
else:
defaults = dict((d for d in zip(reversed(argspec.args), argspec.defaults)))
return dict((a, str) for a in argspec.args), defaults
class Api(object):
def __init__(self, name, mod_name, prefix=None, description=None, **kwargs):
if prefix is None:
prefix = "/%s" % name
self.description = description
self.name = name
self.url_prefix = prefix
self.app = flask.Blueprint(name, mod_name, url_prefix=prefix, **kwargs)
self.endpoints = {}
def endpoint(self, endpoint_name, types=None, data_key="data", defaults=None):
def annotate(func):
args, actual_defaults = infer_args(func)
if types is not None:
args.update(types)
if defaults is not None:
actual_defaults = defaults
@functools.wraps(func)
def endpoint():
try:
view_args = actual_defaults.copy()
for key, value in flask.request.values.iteritems():
view_args[key] = args[key](value)
return flask.jsonify({"success": True, data_key: func(**view_args)})
except Exception, e:
rv = {"success": False}
if isinstance(e, (KeyError, )):
rv["message"] = "Item not Found: %s" % e.message
else:
rv["message"] = str(e.message or "Unknown Error")
print >>sys.stderr, traceback.format_exc()
rv["traceback"] = traceback.format_exc()
response = flask.jsonify(rv)
response.status_code = getattr(e, "code", 500)
flask.request.log("ERROR", "error", "Error with %s: '%r'",
flask.request.path, e)
return response
self.endpoints[endpoint_name] = (args, data_key, actual_defaults, func.__doc__ or "")
self.app.route("/%s" % endpoint_name, methods=("GET", "POST"))(endpoint)
return func
return annotate
import path.to.api
api = path.to.api.Api("usage", __name__, description="Example")
@api.endpoint("add")
def add_numbers(a, b, c=0):
return a+b+c
# wget http://server:5000/usage/add?a=1&b=2
# wget http://server:5000/usage/add?a=1&b=2&c=3
#
# OR
#
# import usage
# usage.add_numbers(1, 2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment