mt940 package

Submodules

mt940.json module

class mt940.json.JSONEncoder(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, encoding='utf-8', default=None)[source]

Bases: json.encoder.JSONEncoder

default(value)[source]

Implement this method in a subclass such that it returns a serializable object for o, or calls the base implementation (to raise a TypeError).

For example, to support arbitrary iterators, you could implement default like this:

def default(self, o):
    try:
        iterable = iter(o)
    except TypeError:
        pass
    else:
        return list(iterable)
    # Let the base class default method raise the TypeError
    return JSONEncoder.default(self, o)

mt940.models module

class mt940.models.Amount(amount, status, currency=None, **kwargs)[source]

Bases: mt940.models.Model

Amount object containing currency and amount

Parameters:
  • amount (str) – Amount using either a , or a . as decimal separator
  • status (str) – Either C or D for credit or debit respectively
  • currency (str) – A 3 letter currency (e.g. EUR)
>>> Amount('123.45', 'C', 'EUR')
<123.45 EUR>
>>> Amount('123.45', 'D', 'EUR')
<-123.45 EUR>
class mt940.models.Balance(status=None, amount=None, date=None, **kwargs)[source]

Bases: mt940.models.Model

Parse balance statement

Parameters:
  • status (str) – Either C or D for credit or debit respectively
  • amount (Amount) – Object containing the amount and currency
  • date (date) – The balance date
>>> balance = Balance('C', '0.00', Date(2010, 7, 22))
>>> balance.status
'C'
>>> balance.amount.amount
Decimal('0.00')
>>> isinstance(balance.date, Date)
True
>>> balance.date.year, balance.date.month, balance.date.day
(2010, 7, 22)
>>> Balance()
<None @ None>
class mt940.models.Date[source]

Bases: datetime.date, mt940.models.Model

Just a regular date object which supports dates given as strings

>>> Date(year='2000', month='1', day='2')
Date(2000, 1, 2)
>>> Date(year='123', month='1', day='2')
Date(2123, 1, 2)
Parameters:
  • year (str) – Year (0-100), will automatically add 2000 when needed
  • month (str) – Month
  • day (str) – Day
class mt940.models.DateTime[source]

Bases: datetime.datetime, mt940.models.Model

Just a regular datetime object which supports dates given as strings

>>> DateTime(year='2000', month='1', day='2', hour='3', minute='4',
...          second='5', microsecond='6')
DateTime(2000, 1, 2, 3, 4, 5, 6)
>>> DateTime(year='123', month='1', day='2', hour='3', minute='4',
...          second='5', microsecond='6')
DateTime(2123, 1, 2, 3, 4, 5, 6)
>>> DateTime(2000, 1, 2, 3, 4, 5, 6)
DateTime(2000, 1, 2, 3, 4, 5, 6)
>>> DateTime(year='123', month='1', day='2', hour='3', minute='4',
...          second='5', microsecond='6', tzinfo=FixedOffset('60'))
DateTime(2123, 1, 2, 3, 4, 5, 6, tzinfo=<mt940.models.FixedOffset ...>)
Parameters:
  • year (str) – Year (0-100), will automatically add 2000 when needed
  • month (str) – Month
  • day (str) – Day
  • hour (str) – Hour
  • minute (str) – Minute
  • second (str) – Second
  • microsecond (str) – Microsecond
  • tzinfo (tzinfo) – Timezone information. Overwrites offset
  • offset (str) – Timezone offset in minutes, generates a tzinfo object with the given offset if no tzinfo is available.
class mt940.models.FixedOffset(offset=0, name=None)[source]

Bases: datetime.tzinfo

Fixed time offset based on the Python docs Source: https://docs.python.org/2/library/datetime.html#tzinfo-objects

>>> offset = FixedOffset(60)
>>> offset.utcoffset(None).total_seconds()
3600.0
>>> offset.dst(None)
datetime.timedelta(0)
>>> offset.tzname(None)
'60'
dst(dt)[source]

datetime -> DST offset in minutes east of UTC.

tzname(dt)[source]

datetime -> string name of time zone.

utcoffset(dt)[source]

datetime -> minutes east of UTC (negative for west of UTC).

class mt940.models.Model[source]

Bases: object

class mt940.models.SumAmount(*args, **kwargs)[source]

Bases: mt940.models.Amount

class mt940.models.Transaction(transactions, data=None)[source]

Bases: mt940.models.Model

update(data)[source]
class mt940.models.Transactions(processors=None, tags=None)[source]

Bases: _abcoll.Sequence

Collection of Transaction objects with global properties such as begin and end balance

DEFAULT_PROCESSORS = {'post_account_identification': [], 'post_available_balance': [], 'post_closing_balance': [], 'post_date_time_indication': [], 'post_final_closing_balance': [], 'post_final_opening_balance': [], 'post_floor_limit_indicator': [], 'post_forward_available_balance': [], 'post_intermediate_closing_balance': [], 'post_intermediate_opening_balance': [], 'post_non_swift': [], 'post_opening_balance': [], 'post_related_reference': [], 'post_statement': [<function date_cleanup_post_processor>], 'post_statement_number': [], 'post_sum_credit_entries': [], 'post_sum_debit_entries': [], 'post_transaction_details': [<function transaction_details_post_processor>], 'post_transaction_reference_number': [], 'pre_account_identification': [], 'pre_available_balance': [], 'pre_closing_balance': [], 'pre_date_time_indication': [], 'pre_final_closing_balance': [], 'pre_final_opening_balance': [], 'pre_floor_limit_indicator': [], 'pre_forward_available_balance': [], 'pre_intermediate_closing_balance': [], 'pre_intermediate_opening_balance': [], 'pre_non_swift': [], 'pre_opening_balance': [], 'pre_related_reference': [], 'pre_statement': [<function date_fixup_pre_processor>], 'pre_statement_number': [], 'pre_sum_credit_entries': [], 'pre_sum_debit_entries': [], 'pre_transaction_details': [], 'pre_transaction_reference_number': []}

Using the processors you can pre-process data before creating objects and modify them after creating the objects

currency
static defaultTags()[source]
classmethod normalize_tag_id(tag_id)[source]
parse(data)[source]

Parses mt940 data, expects a string with data

Parameters:data (str) – The MT940 data

Returns: list of Transaction

sanitize_tag_id_matches(matches)[source]
classmethod strip(lines)[source]

mt940.parser module

Format

Sources:

[] = optional
! = fixed length
a = Text
x = Alphanumeric, seems more like text actually. Can include special
    characters (slashes) and whitespace as well as letters and numbers
d = Numeric separated by decimal (usually comma)
c = Code list value
n = Numeric
mt940.parser.parse(src, encoding=None, processors=None, tags=None)[source]

Parses mt940 data and returns transactions object

Parameters:src – file handler to read, filename to read or raw data as string
Returns:Collection of transactions
Return type:Transactions

mt940.processors module

mt940.processors.add_currency_pre_processor(currency, overwrite=True)[source]
mt940.processors.date_cleanup_post_processor(transactions, tag, tag_dict, result)[source]
mt940.processors.date_fixup_pre_processor(transactions, tag, tag_dict, *args)[source]

Replace illegal February 29, 30 dates with the last day of February.

German banks use a variant of the 30/360 interest rate calculation, where each month has always 30 days even February. Python’s datetime module won’t accept such dates.

mt940.processors.mBank_set_iph_id(transactions, tag, tag_dict, *args)[source]

mBank Collect uses ID IPH to distinguish between virtual accounts, adding iph_id may be helpful in further processing

mt940.processors.mBank_set_tnr(transactions, tag, tag_dict, *args)[source]

mBank Collect states TNR in transaction details as unique id for transactions, that may be used to identify the same transactions in different statement files eg. partial mt942 and full mt940 Information about tnr uniqueness has been obtained from mBank support, it lacks in mt940 mBank specification.

mt940.processors.mBank_set_transaction_code(transactions, tag, tag_dict, *args)[source]

mBank Collect uses transaction code 911 to distinguish icoming mass payments transactions, adding transaction_code may be helpful in further processing

mt940.processors.transaction_details_post_processor(transactions, tag, tag_dict, result, space=False)[source]

Parse the extra details in some transaction formats such as the 60-65 keys.

Parameters:
mt940.processors.transaction_details_post_processor_with_space(transactions, tag, tag_dict, result)

Parse the extra details in some transaction formats such as the 60-65 keys.

Parameters:

mt940.tags module

Format

Sources:

[] = optional
! = fixed length
a = Text
x = Alphanumeric, seems more like text actually. Can include special
    characters (slashes) and whitespace as well as letters and numbers
d = Numeric separated by decimal (usually comma)
c = Code list value
n = Numeric
class mt940.tags.AccountIdentification[source]

Bases: mt940.tags.Tag

Account identification

Pattern: 35x

id = 25
logger = <logging.Logger object>
name = 'AccountIdentification'
pattern = '(?P<account_identification>.{0,35})'
slug = 'account_identification'
class mt940.tags.AvailableBalance[source]

Bases: mt940.tags.BalanceBase

id = 64
logger = <logging.Logger object>
name = 'AvailableBalance'
slug = 'available_balance'
class mt940.tags.BalanceBase[source]

Bases: mt940.tags.Tag

Balance base

Pattern: 1!a6!n3!a15d

pattern = '^\n (?P<status>[DC]) # 1!a Debit/Credit\n (?P<year>\\d{2}) # 6!n Value Date (YYMMDD)\n (?P<month>\\d{2})\n (?P<day>\\d{2})\n (?P<currency>.{3}) # 3!a Currency\n (?P<amount>[0-9,]{0,16}) # 15d Amount (includes decimal sign, so 16)\n '
class mt940.tags.ClosingBalance[source]

Bases: mt940.tags.BalanceBase

id = 62
logger = <logging.Logger object>
name = 'ClosingBalance'
slug = 'closing_balance'
class mt940.tags.DateTimeIndication[source]

Bases: mt940.tags.Tag

Date/Time indication at which the report was created

Pattern: 6!n4!n1! x4!n

id = 13
logger = <logging.Logger object>
name = 'DateTimeIndication'
pattern = '^\n (?P<year>\\d{2})\n (?P<month>\\d{2})\n (?P<day>\\d{2})\n (?P<hour>\\d{2})\n (?P<minute>\\d{2})\n (\\+(?P<offset>\\d{4})|)\n '
slug = 'date_time_indication'
class mt940.tags.FinalClosingBalance[source]

Bases: mt940.tags.ClosingBalance

id = '62F'
logger = <logging.Logger object>
name = 'FinalClosingBalance'
slug = 'final_closing_balance'
class mt940.tags.FinalOpeningBalance[source]

Bases: mt940.tags.BalanceBase

id = '60F'
logger = <logging.Logger object>
name = 'FinalOpeningBalance'
slug = 'final_opening_balance'
class mt940.tags.FloorLimitIndicator[source]

Bases: mt940.tags.Tag

Floor limit indicator indicates the minimum value reported for debit and credit amounts

Pattern: :34F:GHSC0,00

id = 34
logger = <logging.Logger object>
name = 'FloorLimitIndicator'
pattern = '^\n (?P<currency>[A-Z]{3}) # 3!a Currency\n (?P<status>[DC ]?) # 2a Debit/Credit Mark\n (?P<amount>[0-9,]{0,16}) # 15d Amount (includes decimal sign, so 16)\n $'
slug = 'floor_limit_indicator'
class mt940.tags.ForwardAvailableBalance[source]

Bases: mt940.tags.BalanceBase

id = 65
logger = <logging.Logger object>
name = 'ForwardAvailableBalance'
slug = 'forward_available_balance'
class mt940.tags.IntermediateClosingBalance[source]

Bases: mt940.tags.ClosingBalance

id = '62M'
logger = <logging.Logger object>
name = 'IntermediateClosingBalance'
slug = 'intermediate_closing_balance'
class mt940.tags.IntermediateOpeningBalance[source]

Bases: mt940.tags.BalanceBase

id = '60M'
logger = <logging.Logger object>
name = 'IntermediateOpeningBalance'
slug = 'intermediate_opening_balance'
class mt940.tags.NonSwift[source]

Bases: mt940.tags.Tag

Non-swift extension for MT940 containing extra information. The actual definition is not consistent between banks so the current implementation is a tad limited. Feel free to extend the implementation and create a pull request with a better version :)

It seems this could be anything so we’ll have to be flexible about it.

Pattern: 2!n35x | *x

id = 'NS'
logger = <logging.Logger object>
name = 'NonSwift'
pattern = '\n (?P<non_swift>\n (\n (\\d{2}.{0,})\n (\\n\\d{2}.{0,})*\n )|(\n [^\\n]*\n )\n )\n $'
class scope(transactions, data=None)[source]

Bases: mt940.models.Transaction, mt940.models.Transactions

slug = 'non_swift'
sub_pattern = '\n (?P<ns_id>\\d{2})(?P<ns_data>.{0,})\n '
sub_pattern_m = <_sre.SRE_Pattern object>
class mt940.tags.OpeningBalance[source]

Bases: mt940.tags.BalanceBase

id = 60
logger = <logging.Logger object>
name = 'OpeningBalance'
slug = 'opening_balance'
class mt940.tags.RelatedReference[source]

Bases: mt940.tags.Tag

Related reference

Pattern: 16x

id = 21
logger = <logging.Logger object>
name = 'RelatedReference'
pattern = '(?P<related_reference>.{0,16})'
slug = 'related_reference'
class mt940.tags.Statement[source]

Bases: mt940.tags.Tag

Pattern: 6!n[4!n]2a[1!a]15d1!a3!c23x[//16x]

id = 61
logger = <logging.Logger object>
name = 'Statement'
pattern = '^\n (?P<year>\\d{2}) # 6!n Value Date (YYMMDD)\n (?P<month>\\d{2})\n (?P<day>\\d{2})\n (?P<entry_month>\\d{2})? # [4!n] Entry Date (MMDD)\n (?P<entry_day>\\d{2})?\n (?P<status>[A-Z]?[DC]) # 2a Debit/Credit Mark\n (?P<funds_code>[A-Z])? # [1!a] Funds Code (3rd character of the currency\n # code, if needed)\n \\n? # apparently some banks (sparkassen) incorporate newlines here\n (?P<amount>[\\d,]{1,15}) # 15d Amount\n (?P<id>[A-Z][A-Z0-9 ]{3})? # 1!a3!c Transaction Type Identification Code\n (?P<customer_reference>.{0,16}) # 16x Customer Reference\n (//(?P<bank_reference>.{0,23}))? # [//23x] Bank Reference\n (\\n?(?P<extra_details>.{0,34}))? # [34x] Supplementary Details\n $'
scope

alias of mt940.models.Transaction

slug = 'statement'
class mt940.tags.StatementASNB[source]

Bases: mt940.tags.Statement

From: https://www.sepaforcorporates.com/swift-for-corporates

Pattern: 6!n[4!n]2a[1!a]15d1!a3!c16x[//16x] [34x]

But ASN bank puts the IBAN in the customer reference, which is acording to Wikipedia at most 34 characters.

So this is the new pattern:

Pattern: 6!n[4!n]2a[1!a]15d1!a3!c34x[//16x] [34x]

pattern = '^\n (?P<year>\\d{2}) # 6!n Value Date (YYMMDD)\n (?P<month>\\d{2})\n (?P<day>\\d{2})\n (?P<entry_month>\\d{2})? # [4!n] Entry Date (MMDD)\n (?P<entry_day>\\d{2})?\n (?P<status>[A-Z]?[DC]) # 2a Debit/Credit Mark\n (?P<funds_code>[A-Z])? # [1!a] Funds Code (3rd character of the currency\n # code, if needed)\n \\n? # apparently some banks (sparkassen) incorporate newlines here\n (?P<amount>[\\d,]{1,15}) # 15d Amount\n (?P<id>[A-Z][A-Z0-9 ]{3})? # 1!a3!c Transaction Type Identification Code\n (?P<customer_reference>.{0,34}) # 34x Customer Reference\n (//(?P<bank_reference>.{0,16}))? # [//16x] Bank Reference\n (\\n?(?P<extra_details>.{0,34}))? # [34x] Supplementary Details\n $'
class mt940.tags.StatementNumber[source]

Bases: mt940.tags.Tag

Statement number / sequence number

Pattern: 5n[/5n]

id = 28
logger = <logging.Logger object>
name = 'StatementNumber'
pattern = '\n (?P<statement_number>\\d{1,5}) # 5n\n (?:/?(?P<sequence_number>\\d{1,5}))? # [/5n]\n $'
slug = 'statement_number'
class mt940.tags.SumCreditEntries[source]

Bases: mt940.tags.SumEntries

id = '90C'
logger = <logging.Logger object>
name = 'SumCreditEntries'
slug = 'sum_credit_entries'
status = 'C'
class mt940.tags.SumDebitEntries[source]

Bases: mt940.tags.SumEntries

id = '90D'
logger = <logging.Logger object>
name = 'SumDebitEntries'
slug = 'sum_debit_entries'
status = 'D'
class mt940.tags.SumEntries[source]

Bases: mt940.tags.Tag

Number and Sum of debit Entries

id = 90
logger = <logging.Logger object>
name = 'SumEntries'
pattern = '^\n (?P<number>\\d*)\n (?P<currency>.{3}) # 3!a Currency\n (?P<amount>[\\d,]{1,15}) # 15d Amount\n '
slug = 'sum_entries'
class mt940.tags.Tag[source]

Bases: object

RE_FLAGS = 98
id = 0
parse(transactions, value)[source]
scope

alias of mt940.models.Transactions

class mt940.tags.Tags[source]

Bases: enum.Enum

ACCOUNT_IDENTIFICATION = <mt940.tags.AccountIdentification object>
AVAILABLE_BALANCE = <mt940.tags.AvailableBalance object>
CLOSING_BALANCE = <mt940.tags.ClosingBalance object>
DATE_TIME_INDICATION = <mt940.tags.DateTimeIndication object>
FINAL_CLOSING_BALANCE = <mt940.tags.FinalClosingBalance object>
FINAL_OPENING_BALANCE = <mt940.tags.FinalOpeningBalance object>
FLOOR_LIMIT_INDICATOR = <mt940.tags.FloorLimitIndicator object>
FORWARD_AVAILABLE_BALANCE = <mt940.tags.ForwardAvailableBalance object>
INTERMEDIATE_CLOSING_BALANCE = <mt940.tags.IntermediateClosingBalance object>
INTERMEDIATE_OPENING_BALANCE = <mt940.tags.IntermediateOpeningBalance object>
NON_SWIFT = <mt940.tags.NonSwift object>
OPENING_BALANCE = <mt940.tags.OpeningBalance object>
RELATED_REFERENCE = <mt940.tags.RelatedReference object>
STATEMENT = <mt940.tags.Statement object>
STATEMENT_NUMBER = <mt940.tags.StatementNumber object>
SUM_CREDIT_ENTRIES = <mt940.tags.SumCreditEntries object>
SUM_DEBIT_ENTRIES = <mt940.tags.SumDebitEntries object>
SUM_ENTRIES = <mt940.tags.SumEntries object>
TRANSACTION_DETAILS = <mt940.tags.TransactionDetails object>
TRANSACTION_REFERENCE_NUMBER = <mt940.tags.TransactionReferenceNumber object>
class mt940.tags.TransactionDetails[source]

Bases: mt940.tags.Tag

Transaction details

Pattern: 6x65x

id = 86
logger = <logging.Logger object>
name = 'TransactionDetails'
pattern = '\n (?P<transaction_details>(([\\s\\S]{0,65}\\r?\\n?){0,8}[\\s\\S]{0,65}))\n '
scope

alias of mt940.models.Transaction

slug = 'transaction_details'
class mt940.tags.TransactionReferenceNumber[source]

Bases: mt940.tags.Tag

Transaction reference number

Pattern: 16x

id = 20
logger = <logging.Logger object>
name = 'TransactionReferenceNumber'
pattern = '(?P<transaction_reference>.{0,16})'
slug = 'transaction_reference_number'

mt940.utils module

class mt940.utils.Strip[source]

Bases: enum.IntEnum

BOTH = 3
LEFT = 1
NONE = 0
RIGHT = 2
mt940.utils.coalesce(*args)[source]

Return the first non-None argument

>>> coalesce()
>>> coalesce(0, 1)
0
>>> coalesce(None, 0)
0
mt940.utils.join_lines(string, strip=<Strip.BOTH: 3>)[source]

Join strings together and strip whitespace in between if needed

Module contents

class mt940.JSONEncoder(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, encoding='utf-8', default=None)[source]

Bases: json.encoder.JSONEncoder

default(value)[source]

Implement this method in a subclass such that it returns a serializable object for o, or calls the base implementation (to raise a TypeError).

For example, to support arbitrary iterators, you could implement default like this:

def default(self, o):
    try:
        iterable = iter(o)
    except TypeError:
        pass
    else:
        return list(iterable)
    # Let the base class default method raise the TypeError
    return JSONEncoder.default(self, o)
mt940.parse(src, encoding=None, processors=None, tags=None)[source]

Parses mt940 data and returns transactions object

Parameters:src – file handler to read, filename to read or raw data as string
Returns:Collection of transactions
Return type:Transactions