def test_should_capitalize_hyphenated_names(self, mock_open): xml = '''\ <ePismo> <TrescPisma> <Dluznicy> <Dluznik> <OsobaFizyczna> <Imie>ZA\u017b\xd3\u0141\u0106</Imie> <Nazwisko>G\u0118\u015aL\u0104-JA\u0179\u0143</Nazwisko> <Oznaczenie> <regon>123456789</regon> </Oznaczenie> <Odpowiedz>nie</Odpowiedz> </OsobaFizyczna> </Dluznik> </Dluznicy> </TrescPisma> </ePismo>''' mock_open.return_value.__enter__.return_value = io.StringIO(xml) parser = BankReplyParser('/path/to/file.xml') self.assertEqual('G\u0119\u015bl\u0105-Ja\u017a\u0144', list(parser.entities).pop().last_name)
def test_should_parse_single_entity(self, mock_open): xml = '''\ <ePismo> <TrescPisma> <Dluznicy> <Dluznik> <OsobaFizyczna> <Imie>Jan</Imie> <Nazwisko>Kowalski</Nazwisko> <Oznaczenie> <Pesel>12345678900</Pesel> </Oznaczenie> <Odpowiedz>tak</Odpowiedz> </OsobaFizyczna> </Dluznik> </Dluznicy> </TrescPisma> </ePismo>''' mock_open.return_value.__enter__.return_value = io.StringIO(xml) parser = BankReplyParser('/path/to/file.xml') entities = list(parser.entities) self.assertEqual(1, len(entities)) entity = entities.pop() self.assertIsInstance(entity, NaturalPerson) self.assertEqual( NaturalPerson(first_name='Jan', last_name='Kowalski', id=Id(name='PESEL', value='12345678900'), has_account=True), entity)
def test_should_return_naive_date_and_time(self, mock_open): mock_open.return_value.__enter__.return_value = io.StringIO( '<ePismo dataPisma="2016-08-01T12:01:05.306000"/>') parser = BankReplyParser('/path/to/file.xml') self.assertIsInstance(parser.date, datetime.datetime) self.assertEqual(datetime.datetime(2016, 8, 1, 12, 1, 5, 306000), parser.date)
def test_should_convert_identity_name_to_uppercase(self, mock_open): xml = '''\ <ePismo> <TrescPisma> <Dluznicy> <Dluznik> <OsobaFizyczna> <Imie>Jan</Imie> <Nazwisko>Kowalski</Nazwisko> <Oznaczenie> <regon>123456789</regon> </Oznaczenie> <Odpowiedz>tak</Odpowiedz> </OsobaFizyczna> </Dluznik> </Dluznicy> </TrescPisma> </ePismo>''' mock_open.return_value.__enter__.return_value = io.StringIO(xml) parser = BankReplyParser('/path/to/file.xml') self.assertTrue(list(parser.entities).pop().id.name.isupper())
def test_should_parse_natural_person_and_legal_entity_differently( self, mock_open): xml = '''\ <ePismo> <TrescPisma> <Dluznicy> <Dluznik> <OsobaFizyczna> <Imie>Jan</Imie> <Nazwisko>Kowalski</Nazwisko> <Oznaczenie> <Pesel>12345678900</Pesel> </Oznaczenie> <Odpowiedz>tak</Odpowiedz> </OsobaFizyczna> </Dluznik> <Dluznik> <OsobaPrawna> <NazwaInstytucji>Firma Sp. z O.O.</NazwaInstytucji> <Oznaczenie> <NIP>1234567890</NIP> </Oznaczenie> <Odpowiedz>nie</Odpowiedz> </OsobaPrawna> </Dluznik> <Dluznik> <OsobaFizyczna> <Imie>Anna</Imie> <Nazwisko>Nowak</Nazwisko> <Oznaczenie> <Pesel>00987654321</Pesel> </Oznaczenie> <Odpowiedz>nie</Odpowiedz> </OsobaFizyczna> </Dluznik> </Dluznicy> </TrescPisma> </ePismo>''' mock_open.return_value.__enter__.return_value = io.StringIO(xml) parser = BankReplyParser('/path/to/file.xml') entities = list(parser.entities) self.assertEqual(3, len(entities)) self.assertListEqual([ NaturalPerson(first_name='Jan', last_name='Kowalski', id=Id(name='PESEL', value='12345678900'), has_account=True), LegalEntity(name='Firma Sp. z O.O.', id=Id(name='NIP', value='1234567890'), has_account=False), NaturalPerson(first_name='Anna', last_name='Nowak', id=Id(name='PESEL', value='00987654321'), has_account=False) ], entities)
def test_should_return_empty_values_of_missing_elements(self, mock_open): mock_open.return_value.__enter__.return_value = io.BytesIO(b'<root/>') parser = BankReplyParser('/path/to/file.xml') self.assertIsNone(parser.date) self.assertIsNone(parser.bank_code) self.assertListEqual([], list(parser.entities))
def __init__(self, file_paths): assert isinstance(file_paths, collections.Iterable), 'expected an iterable' self._banks = set() self._debtors = set() self._replies = collections.defaultdict(dict) logger.info('Scanning working directory...') for i, file_path in enumerate(sorted(file_paths)): try: parser = BankReplyParser(file_path) bank = Bank(parser.bank_code) self._banks.add(bank) for entity in parser.entities: reply = Reply(bank, parser.date, entity.has_account, file_path) debtor = Debtor(entity) self._debtors.add(debtor) if bank in self._replies[debtor]: previous_reply = self._replies[debtor][bank] if previous_reply.has_account != reply.has_account: logger.warning( 'Inconsistent replies from the same bank %s for %s', bank, debtor) if previous_reply.date == reply.date: del self._replies[debtor][bank] continue elif previous_reply.date > reply.date: continue self._replies[debtor][bank] = reply except Exception: logger.error( 'Invalid or not well-formed XML content at %s', file_path) else: logger.debug( 'Processed file %d of %d "%s"', i + 1, len(file_paths), file_path)
def test_should_return_date_and_time_with_timezone(self, mock_open): mock_open.return_value.__enter__.return_value = io.StringIO( '<ePismo dataPisma="2016-08-01T12:30:30.8929287+02:00"/>') parser = BankReplyParser('/path/to/file.xml') self.assertIsInstance(parser.date, datetime.datetime) self.assertEqual( datetime.datetime(2016, 8, 1, 12, 30, 30, 892928, tzinfo=tzoffset(None, 7200)), parser.date)
def test_should_not_require_xml_signature(self, mock_open): mock_open.return_value.__enter__.return_value = io.BytesIO(b'''\ <ePismo dataPisma="2016-12-31"> <NadawcaPisma> <KodBanku>12345678</KodBanku> </NadawcaPisma> </ePismo>''') parser = BankReplyParser('/path/to/file.xml') self.assertEqual(datetime.datetime(2016, 12, 31, 0, 0), parser.date) self.assertEqual('12345678', parser.bank_code) self.assertListEqual([], list(parser.entities))
def test_should_decode_unicode_values(self, mock_open): xml = '''<ePismo> <TrescPisma> <Dluznicy> <Dluznik> <OsobaFizyczna> <Imie>ZAŻÓŁĆ</Imie> <Nazwisko>GĘŚLĄ JAŹŃ</Nazwisko> <Oznaczenie> <regon>123456789</regon> </Oznaczenie> <Odpowiedz>tak</Odpowiedz> </OsobaFizyczna> </Dluznik> <Dluznik> <OsobaPrawna> <NazwaInstytucji>ZAŻÓŁĆ GĘŚLĄ-JAŹŃ</NazwaInstytucji> <Oznaczenie> <NIP>1234567890</NIP> </Oznaczenie> <Odpowiedz>nie</Odpowiedz> </OsobaPrawna> </Dluznik> </Dluznicy> </TrescPisma> </ePismo>'''.encode('utf-8') mock_open.return_value.__enter__.return_value = io.BytesIO(xml) parser = BankReplyParser('/path/to/file.xml') entity1, entity2 = list(parser.entities) self.assertEqual('Za\u017c\xf3\u0142\u0107', entity1.first_name) self.assertEqual('G\u0119\u015bl\u0105 Ja\u017a\u0144', entity1.last_name) self.assertEqual( 'ZA\u017b\xd3\u0141\u0106 G\u0118\u015aL\u0104-JA\u0179\u0143', entity2.name)
def test_should_return_original_string_if_date_cannot_be_parsed( self, mock_open): mock_open.return_value.__enter__.return_value = io.StringIO( '<ePismo dataPisma="lorem"/>') parser = BankReplyParser('/path/to/file.xml') self.assertEqual('lorem', parser.date)
def test_should_return_none_if_date_is_missing(self, mock_open): mock_open.return_value.__enter__.return_value = io.StringIO( '<ePismo />') parser = BankReplyParser('/path/to/file.xml') self.assertIsNone(parser.date)