diff options
Diffstat (limited to 'pyaggr3g470r/views/api/common.py')
-rw-r--r-- | pyaggr3g470r/views/api/common.py | 122 |
1 files changed, 102 insertions, 20 deletions
diff --git a/pyaggr3g470r/views/api/common.py b/pyaggr3g470r/views/api/common.py index edf560da..c0759c03 100644 --- a/pyaggr3g470r/views/api/common.py +++ b/pyaggr3g470r/views/api/common.py @@ -1,6 +1,8 @@ +import json +import types from functools import wraps -from flask import request, g, session, Response, jsonify -from flask.ext.restful import Resource +from flask import request, g, session, Response +from flask.ext.restful import Resource, reqparse from pyaggr3g470r.models import User from pyaggr3g470r.lib.exceptions import PyAggError @@ -35,42 +37,122 @@ def authenticate(func): return wrapper +def default_handler(obj): + """JSON handler for default query formatting""" + if hasattr(obj, 'isoformat'): + return obj.isoformat() + if hasattr(obj, 'dump'): + return obj.dump() + if isinstance(obj, (set, frozenset, types.GeneratorType)): + return list(obj) + raise TypeError("Object of type %s with value of %r " + "is not JSON serializable" % (type(obj), obj)) + + def to_response(func): def wrapper(*args, **kwargs): try: - res = func(*args, **kwargs) - except PyAggError, error: - response = jsonify(**error.message) + result = func(*args, **kwargs) + except PyAggError as error: + response = Response(json.dumps(result[0], default=default_handler)) response.status_code = error.status_code return response - if isinstance(res, tuple): - response = jsonify(**res[0]) - if len(res) > 1: - response.status_code = res[1] - return response - return res + status_code = 200 + if isinstance(result, tuple): + result, status_code = result + response = Response(json.dumps(result, default=default_handler), + status=status_code) + return response return wrapper -class PyAggResource(Resource): +class PyAggAbstractResource(Resource): method_decorators = [authenticate, to_response] - controller_cls = None - editable_attrs = [] def __init__(self, *args, **kwargs): self.controller = self.controller_cls(g.user.id) - super(PyAggResource, self).__init__(*args, **kwargs) + super(PyAggAbstractResource, self).__init__(*args, **kwargs) + + def reqparse_args(self, strict=False, default=True): + """ + strict: bool + if True will throw 400 error if args are defined and not in request + default: bool + if True, won't return defaults + + """ + parser = reqparse.RequestParser() + for attr_name, attrs in self.attrs.items(): + if not default and attr_name not in request.args: + continue + parser.add_argument(attr_name, location='json', **attrs) + return parser.parse_args(strict=strict) + + +class PyAggResourceNew(PyAggAbstractResource): + + def post(self): + return self.controller.create(**self.reqparse_args()), 201 + + +class PyAggResourceExisting(PyAggAbstractResource): def get(self, obj_id=None): - return {'result': [self.controller.get(id=obj_id).dump()]} + return self.controller.get(id=obj_id).dump() def put(self, obj_id=None): - args = self.reqparse.parse_args() + args = self.reqparse_args() new_values = {key: args[key] for key in - set(args).intersection(self.editable_attrs)} + set(args).intersection(self.attrs)} self.controller.update(obj_id, **new_values) - return {"message": "ok"} def delete(self, obj_id=None): self.controller.delete(obj_id) - return {"message": "ok"}, 204 + return None, 204 + + +class PyAggResourceMulti(PyAggAbstractResource): + + def get(self): + filters = self.reqparse_args(default=False) + return [res.dump() for res in self.controller.read(**filters).all()] + + def post(self): + status = 201 + results = [] + args = [] # FIXME + for arg in args: + try: + results.append(self.controller.create(**arg).id) + except Exception as error: + status = 206 + results.append(error) + return results, status + + def put(self): + status = 200 + results = [] + args = {} # FIXME + for obj_id, attrs in args.items(): + try: + new_values = {key: args[key] for key in + set(attrs).intersection(self.editable_attrs)} + self.controller.update(obj_id, **new_values) + results.append('ok') + except Exception as error: + status = 206 + results.append(error) + return results, status + + def delete(self): + status = 204 + results = [] + obj_ids = [] # FIXME extract some real ids + for obj_id in obj_ids: + try: + self.controller.delete(obj_id) + results.append('ok') + except Exception as error: + status = 206 + results.append(error) + return results, status |