From be0d6303fd369376d20d3b0c3daf48327e15f49e Mon Sep 17 00:00:00 2001 From: Frank Huang Date: Tue, 29 Sep 2020 11:36:42 +0900 Subject: [PATCH] Support parsing quirky Chase QFX headers --- ofxparse/ofxparse.py | 7 ++++- tests/fixtures/chase_cc.qfx | 62 +++++++++++++++++++++++++++++++++++++ tests/test_parse.py | 6 ++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/chase_cc.qfx diff --git a/ofxparse/ofxparse.py b/ofxparse/ofxparse.py index 8af6c60..bf6c0e3 100644 --- a/ofxparse/ofxparse.py +++ b/ofxparse/ofxparse.py @@ -85,14 +85,19 @@ def __init__(self, fh): def read_headers(self): head_data = self.fh.read(1024 * 10) + # Headers end at the first XML tag (starting with '<') head_data = head_data[:head_data.find(six.b('<'))] for line in head_data.splitlines(): # Newline? if line.strip() == six.b(""): + continue + + header, sep, value = line.partition(six.b(":")) + if len(sep) == 0: + # No ':' separator found, we probably reached the end of the headers break - header, value = line.split(six.b(":")) header, value = header.strip().upper(), value.strip() self.headers[header] = value diff --git a/tests/fixtures/chase_cc.qfx b/tests/fixtures/chase_cc.qfx new file mode 100644 index 0000000..919afcd --- /dev/null +++ b/tests/fixtures/chase_cc.qfx @@ -0,0 +1,62 @@ + +OFXHEADER:100 +DATA:OFXSGML +VERSION:102 +SECURITY:NONE +ENCODING:USASCII +CHARSET:1252 +COMPRESSION:NONE +OLDFILEUID:NONE +NEWFILEUID:NONE + + + + +0 +INFO + +20200102120000[0:GMT] +ENG + +B1 +10898 + +10898 + + + + +1 + +0 +INFO +Success + + +USD + +0123012301230123 + + +20200101120000[0:GMT] +20200102120000[0:GMT] + +DEBIT +20200101120000[0:GMT] +-10.00 +2020010112341234123412341234123 +SQ *ECCO UN POCO ¦ NATURA + + + +-10.00 +20200102120000[0:GMT] + + +90.00 +20200102120000[0:GMT] + + + + + diff --git a/tests/test_parse.py b/tests/test_parse.py index 78bd779..a46c14a 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -220,6 +220,12 @@ def testMultipleAccounts(self): self.assertEqual('CHECKING', ofx.accounts[0].account_type) self.assertEqual('SAVINGS', ofx.accounts[1].account_type) + def testChaseCCNonAscii(self): + with open_file('chase_cc.qfx') as f: + ofx = OfxParser.parse(f) + self.assertEqual(1, len(ofx.account.statement.transactions)) + self.assertEqual(Decimal('-10.00'), ofx.account.statement.transactions[0].amount) + class TestStringToDate(TestCase): ''' Test the string to date parser '''