1
1
# bic.py - functions for handling ISO 9362 Business identifier codes
2
2
#
3
3
# Copyright (C) 2015 Lifealike Ltd
4
- # Copyright (C) 2017-2018 Arthur de Jong
4
+ # Copyright (C) 2017-2025 Arthur de Jong
5
5
#
6
6
# This library is free software; you can redistribute it and/or
7
7
# modify it under the terms of the GNU Lesser General Public
28
28
and a 2 character location code, optionally followed by a three character
29
29
branch code.
30
30
31
+ More information:
32
+
33
+ * https://en.wikipedia.org/wiki/ISO_9362
34
+
31
35
>>> validate('AGRIFRPP882')
32
36
'AGRIFRPP882'
33
37
>>> validate('ABNA BE 2A')
55
59
from stdnum .util import clean
56
60
57
61
58
- _bic_re = re .compile (r'^[A-Z]{6}[0-9A-Z]{2}([0-9A-Z]{3})?$' )
62
+ _bic_re = re .compile (r'^[A-Z]{4}(?P<country_code>[A-Z]{2})[0-9A-Z]{2}([0-9A-Z]{3})?$' )
63
+
64
+
65
+ # Valid BIC country codes are ISO 3166-1 alpha-2 with the addition of
66
+ # XK for the Republic of Kosovo
67
+ # It seems that some of the countries included here don't currently have
68
+ # any banks with a BIC code (e.g. Antarctica, Iran, Myanmar)
69
+ _country_codes = {
70
+ 'AD' , 'AE' , 'AF' , 'AG' , 'AI' , 'AL' , 'AM' , 'AO' , 'AQ' , 'AR' , 'AS' , 'AT' , 'AU' ,
71
+ 'AW' , 'AX' , 'AZ' , 'BA' , 'BB' , 'BD' , 'BE' , 'BF' , 'BG' , 'BH' , 'BI' , 'BJ' , 'BL' ,
72
+ 'BM' , 'BN' , 'BO' , 'BQ' , 'BR' , 'BS' , 'BT' , 'BV' , 'BW' , 'BY' , 'BZ' , 'CA' , 'CC' ,
73
+ 'CD' , 'CF' , 'CG' , 'CH' , 'CI' , 'CK' , 'CL' , 'CM' , 'CN' , 'CO' , 'CR' , 'CU' , 'CV' ,
74
+ 'CW' , 'CX' , 'CY' , 'CZ' , 'DE' , 'DJ' , 'DK' , 'DM' , 'DO' , 'DZ' , 'EC' , 'EE' , 'EG' ,
75
+ 'EH' , 'ER' , 'ES' , 'ET' , 'FI' , 'FJ' , 'FK' , 'FM' , 'FO' , 'FR' , 'GA' , 'GB' , 'GD' ,
76
+ 'GE' , 'GF' , 'GG' , 'GH' , 'GI' , 'GL' , 'GM' , 'GN' , 'GP' , 'GQ' , 'GR' , 'GS' , 'GT' ,
77
+ 'GU' , 'GW' , 'GY' , 'HK' , 'HM' , 'HN' , 'HR' , 'HT' , 'HU' , 'ID' , 'IE' , 'IL' , 'IM' ,
78
+ 'IN' , 'IO' , 'IQ' , 'IR' , 'IS' , 'IT' , 'JE' , 'JM' , 'JO' , 'JP' , 'KE' , 'KG' , 'KH' ,
79
+ 'KI' , 'KM' , 'KN' , 'KP' , 'KR' , 'KW' , 'KY' , 'KZ' , 'LA' , 'LB' , 'LC' , 'LI' , 'LK' ,
80
+ 'LR' , 'LS' , 'LT' , 'LU' , 'LV' , 'LY' , 'MA' , 'MC' , 'MD' , 'ME' , 'MF' , 'MG' , 'MH' ,
81
+ 'MK' , 'ML' , 'MM' , 'MN' , 'MO' , 'MP' , 'MQ' , 'MR' , 'MS' , 'MT' , 'MU' , 'MV' , 'MW' ,
82
+ 'MX' , 'MY' , 'MZ' , 'NA' , 'NC' , 'NE' , 'NF' , 'NG' , 'NI' , 'NL' , 'NO' , 'NP' , 'NR' ,
83
+ 'NU' , 'NZ' , 'OM' , 'PA' , 'PE' , 'PF' , 'PG' , 'PH' , 'PK' , 'PL' , 'PM' , 'PN' , 'PR' ,
84
+ 'PS' , 'PT' , 'PW' , 'PY' , 'QA' , 'RE' , 'RO' , 'RS' , 'RU' , 'RW' , 'SA' , 'SB' , 'SC' ,
85
+ 'SD' , 'SE' , 'SG' , 'SH' , 'SI' , 'SJ' , 'SK' , 'SL' , 'SM' , 'SN' , 'SO' , 'SR' , 'SS' ,
86
+ 'ST' , 'SV' , 'SX' , 'SY' , 'SZ' , 'TC' , 'TD' , 'TF' , 'TG' , 'TH' , 'TJ' , 'TK' , 'TL' ,
87
+ 'TM' , 'TN' , 'TO' , 'TR' , 'TT' , 'TV' , 'TW' , 'TZ' , 'UA' , 'UG' , 'UM' , 'US' , 'UY' ,
88
+ 'UZ' , 'VA' , 'VC' , 'VE' , 'VG' , 'VI' , 'VN' , 'VU' , 'WF' , 'WS' , 'XK' , 'YE' , 'YT' ,
89
+ 'ZA' , 'ZM' , 'ZW' ,
90
+ }
59
91
60
92
61
93
def compact (number : str ) -> str :
@@ -73,6 +105,8 @@ def validate(number: str) -> str:
73
105
match = _bic_re .search (number )
74
106
if not match :
75
107
raise InvalidFormat ()
108
+ if match .group ('country_code' ) not in _country_codes :
109
+ raise InvalidComponent ()
76
110
return number
77
111
78
112
0 commit comments