diff --git a/accountant/api/views/accounts.py b/accountant/api/views/accounts.py index 6011397..f6e39b7 100644 --- a/accountant/api/views/accounts.py +++ b/accountant/api/views/accounts.py @@ -14,9 +14,7 @@ You should have received a copy of the GNU Affero General Public License along with Accountant. If not, see . """ -import dateutil.parser - -from flask.ext.restful import Resource, fields, reqparse, marshal_with_field +from flask.ext.restful import Resource, fields, marshal_with_field from accountant import db @@ -28,6 +26,7 @@ from ..models.operations import Operation from ..fields import Object from .users import requires_auth +from .parsers import account_parser, range_parser account_model = { @@ -49,17 +48,6 @@ balance_model = { } -parser = reqparse.RequestParser() -parser.add_argument('name', type=str, required=True) -parser.add_argument('authorized_overdraft', type=float, required=True) - -date_parser = reqparse.RequestParser() -date_parser.add_argument('begin', - type=lambda a: dateutil.parser.parse(a) if a else None) -date_parser.add_argument('end', - type=lambda a: dateutil.parser.parse(a) if a else None) - - class AccountListResource(Resource): @requires_auth @marshal_with_field(fields.List(Object(account_model))) @@ -75,7 +63,7 @@ class AccountListResource(Resource): """ Create a new account. """ - data = parser.parse_args() + data = account_parser.parse_args() account = Account(**data) @@ -105,7 +93,7 @@ class AccountResource(Resource): @requires_auth @marshal_with_field(Object(account_model)) def post(self, id): - data = parser.parse_args() + data = account_parser.parse_args() assert (id not in data or data.id is None or data.id == id) @@ -160,11 +148,6 @@ class SoldsResource(Resource): return account.solds(), 200 -range_parser = reqparse.RequestParser() -range_parser.add_argument('begin', type=lambda a: dateutil.parser.parse(a)) -range_parser.add_argument('end', type=lambda a: dateutil.parser.parse(a)) - - class BalanceResource(Resource): @requires_auth @marshal_with_field(Object(balance_model)) diff --git a/accountant/api/views/operations.py b/accountant/api/views/operations.py index 0aca19f..f0ad12f 100644 --- a/accountant/api/views/operations.py +++ b/accountant/api/views/operations.py @@ -14,9 +14,7 @@ You should have received a copy of the GNU Affero General Public License along with Accountant. If not, see . """ -import dateutil.parser - -from flask.ext.restful import Resource, fields, reqparse, marshal_with_field +from flask.ext.restful import Resource, fields, marshal_with_field from accountant import db @@ -25,6 +23,7 @@ from .. import api from ..models.operations import Operation from .users import requires_auth +from .parsers import operation_parser, account_range_parser from ..fields import Object @@ -45,31 +44,12 @@ operation_with_sold_model = { operation_model = operation_with_sold_model -parser = reqparse.RequestParser() -# Must use lambda because the parser passes other parameters badly interpreted -# by dateutil.parser.parse -parser.add_argument('operation_date', type=lambda a: dateutil.parser.parse(a)) -parser.add_argument('label', type=str) -parser.add_argument('value', type=float) -parser.add_argument('pointed', type=bool) -parser.add_argument('category', type=str) -parser.add_argument('account_id', type=int) -parser.add_argument('scheduled_operation_id', type=int) -parser.add_argument('confirmed', type=bool) -parser.add_argument('canceled', type=bool) - - -range_parser = reqparse.RequestParser() -range_parser.add_argument('account_id', type=int) -range_parser.add_argument('begin', type=lambda a: dateutil.parser.parse(a)) -range_parser.add_argument('end', type=lambda a: dateutil.parser.parse(a)) - class OperationListResource(Resource): @requires_auth @marshal_with_field(fields.List(Object(operation_with_sold_model))) def get(self): - data = range_parser.parse_args() + data = account_range_parser.parse_args() return Operation.query( begin=data['begin'], @@ -81,7 +61,7 @@ class OperationListResource(Resource): @requires_auth @marshal_with_field(Object(operation_model)) def post(self): - data = parser.parse_args() + data = operation_parser.parse_args() operation = Operation(**data) @@ -107,7 +87,7 @@ class OperationResource(Resource): @requires_auth @marshal_with_field(Object(operation_model)) def post(self, id): - data = parser.parse_args() + data = operation_parser.parse_args() assert (id not in data or data.id is None or data.id == id) diff --git a/accountant/api/views/parsers.py b/accountant/api/views/parsers.py new file mode 100644 index 0000000..08919ca --- /dev/null +++ b/accountant/api/views/parsers.py @@ -0,0 +1,76 @@ +""" + 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 . +""" +import dateutil.parser + +from flask.ext.restful import reqparse + +# Parser for a date range. +range_parser = reqparse.RequestParser() +range_parser.add_argument( + 'begin', + type=lambda a: dateutil.parser.parse(a) if a else None +) +range_parser.add_argument( + 'end', + type=lambda a: dateutil.parser.parse(a) if a else None +) + +# Parser for a date range and an account id. +account_range_parser = range_parser.copy() +account_range_parser.add_argument('account_id', type=int) + +# Parser for an account. +account_parser = reqparse.RequestParser() +account_parser.add_argument('name', type=str, required=True) +account_parser.add_argument('authorized_overdraft', type=float, required=True) + +# Parser for an operation. +operation_parser = reqparse.RequestParser() +# Must use lambda because the parser passes other parameters badly interpreted +# by dateutil.parser.parse +operation_parser.add_argument( + 'operation_date', type=lambda a: dateutil.parser.parse(a)) +operation_parser.add_argument('label', type=str) +operation_parser.add_argument('value', type=float) +operation_parser.add_argument('pointed', type=bool) +operation_parser.add_argument('category', type=str) +operation_parser.add_argument('account_id', type=int) +operation_parser.add_argument('scheduled_operation_id', type=int) +operation_parser.add_argument('confirmed', type=bool) +operation_parser.add_argument('canceled', type=bool) + +# Parser for an account id. +account_id_parser = reqparse.RequestParser() +account_id_parser.add_argument('account_id', type=int) + +# Parser for a scheduled operation. +scheduled_operation_parser = reqparse.RequestParser() +scheduled_operation_parser.add_argument( + 'start_date', type=lambda a: dateutil.parser.parse(a)) +scheduled_operation_parser.add_argument( + 'stop_date', type=lambda a: dateutil.parser.parse(a)) +scheduled_operation_parser.add_argument('day', type=int) +scheduled_operation_parser.add_argument('frequency', type=int) +scheduled_operation_parser.add_argument('label', type=str) +scheduled_operation_parser.add_argument('value', type=float) +scheduled_operation_parser.add_argument('category', type=str) +scheduled_operation_parser.add_argument('account_id', type=int) + +# Parser for a login. +login_parser = reqparse.RequestParser() +login_parser.add_argument('email', type=str, required=True) +login_parser.add_argument('password', type=str, required=True) diff --git a/accountant/api/views/scheduled_operations.py b/accountant/api/views/scheduled_operations.py index b6bf428..9aeb0a6 100644 --- a/accountant/api/views/scheduled_operations.py +++ b/accountant/api/views/scheduled_operations.py @@ -14,9 +14,7 @@ You should have received a copy of the GNU Affero General Public License along with Accountant. If not, see . """ -import dateutil.parser - -from flask.ext.restful import Resource, fields, reqparse, marshal_with_field +from flask.ext.restful import Resource, fields, marshal_with_field from sqlalchemy import true @@ -27,8 +25,8 @@ from ..models.operations import Operation from .. import api - from .users import requires_auth +from .parsers import account_id_parser, scheduled_operation_parser from ..fields import Object @@ -46,21 +44,6 @@ scheduled_operation_model = { } -parser = reqparse.RequestParser() -parser.add_argument('start_date', type=lambda a: dateutil.parser.parse(a)) -parser.add_argument('stop_date', type=lambda a: dateutil.parser.parse(a)) -parser.add_argument('day', type=int) -parser.add_argument('frequency', type=int) -parser.add_argument('label', type=str) -parser.add_argument('value', type=float) -parser.add_argument('category', type=str) -parser.add_argument('account_id', type=int) - - -get_parser = reqparse.RequestParser() -get_parser.add_argument('account_id', type=int) - - class ScheduledOperationListResource(Resource): @requires_auth @marshal_with_field(fields.List(Object(scheduled_operation_model))) @@ -68,7 +51,7 @@ class ScheduledOperationListResource(Resource): """ Get all scheduled operation for an account. """ - data = get_parser.parse_args() + data = account_id_parser.parse_args() return ScheduledOperation.query().filter_by(**data).all(), 200 @@ -78,7 +61,7 @@ class ScheduledOperationListResource(Resource): """ Add a new scheduled operation. """ - data = parser.parse_args() + data = scheduled_operation_parser.parse_args() scheduled_operation = ScheduledOperation(**data) @@ -111,7 +94,7 @@ class ScheduledOperationResource(Resource): """ Update a scheduled operation. """ - data = parser.parse_args() + data = scheduled_operation_parser.parse_args() assert (id not in data or data.id is None or data.id == id) @@ -162,4 +145,4 @@ class ScheduledOperationResource(Resource): api.add_resource(ScheduledOperationListResource, "/scheduled_operation") api.add_resource(ScheduledOperationResource, - "/scheduled_operation/") + "/scheduled_operation/") diff --git a/accountant/api/views/users.py b/accountant/api/views/users.py index afaffa7..5d35bd3 100644 --- a/accountant/api/views/users.py +++ b/accountant/api/views/users.py @@ -20,7 +20,7 @@ import arrow from functools import wraps from flask import request, g -from flask.ext.restful import Resource, fields, reqparse, marshal_with, marshal_with_field +from flask.ext.restful import Resource, fields, marshal_with, marshal_with_field from accountant import app @@ -30,6 +30,8 @@ from ..fields import Object from ..models.users import User +from .parsers import login_parser + def load_user_from_token(token): return User.verify_auth_token(token) @@ -73,10 +75,6 @@ user_model = { 'active': fields.Boolean } -parser = reqparse.RequestParser() -parser.add_argument('email', type=str, required=True) -parser.add_argument('password', type=str, required=True) - class LoginResource(Resource): @marshal_with(token_model) @@ -84,7 +82,7 @@ class LoginResource(Resource): """ Login to retrieve authentication token. """ - data = parser.parse_args() + data = login_parser.parse_args() user = User.query().filter( User.email == data['email']