Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2013-05-17 12:46:27 +0200
committerArthur de Jong <arthur@arthurdejong.org>2013-06-08 14:45:39 +0200
commit2259cbb09e419e56c355efdbd865f99127d559c5 (patch)
tree736b02f87d6f1240ae14a5dba118a617cb0b688b
parent07c66e13b3928fb92fd0e537e23d3c5be2ad8956 (diff)
Implement validate() for Spanish numbers
-rw-r--r--stdnum/es/cif.py71
-rw-r--r--stdnum/es/dni.py36
-rw-r--r--stdnum/es/nie.py40
-rw-r--r--stdnum/es/nif.py57
4 files changed, 134 insertions, 70 deletions
diff --git a/stdnum/es/cif.py b/stdnum/es/cif.py
index 679e596..eeb0e72 100644
--- a/stdnum/es/cif.py
+++ b/stdnum/es/cif.py
@@ -1,7 +1,7 @@
# cif.py - functions for handling Spanish fiscal numbers
# coding: utf-8
#
-# Copyright (C) 2012 Arthur de Jong
+# Copyright (C) 2012, 2013 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -24,25 +24,32 @@ The CIF is a tax identification number for legal entities. It has 9 digits
where the first digit is a letter (denoting the type of entity) and the
last is a check digit (which may also be a letter).
->>> compact('J-99216582')
+>>> validate('J99216582')
'J99216582'
->>> is_valid('J99216582')
-True
->>> is_valid('J99216583') # invalid check digit
-False
->>> is_valid('M-1234567-L')
-True
->>> is_valid('O-1234567-L') # invalid first character
-False
+>>> validate('J99216583') # invalid check digit
+Traceback (most recent call last):
+ ...
+InvalidChecksum: ...
+>>> validate('J992165831') # too long
+Traceback (most recent call last):
+ ...
+InvalidLength: ...
+>>> validate('M-1234567-L')
+'M1234567L'
+>>> validate('O-1234567-L') # invalid first character
+Traceback (most recent call last):
+ ...
+InvalidFormat: ...
>>> split('A13 585 625')
('A', '13', '58562', '5')
"""
from stdnum import luhn
from stdnum.es import dni
+from stdnum.exceptions import *
-__all__ = ['compact', 'is_valid', 'split']
+__all__ = ['compact', 'validate', 'is_valid', 'split']
# use the same compact function as DNI
@@ -57,28 +64,40 @@ def calc_check_digits(number):
return check + 'JABCDEFGHI'[int(check)]
-def is_valid(number):
+def validate(number):
"""Checks to see if the number provided is a valid DNI number. This
checks the length, formatting and check digit."""
- try:
- number = compact(number)
- except:
- return False
- if len(number) != 9 or not number[1:-1].isdigit():
- return False
+ number = compact(number)
+ if not number[1:-1].isdigit():
+ raise InvalidFormat()
+ if len(number) != 9:
+ raise InvalidLength()
if number[0] in 'KLM':
# K: Spanish younger than 14 year old
# L: Spanish living outside Spain without DNI
# M: granted the tax to foreigners who have no NIE
# these use the old checkdigit algorithm (the DNI one)
- return number[-1] == dni.calc_check_digit(number[1:-1])
- # there seems to be conflicting information on which organisation types
- # should have which type of check digit (alphabetic or numeric) so
- # we support either here
- if number[0] in 'ABCDEFGHJNPQRSUVW':
- return number[-1] in calc_check_digits(number[:-1])
- # anything else is invalid
- return False
+ if number[-1] != dni.calc_check_digit(number[1:-1]):
+ raise InvalidChecksum()
+ elif number[0] in 'ABCDEFGHJNPQRSUVW':
+ # there seems to be conflicting information on which organisation types
+ # should have which type of check digit (alphabetic or numeric) so
+ # we support either here
+ if number[-1] not in calc_check_digits(number[:-1]):
+ raise InvalidChecksum()
+ else:
+ # anything else is invalid
+ raise InvalidFormat()
+ return number
+
+
+def is_valid(number):
+ """Checks to see if the number provided is a valid DNI number. This
+ checks the length, formatting and check digit."""
+ try:
+ return bool(validate(number))
+ except ValidationError:
+ return False
def split(number):
diff --git a/stdnum/es/dni.py b/stdnum/es/dni.py
index 3d5c508..18d0954 100644
--- a/stdnum/es/dni.py
+++ b/stdnum/es/dni.py
@@ -1,7 +1,7 @@
# dni.py - functions for handling Spanish personal identity codes
# coding: utf-8
#
-# Copyright (C) 2012 Arthur de Jong
+# Copyright (C) 2012, 2013 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -26,14 +26,19 @@ digit is a checksum letter.
Foreign nationals, since 2010 are issued an NIE (Número de Identificación
de Extranjeros, Foreigner's Identity Number) instead.
->>> compact('54362315-K')
+>>> validate('54362315-K')
'54362315K'
->>> is_valid('54362315-K')
-True
->>> is_valid('54362315Z') # invalid check digit
-False
+>>> validate('54362315Z') # invalid check digit
+Traceback (most recent call last):
+ ...
+InvalidChecksum: ...
+>>> validate('54362315') # digit missing
+Traceback (most recent call last):
+ ...
+InvalidLength: ...
"""
+from stdnum.exceptions import *
from stdnum.util import clean
@@ -49,12 +54,23 @@ def calc_check_digit(number):
return 'TRWAGMYFPDXBNJZSQVHLCKE'[int(number) % 23]
+def validate(number):
+ """Checks to see if the number provided is a valid DNI number. This
+ checks the length, formatting and check digit."""
+ number = compact(number)
+ if not number[:-1].isdigit():
+ raise InvalidFormat()
+ if len(number) != 9:
+ raise InvalidLength()
+ if calc_check_digit(number[:-1]) != number[-1]:
+ raise InvalidChecksum()
+ return number
+
+
def is_valid(number):
"""Checks to see if the number provided is a valid DNI number. This
checks the length, formatting and check digit."""
try:
- number = compact(number)
- except:
+ return bool(validate(number))
+ except ValidationError:
return False
- return number[:-1].isdigit() and len(number) == 9 and \
- calc_check_digit(number[:-1]) == number[-1]
diff --git a/stdnum/es/nie.py b/stdnum/es/nie.py
index fde7da0..9e510e6 100644
--- a/stdnum/es/nie.py
+++ b/stdnum/es/nie.py
@@ -1,7 +1,7 @@
# nie.py - functions for handling Spanish foreigner identity codes
# coding: utf-8
#
-# Copyright (C) 2012 Arthur de Jong
+# Copyright (C) 2012, 2013 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -24,15 +24,20 @@ The NIE is an identification number for foreigners. It is a 9 digit number
where the first digit is either X, Y or Z and last digit is a checksum
letter.
->>> compact('x-2482300w')
+>>> validate('x-2482300w')
'X2482300W'
->>> is_valid('x-2482300w')
-True
->>> is_valid('x-2482300a') # invalid check digit
-False
+>>> validate('x-2482300a') # invalid check digit
+Traceback (most recent call last):
+ ...
+InvalidChecksum: ...
+>>> validate('X2482300') # digit missing
+Traceback (most recent call last):
+ ...
+InvalidLength: ...
"""
from stdnum.es import dni
+from stdnum.exceptions import *
__all__ = ['compact', 'is_valid']
@@ -50,12 +55,23 @@ def calc_check_digit(number):
return dni.calc_check_digit(number)
+def validate(number):
+ """Checks to see if the number provided is a valid NIE. This checks
+ the length, formatting and check digit."""
+ number = compact(number)
+ if not number[1:-1].isdigit() or number[:1] not in 'XYZ':
+ raise InvalidFormat()
+ if len(number) != 9:
+ raise InvalidLength()
+ if calc_check_digit(number[:-1]) != number[-1]:
+ raise InvalidChecksum()
+ return number
+
+
def is_valid(number):
- """Checks to see if the number provided is a valid DNI number. This
- checks the length, formatting and check digit."""
+ """Checks to see if the number provided is a valid NIE. This checks
+ the length, formatting and check digit."""
try:
- number = compact(number)
- except:
+ return bool(validate(number))
+ except ValidationError:
return False
- return len(number) == 9 and number[1:-1].isdigit() and \
- number[0] in 'XYZ' and calc_check_digit(number[:-1]) == number[-1]
diff --git a/stdnum/es/nif.py b/stdnum/es/nif.py
index e1bc7df..7cd689e 100644
--- a/stdnum/es/nif.py
+++ b/stdnum/es/nif.py
@@ -1,7 +1,7 @@
# nif.py - functions for handling Spanish NIF (VAT) numbers
# coding: utf-8
#
-# Copyright (C) 2012 Arthur de Jong
+# Copyright (C) 2012, 2013 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -30,18 +30,21 @@ entities and others).
>>> compact('ES B-58378431')
'B58378431'
->>> is_valid('B64717838')
-True
->>> is_valid('B64717839') # invalid check digit
-False
->>> is_valid('54362315K') # resident
-True
->>> is_valid('X-5253868-R') # foreign person
-True
+>>> validate('B64717838')
+'B64717838'
+>>> validate('B64717839') # invalid check digit
+Traceback (most recent call last):
+ ...
+InvalidChecksum: ...
+>>> validate('54362315K') # resident
+'54362315K'
+>>> validate('X-5253868-R') # foreign person
+'X5253868R'
"""
-from stdnum.util import clean
from stdnum.es import dni, nie, cif
+from stdnum.exceptions import *
+from stdnum.util import clean
def compact(number):
@@ -53,20 +56,30 @@ def compact(number):
return number
-def is_valid(number):
+def validate(number):
"""Checks to see if the number provided is a valid VAT number. This checks
the length, formatting and check digit."""
- try:
- number = compact(number)
- except:
- return False
- if len(number) != 9 or not number[1:-1].isdigit():
- return False
+ number = compact(number)
+ if not number[1:-1].isdigit():
+ raise InvalidFormat()
+ if len(number) != 9:
+ raise InvalidLength()
if number[0].isdigit():
# natural resident
- return dni.is_valid(number)
- if number[0] in 'XYZ':
+ dni.validate(number)
+ elif number[0] in 'XYZ':
# foreign natural person
- return nie.is_valid(number)
- # otherwise it has to be a valid CIF
- return cif.is_valid(number)
+ nie.validate(number)
+ else:
+ # otherwise it has to be a valid CIF
+ cif.validate(number)
+ return number
+
+
+def is_valid(number):
+ """Checks to see if the number provided is a valid VAT number. This checks
+ the length, formatting and check digit."""
+ try:
+ return bool(validate(number))
+ except ValidationError:
+ return False