Skip to content

Commit 5ba1abb

Browse files
committed
Add support for Tanzania TIN
Fixes arthurdejong#224.
1 parent 6d366e3 commit 5ba1abb

File tree

3 files changed

+340
-0
lines changed

3 files changed

+340
-0
lines changed

stdnum/tz/__init__.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# __init__.py - collection of Tanzania numbers
2+
# coding: utf-8
3+
#
4+
# Copyright (C) 2023 Leandro Regueiro
5+
#
6+
# This library is free software; you can redistribute it and/or
7+
# modify it under the terms of the GNU Lesser General Public
8+
# License as published by the Free Software Foundation; either
9+
# version 2.1 of the License, or (at your option) any later version.
10+
#
11+
# This library is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
# Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public
17+
# License along with this library; if not, write to the Free Software
18+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19+
# 02110-1301 USA
20+
21+
"""Collection of Tanzania numbers."""

stdnum/tz/tin.py

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# tin.py - functions for handling Tanzania TIN numbers
2+
# coding: utf-8
3+
#
4+
# Copyright (C) 2023 Leandro Regueiro
5+
#
6+
# This library is free software; you can redistribute it and/or
7+
# modify it under the terms of the GNU Lesser General Public
8+
# License as published by the Free Software Foundation; either
9+
# version 2.1 of the License, or (at your option) any later version.
10+
#
11+
# This library is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
# Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public
17+
# License along with this library; if not, write to the Free Software
18+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19+
# 02110-1301 USA
20+
21+
"""TIN (Taxpayer Identification Number, or TIN namba, Tanzania tax number).
22+
23+
This number consists of 9 digits, usually separated into three groups
24+
using hyphens to make it easier to read, like XXX-XXX-XXX.
25+
26+
>>> validate('121-207-079')
27+
'121207079'
28+
>>> validate('12345')
29+
Traceback (most recent call last):
30+
...
31+
InvalidLength: ...
32+
>>> format('121207079')
33+
'121-207-079'
34+
"""
35+
36+
from stdnum.exceptions import *
37+
from stdnum.util import clean, isdigits
38+
39+
40+
def compact(number):
41+
"""Convert the number to the minimal representation.
42+
43+
This strips the number of any valid separators and removes surrounding
44+
whitespace.
45+
"""
46+
return str(clean(number, u' -–').strip())
47+
48+
49+
def validate(number):
50+
"""Check if the number is a valid Tanzania TIN number.
51+
52+
This checks the length and formatting.
53+
"""
54+
number = compact(number)
55+
if len(number) != 9:
56+
raise InvalidLength()
57+
if not isdigits(number):
58+
raise InvalidFormat()
59+
return number
60+
61+
62+
def is_valid(number):
63+
"""Check if the number is a valid Tanzania TIN number."""
64+
try:
65+
return bool(validate(number))
66+
except ValidationError:
67+
return False
68+
69+
70+
def format(number):
71+
"""Reformat the number to the standard presentation format."""
72+
number = compact(number)
73+
return '-'.join([number[:3], number[3:-3], number[-3:]])

tests/test_tz_tin.doctest

+246
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
test_tz_tin.doctest - more detailed doctests for stdnum.tz.tin module
2+
coding: utf-8
3+
4+
Copyright (C) 2023 Leandro Regueiro
5+
6+
This library is free software; you can redistribute it and/or
7+
modify it under the terms of the GNU Lesser General Public
8+
License as published by the Free Software Foundation; either
9+
version 2.1 of the License, or (at your option) any later version.
10+
11+
This library is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
Lesser General Public License for more details.
15+
16+
You should have received a copy of the GNU Lesser General Public
17+
License along with this library; if not, write to the Free Software
18+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19+
02110-1301 USA
20+
21+
22+
This file contains more detailed doctests for the stdnum.tz.tin module. It
23+
tries to test more corner cases and detailed functionality that is not really
24+
useful as module documentation.
25+
26+
>>> from stdnum.tz import tin
27+
28+
29+
Tests for some corner cases.
30+
31+
>>> tin.validate('121-207-079')
32+
'121207079'
33+
>>> tin.validate(u'121–207–079')
34+
'121207079'
35+
>>> tin.validate('121 207 079')
36+
'121207079'
37+
>>> tin.validate('121 - 207 - 079')
38+
'121207079'
39+
>>> tin.validate('121207079')
40+
'121207079'
41+
>>> tin.format('121207079')
42+
'121-207-079'
43+
>>> tin.validate('12345')
44+
Traceback (most recent call last):
45+
...
46+
InvalidLength: ...
47+
>>> tin.validate('VV3456789')
48+
Traceback (most recent call last):
49+
...
50+
InvalidFormat: ...
51+
52+
53+
These have been found online and should all be valid numbers.
54+
55+
>>> numbers = u'''
56+
...
57+
... 121-207-079
58+
... 117-030-407
59+
... 130-393-985
60+
... 139 457 471
61+
... 135-000-205
62+
... 107-618-627
63+
... 124-753-783
64+
... 120-662-023
65+
... 105-038-321
66+
... 105-669-445
67+
... 139-384-059
68+
... 133-604-049
69+
... 142-303-175
70+
... 138-506-789
71+
... 100-849-089
72+
... 107-211-748
73+
... 141-076-841
74+
... 115-793-217
75+
... 156-158-429
76+
... 100-168-375
77+
... 127-321-361
78+
... 121-899-779
79+
... 108-711-744
80+
... 130-376-134
81+
... 136-449-125
82+
... 138-921-646
83+
... 102-158-008
84+
... 127-975-116
85+
... 110-496-907
86+
... 105-437-706
87+
... 101-325-695
88+
... 100-784-661
89+
... 129-210-958
90+
... 124-530-725
91+
... 120-332-694
92+
... 144 - 532 - 074
93+
... 101-345-467
94+
... 111-169-268
95+
... 105-875-304
96+
... 108-537-108
97+
... 100-147-181
98+
... 128-755-586
99+
... 100-145-804
100+
... 102-072-286
101+
... 120-992-864
102+
... 123-854-233
103+
... 142-253-011
104+
... 101-042-197
105+
... 101-195-651
106+
... 130 307 337
107+
... 138-360-679
108+
... 130-084-273
109+
... 107-089-765
110+
... 144-436-253
111+
... 130-265-529
112+
... 132760721
113+
... 135-972-118
114+
... 105-632-991
115+
... 101-034-879
116+
... 112-911-847
117+
... 100-195-232
118+
... 120-884-336
119+
... 110-170-335
120+
... 100-895-803
121+
... 129-506-202
122+
... 145-456-789
123+
... 120-537-776
124+
... 136-968-017
125+
... 100-202-646
126+
... 103150524
127+
... 117-953-300
128+
... 125-181-317
129+
... 134-267-437
130+
... 125 319 890
131+
... 122-452-328
132+
... 118-847-407
133+
... 107-855-106
134+
... 116-738-023
135+
... 144-372-069
136+
... 100-146-630
137+
... 102-825-128
138+
... 113-521-937
139+
... 128-263-454
140+
... 138-675-009
141+
... 120-364-529
142+
... 141-610-678
143+
... 126 – 041 – 349
144+
... 108-998-350
145+
... 115-577-239
146+
... 125-885-020
147+
... 132-800-723
148+
... 110-402-910
149+
... 138-692-302
150+
... 103-626-137
151+
... 153-443-971
152+
... 111-927-480
153+
... 116-285-088
154+
... 129-937-084
155+
... 142-002-078
156+
... 115-302-302
157+
... 127-491-690
158+
... 127- 532-931
159+
... 103-410-444
160+
... 101-346-943
161+
... 154-318-933
162+
... 139-793-412
163+
... 100147181
164+
... 130-210- 392
165+
... 138-584-666
166+
... 120-036-815
167+
... 117-653-218
168+
... 131-946-961
169+
... 118-690-265
170+
... 125-801-153
171+
... 129-042-877
172+
... 135-202-827
173+
... 115-575-503
174+
... 106-091-625
175+
... 120-723-987
176+
... 122-044-483
177+
... 104-746-047
178+
... 123-854-233
179+
... 100-101-297
180+
... 117-305-341
181+
... 107-075-259
182+
... 100-178-117
183+
... 107-966-013
184+
... 112-166-386
185+
... 122-034-178
186+
... 138-882-756
187+
... 117-409-171
188+
... 107-260-692
189+
... 100-197-898
190+
... 137-843-951
191+
... 107-199-101
192+
... 126-085-451
193+
... 135-769-827
194+
... 118-926-862
195+
... 115-692-127
196+
... 126-471-688
197+
... 112-351-035
198+
... 123-288-602
199+
... 121-786-524
200+
... 113-225-246
201+
... 138-007-286
202+
... 122-992-136
203+
... 101-041-662
204+
... 139-953-462
205+
... 109-345-180
206+
... 908-263-792
207+
... 111-588-198
208+
... 125-967-574
209+
... 107-588-582
210+
... 116-800-403
211+
... 101-299-570
212+
... 139-362-756
213+
... 131-057-857
214+
... 106-736-839
215+
... 101-151-425
216+
... 101-668-479
217+
... 104-368-867
218+
... 113-663-903
219+
... 121-666-944
220+
... 135-703-877
221+
... 132-761-728
222+
... 106-955-581
223+
... 130-882-110
224+
... 105-861-400
225+
... 140-564-044
226+
... 134-154-497
227+
... 115-236-776
228+
... 129-515-406
229+
... 119-343-100
230+
... 110-034-326
231+
... 119-264-251
232+
... 101-024-490
233+
... 107-538-844
234+
... 101-473-368
235+
... 104-979-386
236+
... 100-173-697
237+
... 106-535-590
238+
... 140-148-628
239+
... 111-039-240
240+
... 105541295
241+
... 100582775
242+
... 100254484
243+
...
244+
... '''
245+
>>> [x for x in numbers.splitlines() if x and not tin.is_valid(x)]
246+
[]

0 commit comments

Comments
 (0)