Simplify marshalling.

This commit is contained in:
Alexis Lahouze 2017-05-18 21:37:57 +02:00
parent de59dc3bb0
commit e1190c872d
5 changed files with 24 additions and 76 deletions

View File

@ -1,44 +0,0 @@
# vim: set tw=80 ts=4 sw=4 sts=4:
"""
This file is part of Accountant.
Accountant is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Accountant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
"""
from flask_restplus import marshal, fields
class Object(fields.Raw):
"""
Field to marshal an object with fields.
SQLAlchemy rows are viewed as tuples by Restful marshaller, and must be
translated into a dict before marshaling.
"""
def __init__(self, model, **kwargs):
"""
:param model: the target model of the object.
"""
self.model = model
super(Object, self).__init__(**kwargs)
def format(self, value):
# First transform object in dict with fields in attribute.
result = {key: getattr(value, key, None) for key in self.model.keys()}
# Marshal the dict
return marshal(result, self.model)
def schema(self):
return self.model.__schema__

View File

@ -16,14 +16,12 @@
"""
import dateutil.parser
from flask_restplus import Namespace, Resource, fields, marshal_with_field
from flask_restplus import Namespace, Resource, fields
from ..models import db
from ..models.accounts import Account
from ..models.operations import Operation
from ..fields import Object
from .users import requires_auth
@ -144,7 +142,7 @@ class AccountListResource(Resource):
@requires_auth
@ns.response(200, 'OK', [account_model])
@marshal_with_field(fields.List(Object(account_model)))
@ns.marshal_list_with(account_model)
def get(self):
""" Returns accounts with their balances."""
@ -154,7 +152,7 @@ class AccountListResource(Resource):
@ns.expect(account_model)
@ns.response(201, 'Account created', account_model)
@ns.response(406, 'Invalid account data')
@marshal_with_field(Object(account_model))
@ns.marshal_with(account_model)
def post(self):
"""Create a new account."""
@ -195,7 +193,7 @@ class AccountResource(Resource):
@requires_auth
@ns.response(200, 'OK', account_model)
@marshal_with_field(Object(account_model))
@ns.marshal_with(account_model)
def get(self, id):
"""Get an account."""
@ -215,7 +213,7 @@ class AccountResource(Resource):
@ns.expect(account_model)
@ns.response(200, 'OK', account_model)
@ns.response(406, 'Invalid account data')
@marshal_with_field(Object(account_model))
@ns.marshal_with(account_model)
def post(self, id):
"""Update an account."""
@ -248,7 +246,7 @@ class AccountResource(Resource):
@requires_auth
@ns.response(204, 'Account deleted', account_model)
@marshal_with_field(Object(account_model))
@ns.marshal_with(account_model)
def delete(self, id):
"""Delete an account."""
@ -278,7 +276,7 @@ class SoldsResource(Resource):
401: 'Unauthorized',
404: 'Account not found'
})
@marshal_with_field(Object(solds_model))
@ns.marshal_with(solds_model)
def get(self, id):
"""Get solds for a specific account and date range."""
@ -308,7 +306,7 @@ class BalanceResource(Resource):
404: 'Account not found'
})
@ns.expect(range_parser)
@marshal_with_field(Object(balance_model))
@ns.marshal_with(balance_model)
def get(self, id):
"""Get account balance for a specific date range."""
@ -340,7 +338,7 @@ class CategoryResource(Resource):
404: 'Account not found'
})
@ns.expect(range_parser)
@marshal_with_field(fields.List(Object(category_model)))
@ns.marshal_list_with(category_model)
def get(self, id):
"""Get account category balances for a specific date range."""
@ -362,7 +360,7 @@ class OHLCResource(Resource):
404: 'Account not found'
})
@ns.expect(range_parser)
@marshal_with_field(fields.List(Object(ohlc_model)))
@ns.marshal_list_with(ohlc_model)
def get(self, id):
"""Get OHLC data for a specific date range and account."""

View File

@ -16,7 +16,7 @@
"""
import dateutil.parser
from flask_restplus import Namespace, Resource, fields, marshal_with_field
from flask_restplus import Namespace, Resource, fields
from ..models import db
from ..models.accounts import Account
@ -24,8 +24,6 @@ from ..models.operations import Operation
from .users import requires_auth
from ..fields import Object
# pylint: disable=invalid-name
ns = Namespace('operation', description='Operation management')
@ -115,7 +113,7 @@ class OperationListResource(Resource):
@requires_auth
@ns.response(200, 'OK', [operation_with_sold_model])
@ns.expect(parser=account_range_parser)
@marshal_with_field(fields.List(Object(operation_with_sold_model)))
@ns.marshal_list_with(operation_with_sold_model)
def get(self):
"""Get operations with solds for a specific account."""
@ -132,7 +130,7 @@ class OperationListResource(Resource):
@ns.response(201, 'Operation created', operation_model)
@ns.response(404, 'Account not found')
@ns.response(406, 'Invalid operation data')
@marshal_with_field(Object(operation_model))
@ns.marshal_with(operation_model)
def post(self):
"""Create a new operation."""
@ -176,7 +174,7 @@ class OperationResource(Resource):
@requires_auth
@ns.response(200, 'OK', operation_model)
@marshal_with_field(Object(operation_model))
@ns.marshal_with(operation_model)
def get(self, id):
"""Get operation."""
@ -194,7 +192,7 @@ class OperationResource(Resource):
@ns.expect(operation_model)
@ns.response(200, 'OK', operation_model)
@ns.response(406, 'Invalid operation data')
@marshal_with_field(Object(operation_model))
@ns.marshal_with(operation_model)
def post(self, id):
"""Update an operation."""
@ -227,7 +225,7 @@ class OperationResource(Resource):
@requires_auth
@ns.response(204, 'Operation deleted', operation_model)
@marshal_with_field(Object(operation_model))
@ns.marshal_with(operation_model)
def delete(self, id):
"""Delete an operation."""

View File

@ -14,7 +14,7 @@
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
"""
from flask_restplus import Namespace, Resource, fields, marshal_with_field
from flask_restplus import Namespace, Resource, fields
from sqlalchemy import true
@ -25,8 +25,6 @@ from ..models.scheduled_operations import ScheduledOperation
from .users import requires_auth
from ..fields import Object
# pylint: disable=invalid-name
ns = Namespace(
'scheduled_operation',
@ -92,7 +90,7 @@ class ScheduledOperationListResource(Resource):
@requires_auth
@ns.expect(account_id_parser)
@ns.response(200, 'OK', [scheduled_operation_model])
@marshal_with_field(fields.List(Object(scheduled_operation_model)))
@ns.marshal_list_with(scheduled_operation_model)
def get(self):
"""Get all scheduled operation for an account."""
@ -105,7 +103,7 @@ class ScheduledOperationListResource(Resource):
@ns.response(200, 'OK', scheduled_operation_model)
@ns.response(404, 'Account not found')
@ns.response(406, 'Invalid operation data')
@marshal_with_field(Object(scheduled_operation_model))
@ns.marshal_with(scheduled_operation_model)
def post(self):
"""Add a new scheduled operation."""
@ -153,7 +151,7 @@ class ScheduledOperationResource(Resource):
@requires_auth
@ns.response(200, 'OK', scheduled_operation_model)
@marshal_with_field(Object(scheduled_operation_model))
@ns.marshal_with(scheduled_operation_model)
def get(self, id):
"""Get scheduled operation."""
@ -171,7 +169,7 @@ class ScheduledOperationResource(Resource):
@ns.response(200, 'OK', scheduled_operation_model)
@ns.response(406, 'Invalid scheduled operation data')
@ns.expect(scheduled_operation_model)
@marshal_with_field(Object(scheduled_operation_model))
@ns.marshal_with(scheduled_operation_model)
def post(self, id):
"""Update a scheduled operation."""
@ -209,7 +207,7 @@ class ScheduledOperationResource(Resource):
@requires_auth
@ns.response(200, 'OK', scheduled_operation_model)
@ns.response(409, 'Cannot be deleted')
@marshal_with_field(Object(scheduled_operation_model))
@ns.marshal_with(scheduled_operation_model)
def delete(self, id):
"""Delete a scheduled operation."""

View File

@ -20,9 +20,7 @@ from functools import wraps
import arrow
from flask import request, g, current_app as app
from flask_restplus import Namespace, Resource, fields, marshal_with_field
from ..fields import Object
from flask_restplus import Namespace, Resource, fields
from ..models.users import User
@ -144,7 +142,7 @@ class LoginResource(Resource):
responses={
200: ('OK', user_model)
})
@marshal_with_field(Object(user_model))
@ns.marshal_with(user_model)
def get(self):
"""Get authenticated user information."""