Skip to content

Commit e34032d

Browse files
committed
Add support for Faroe Islands TIN
Fixes #219.
1 parent e40c827 commit e34032d

File tree

3 files changed

+283
-0
lines changed

3 files changed

+283
-0
lines changed

stdnum/fo/__init__.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# __init__.py - collection of Faroe Islands numbers
2+
# coding: utf-8
3+
#
4+
# Copyright (C) 2022 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 Faroe Islands numbers."""
22+
23+
# provide aliases
24+
from stdnum.fo import vn as vat # noqa: F401

stdnum/fo/vn.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# vn.py - functions for handling Faroe Islands V-number numbers
2+
# coding: utf-8
3+
#
4+
# Copyright (C) 2022 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+
"""V-number (Faroe Islands tax number).
22+
23+
In the Faroe Islands the legal persons TIN equals the V number issued by the
24+
Faroese Tax Administration.
25+
26+
It is a consecutive number.
27+
28+
More information:
29+
30+
* https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Faroe-islands-TIN.pdf
31+
32+
>>> validate('623857')
33+
'623857'
34+
>>> validate('602 590')
35+
'602590'
36+
>>> validate('1234')
37+
Traceback (most recent call last):
38+
...
39+
InvalidLength: ...
40+
>>> validate('12345X')
41+
Traceback (most recent call last):
42+
...
43+
InvalidFormat: ...
44+
>>> format('602 590')
45+
'602590'
46+
""" # noqa: E501
47+
48+
from stdnum.exceptions import *
49+
from stdnum.util import clean, isdigits
50+
51+
52+
def compact(number):
53+
"""Convert the number to the minimal representation.
54+
55+
This strips the number of any valid separators and removes surrounding
56+
whitespace.
57+
"""
58+
return clean(number, ' -.').upper().strip()
59+
if number.startswith('FO'):
60+
return number[2:]
61+
return number
62+
63+
64+
def validate(number):
65+
"""Check if the number is a valid Faroe Islands V-number number.
66+
67+
This checks the length and formatting.
68+
"""
69+
number = compact(number)
70+
if len(number) != 6:
71+
raise InvalidLength()
72+
if not isdigits(number):
73+
raise InvalidFormat()
74+
return number
75+
76+
77+
def is_valid(number):
78+
"""Check if the number is a valid Faroe Islands V-number number."""
79+
try:
80+
return bool(validate(number))
81+
except ValidationError:
82+
return False
83+
84+
85+
def format(number):
86+
"""Reformat the number to the standard presentation format."""
87+
return compact(number)

tests/test_fo_vn.doctest

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
test_fo_vn.doctest - more detailed doctests for stdnum.fo.vn module
2+
3+
Copyright (C) 2022 Leandro Regueiro
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18+
02110-1301 USA
19+
20+
21+
This file contains more detailed doctests for the stdnum.fo.vn module. It
22+
tries to test more corner cases and detailed functionality that is not really
23+
useful as module documentation.
24+
25+
>>> from stdnum.fo import vn
26+
27+
28+
Tests for some corner cases.
29+
30+
>>> vn.validate('623857')
31+
'623857'
32+
>>> vn.validate('602 590')
33+
'602590'
34+
>>> vn.validate('563.609')
35+
'563609'
36+
>>> vn.validate('FO384941')
37+
'384941'
38+
>>> vn.format('623857')
39+
'623857'
40+
>>> vn.format('602 590')
41+
'602590'
42+
>>> vn.format('33 28 28')
43+
'332828'
44+
>>> vn.format('563.609')
45+
'563609'
46+
>>> vn.format('FO384941')
47+
'384941'
48+
>>> vn.validate('12345')
49+
Traceback (most recent call last):
50+
...
51+
InvalidLength: ...
52+
>>> vn.validate('12345X')
53+
Traceback (most recent call last):
54+
...
55+
InvalidFormat: ...
56+
57+
58+
These have been found online and should all be valid numbers.
59+
60+
>>> numbers = '''
61+
...
62+
... 602 590
63+
... 616 923
64+
... 557 692
65+
... 568 597
66+
... 568 031
67+
... 605 174
68+
... 623857
69+
... 323853
70+
... 323853
71+
... 549118
72+
... 330833
73+
... 345490
74+
... 589306
75+
... 537.535
76+
... 563.609
77+
... 478 865
78+
... 537.543
79+
... 463000
80+
... 55 16 00
81+
... 345334
82+
... 403369
83+
... 630713
84+
... 369497
85+
... 623016
86+
... 636568
87+
... 322407
88+
... 538485
89+
... 452432
90+
... 339849
91+
... 489042
92+
... 328871
93+
... 324213
94+
... 552569
95+
... 575712
96+
... 328944
97+
... 504572
98+
... 322059
99+
... 308382
100+
... 502855
101+
... 554375
102+
... 33 28 28
103+
... 606294
104+
... 309273
105+
... 353477
106+
... 617105
107+
... 539813
108+
... 328863
109+
... 321079
110+
... 607436
111+
... 401900
112+
... 550558
113+
... 569682
114+
... 637114
115+
... 628980
116+
... 522821
117+
... 427888
118+
... 401900
119+
... 355216
120+
... 619558
121+
... 437.115
122+
... 603937
123+
... 355186
124+
... 476897
125+
... 366161
126+
... 620092
127+
... 546.089
128+
... 551.023
129+
... 408638
130+
... 498.289
131+
... 601470
132+
... 587974
133+
... 641154
134+
... 636223
135+
... 488135
136+
... 619388
137+
... 625485
138+
... 627976
139+
... 576174
140+
... 576174
141+
... 403687
142+
... 401900
143+
... 625590
144+
... 374989
145+
... 623792
146+
... 623385
147+
... 585335
148+
... 331538
149+
... 613606
150+
... 597570
151+
... 589.810
152+
... FO384941
153+
... 559679
154+
... 443921
155+
... 617121
156+
... 620785
157+
... 638722
158+
... 550612
159+
... 509078
160+
... 344338
161+
... 579319
162+
... 602221
163+
... 516244
164+
... 33 28 28
165+
... 379778
166+
... 604097
167+
... 578 509
168+
... 519324
169+
...
170+
... '''
171+
>>> [x for x in numbers.splitlines() if x and not vn.is_valid(x)]
172+
[]

0 commit comments

Comments
 (0)