Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
path: root/stdnum/es/cif.py
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 /stdnum/es/cif.py
parent07c66e13b3928fb92fd0e537e23d3c5be2ad8956 (diff)
Implement validate() for Spanish numbers
Diffstat (limited to 'stdnum/es/cif.py')
-rw-r--r--stdnum/es/cif.py71
1 files changed, 45 insertions, 26 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):