Skip to content

Commit

Permalink
Changed QifConverter to use new exception handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
adammansfield committed Sep 26, 2014
1 parent 79027e2 commit 2201ee9
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 68 deletions.
95 changes: 47 additions & 48 deletions powl/transactionconverter.py
@@ -1,6 +1,7 @@
"""Provides conversion for transaction data into an exchange format."""
import textwrap
import time
from powl import exception

class TransactionConverter(object):
"""
Expand Down Expand Up @@ -37,7 +38,7 @@ def __init__(self, log, files, account_types, assets, liabilities,
"""
Parameters
----------
log : powl.logwriter.Log
log : powl.log.Log
Used to log.
files : dict of powl.filesystem.File
Map of account key to files. Every key in files must exist in
Expand All @@ -59,6 +60,12 @@ def __init__(self, log, files, account_types, assets, liabilities,
Multiple account key words can map to the same account.
For example "ent" can map to "Expenses:Entertainment" and
"entertainment" can also map to "Expenses:Entertainment".
Raises
------
ValueError
If a key is files does not have a key in any of assets,
liabilities, revenues, or expenses.
"""
self._log = log
self._files = files
Expand All @@ -68,18 +75,18 @@ def __init__(self, log, files, account_types, assets, liabilities,
self._revenues = revenues
self._expenses = expenses

self._accounts = dict(
self._assets.items() +
self._liabilities.items() +
self._revenues.items() +
self._expenses.items())
self._accounts = dict(self._assets.items() +
self._liabilities.items() +
self._revenues.items() +
self._expenses.items())

for key, value in self._files.items():
if key not in self._accounts.keys():
raise ValueError(
"account key ({0}) ".format(key) +
"for file ({0}) ".format(value.filename) +
"does not have has an associated QIF account")
msg = ("account key ({0}) ".format(key) +
"for file ({0}) ".format(value.filename) +
"does not have has an associated QIF account")
err = exception.create(ValueError, msg)
raise err

def convert(self, date, debit, credit, amount, memo):
"""
Expand Down Expand Up @@ -114,19 +121,12 @@ def convert(self, date, debit, credit, amount, memo):
qif_transfer = self._get_transfer_account(debit, credit)
qif_amount = self._format_amount(debit, amount)
qif_memo = memo
qif_record = self._format_qif_record(
qif_date,
qif_transfer,
qif_amount,
qif_memo)
qif_record = self._format_qif_record(qif_date, qif_transfer,
qif_amount, qif_memo)
qif_file = self._get_qif_file(debit, credit)

self._log_transaction(
qif_date,
qif_file.filename,
qif_transfer,
qif_amount,
qif_memo)
self._log_transaction(qif_date, qif_file.filename, qif_transfer,
qif_amount, qif_memo)
return qif_record, qif_file

def _create_qif_templates(self):
Expand Down Expand Up @@ -164,17 +164,20 @@ def _format_amount(self, debit, amount):
"""
try:
formatted_amount = "{0:.2f}".format(float(amount))
except ValueError:
raise ValueError(
"amount ({0}) cannot be converted to float".format(amount))
except ValueError as err:
msg = "amount ({0}) cannot be converted to float".format(amount)
exception.add_message(err, msg)
raise

if debit in self._expenses:
# Amount should be negative.
return '-' + formatted_amount
elif debit in self._accounts:
return formatted_amount
else:
raise KeyError("account key ({0}) does not exist".format(debit))
msg ="account key ({0}) does not exist".format(debit)
err = exception.create(KeyError, msg)
raise err

def _format_date(self, date):
"""
Expand All @@ -201,18 +204,11 @@ def _format_date(self, date):
"""
try:
return time.strftime("%m/%d/%Y", date)
except TypeError as e:
raise TypeError(
"date ({0}) cannot be converted to MM/DD/YYYY ".format(date) +
"because {0}".format(e.message))
except ValueError as e:
raise ValueError(
"date ({0}) cannot be converted to MM/DD/YYYY ".format(date) +
"because {0}".format(e.message))
except OverflowError as e:
raise OverflowError(
"date ({0}) cannot be converted to MM/DD/YYYY ".format(date) +
"because {0}".format(e.message))
except (ValueError, TypeError, OverflowError) as err:
msg = ("date ({0}) cannot be converted ".format(date) +
"to MM/DD/YYYY ")
exception.add_message(err, msg)
raise

def _format_qif_header(self, account_name, account_type):
"""Format an account name and type into a header for a QIF file."""
Expand Down Expand Up @@ -280,10 +276,11 @@ def _get_qif_file(self, debit, credit):
elif credit in self._files:
return self._files[credit]
else:
raise KeyError(
"neither debit key ({0}) ".format(debit) +
"or credit key ({0}) ".format(credit) +
"has an associated QIF file")
msg = ("neither debit key ({0}) ".format(debit) +
"or credit key ({0}) ".format(credit) +
"has an associated QIF file")
err = exception.create(KeyError, msg)
raise err

def _get_transfer_account(self, debit, credit):
"""
Expand Down Expand Up @@ -317,17 +314,19 @@ def _get_transfer_account(self, debit, credit):
elif credit in self._files:
key = debit
else:
raise KeyError(
"neither debit key ({0}) ".format(debit) +
"or credit key ({0}) ".format(credit) +
"has an associated QIF file")
msg = ("neither debit key ({0}) ".format(debit) +
"or credit key ({0}) ".format(credit) +
"has an associated QIF file")
err = exception.create(KeyError, msg)
raise err

if key in self._accounts:
return self._accounts[key]
else:
raise KeyError(
"account key ({0}) ".format(key) +
"does not have has an associated QIF account")
msg = ("account key ({0}) ".format(key) +
"does not have has an associated QIF account")
err = exception.create(KeyError, msg)
raise err

def _log_transaction(self, date, filename, transfer, amount, memo):
"""
Expand Down
43 changes: 23 additions & 20 deletions test/transactionconverter.test.py
Expand Up @@ -3,6 +3,7 @@
import textwrap
import time
import unittest
from powl import exception
from powl import transactionconverter
from test.mock import filesystem
from test.mock import log
Expand Down Expand Up @@ -60,6 +61,9 @@ def setUp(self):

# convert() tests.
def test__convert(self):
"""
Test sample transaction to convert to QIF format.
"""
date = time.localtime()
debit = self._EXPENSES.keys()[0]
credit = self._FILES.keys()[0]
Expand Down Expand Up @@ -115,7 +119,7 @@ def test__format_amount__invalid_amount(self):
expected_message = "amount ({0}) cannot be converted to float".format(amount)
with self.assertRaises(ValueError) as context:
self._converter._format_amount(debit, amount)
actual_message = context.exception.message
actual_message = exception.get_message(context.exception)
self.assertEqual(expected_message, actual_message)

def test__format_amount__debit_is_expense(self):
Expand Down Expand Up @@ -147,7 +151,7 @@ def test__format_amount__invalid_debit_account(self):
expected_message = "account key ({0}) does not exist".format(debit)
with self.assertRaises(KeyError) as context:
self._converter._format_amount(debit, amount)
actual_message = context.exception.message
actual_message = exception.get_message(context.exception)
self.assertEqual(expected_message, actual_message)

def test__format_amount__output_is_two_decimal_places(self):
Expand Down Expand Up @@ -196,12 +200,11 @@ def test__format_date__overflow_error(self):
Test for a date that cannot be converted to C long.
"""
date = (9999999999,0,0,0,0,0,0,0,0)
expected_message = (
"date ({0}) cannot be converted to MM/DD/YYYY ".format(date) +
"because Python int too large to convert to C long")
expected_message = ("date ({0}) cannot be ".format(date) +
"converted to MM/DD/YYYY ")
with self.assertRaises(OverflowError) as context:
self._converter._format_date(date)
actual_message = context.exception.message
actual_message = exception.get_message(context.exception)
self.assertEqual(expected_message, actual_message)

def test__format_date__past_date(self):
Expand All @@ -218,26 +221,24 @@ def test__format_date__type_error(self):
Test for a date that is invalid.
"""
date = "invalid date type"
expected_message = (
"date ({0}) cannot be converted to MM/DD/YYYY ".format(date) +
"because argument must be 9-item sequence, not str")
expected_message = ("date ({0}) cannot be ".format(date) +
"converted to MM/DD/YYYY ")
with self.assertRaises(TypeError) as context:
self._converter._format_date(date)
actual_message = context.exception.message
actual_message = exception.get_message(context.exception)
self.assertEqual(expected_message, actual_message)

def test__format_date__value_error(self):
"""
Test for a date that is out of range.
"""
date = (1000,0,0,0,0,0,0,0,0)
expected = (
"date ({0}) cannot be converted to MM/DD/YYYY ".format(date) +
"because year out of range")
expected_message = ("date ({0}) cannot be ".format(date) +
"converted to MM/DD/YYYY ")
with self.assertRaises(ValueError) as context:
self._converter._format_date(date)
actual = context.exception.message
self.assertEqual(expected, actual)
actual_message = exception.get_message(context.exception)
self.assertEqual(expected_message, actual_message)

# _get_qif_file() tests.
def test__get_qif_file__both_have_file(self):
Expand Down Expand Up @@ -265,7 +266,7 @@ def test__get_qif_file__both_have_no_file(self):
"has an associated QIF file")
with self.assertRaises(KeyError) as context:
self._converter._get_qif_file(debit, credit)
actual_message = context.exception.message
actual_message = exception.get_message(context.exception)
self.assertEqual(expected_message, actual_message)

def test__get_qif_file__debit_has_file_and_credit_has_no_file(self):
Expand Down Expand Up @@ -316,7 +317,7 @@ def test__get_transfer_account__both_have_no_file(self):
"has an associated QIF file")
with self.assertRaises(KeyError) as context:
self._converter._get_transfer_account(debit, credit)
actual_message = context.exception.message
actual_message = exception.get_message(context.exception)
self.assertEqual(expected_message, actual_message)

def test__get_transfer_account__debit_has_file_and_credit_has_no_file(self):
Expand Down Expand Up @@ -353,7 +354,7 @@ def test__get_transfer_account__account_key_not_in_accounts(self):
"does not have has an associated QIF account")
with self.assertRaises(KeyError) as context:
self._converter._get_transfer_account(debit, credit)
actual_message = context.exception.message
actual_message = exception.get_message(context.exception)
self.assertEqual(expected_message, actual_message)

# _get_transfer_account() with _get_qif_file() tests.
Expand Down Expand Up @@ -391,8 +392,10 @@ def test__init__key_in_files_is_not_in_accounts(self):
transactionconverter.QifConverter(
self._log, files, self._ACCOUNT_TYPES, self._ASSETS,
self._LIABILITIES, self._REVENUES, self._EXPENSES)
actual_message = context.exception.message
actual_message = exception.get_message(context.exception)
self.assertEqual(expected_message, actual_message)


if __name__ == '__main__':
unittest.main(verbosity=2)
unittest.main()

0 comments on commit 2201ee9

Please sign in to comment.