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']