Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
path: root/stdnum
diff options
context:
space:
mode:
Diffstat (limited to 'stdnum')
-rw-r--r--stdnum/bg/egn.py56
-rw-r--r--stdnum/bg/pnf.py37
-rw-r--r--stdnum/bg/vat.py48
3 files changed, 94 insertions, 47 deletions
diff --git a/stdnum/bg/egn.py b/stdnum/bg/egn.py
index d704543..7f94946 100644
--- a/stdnum/bg/egn.py
+++ b/stdnum/bg/egn.py
@@ -1,7 +1,7 @@
# egn.py - functions for handling Bulgarian national identification 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
@@ -27,18 +27,23 @@ digit.
>>> compact('752316 926 3')
'7523169263'
->>> is_valid('8032056031')
-True
+>>> validate('8032056031')
+'8032056031'
>>> get_birth_date('7542011030')
datetime.date(2075, 2, 1)
->>> is_valid('7552010004') # invalid check digit
-False
->>> is_valid('8019010008') # invalid date
-False
+>>> validate('7552A10004') # invalid digit
+Traceback (most recent call last):
+ ...
+InvalidFormat: ...
+>>> validate('8019010008') # invalid date
+Traceback (most recent call last):
+ ...
+InvalidComponent: ...
"""
import datetime
+from stdnum.exceptions import *
from stdnum.util import clean
@@ -66,24 +71,35 @@ def get_birth_date(number):
elif month > 20:
year -= 100
month -= 20
- return datetime.date(year, month, day)
+ try:
+ return datetime.date(year, month, day)
+ except ValueError:
+ raise InvalidComponent()
-def is_valid(number):
+def validate(number):
"""Checks to see if the number provided is a valid national
identification number. This checks the length, formatting, embedded
date and check digit."""
- try:
- number = compact(number)
- except:
- return False
- if not number.isdigit() or len(number) != 10:
- return False
+ number = compact(number)
+ if not number.isdigit():
+ raise InvalidFormat()
+ if len(number) != 10:
+ raise InvalidLength()
# check if birth date is valid
+ birth_date = get_birth_date(number)
+ # TODO: check that the birth date is not in the future
+ # check the check digit
+ 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 national
+ identification number. This checks the length, formatting, embedded
+ date and check digit."""
try:
- birth_date = get_birth_date(number)
- # TODO: check that the birth date is not in the future
- except ValueError:
+ return bool(validate(number))
+ except ValidationError:
return False
- # check the check digit
- return calc_check_digit(number[:-1]) == number[-1]
diff --git a/stdnum/bg/pnf.py b/stdnum/bg/pnf.py
index e03d33a..bddfb2b 100644
--- a/stdnum/bg/pnf.py
+++ b/stdnum/bg/pnf.py
@@ -1,7 +1,7 @@
# pnf.py - functions for handling Bulgarian personal number of a foreigner
# 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
@@ -23,14 +23,19 @@
The personal number of a foreigner is a 10-digit number where the last digit
is the result of a weighted checksum.
->>> compact('7111 042 925')
+>>> validate('7111 042 925')
'7111042925'
->>> is_valid('7111042925')
-True
->>> is_valid('7111042922') # invalid check digit
-False
+>>> validate('7111042922') # invalid check digit
+Traceback (most recent call last):
+ ...
+InvalidChecksum: ...
+>>> validate('71110A2922') # invalid digit
+Traceback (most recent call last):
+ ...
+InvalidFormat: ...
"""
+from stdnum.exceptions import *
from stdnum.util import clean
@@ -47,13 +52,25 @@ def calc_check_digit(number):
return str(sum(weights[i] * int(n) for i, n in enumerate(number)) % 10)
+def validate(number):
+ """Checks to see if the number provided is a valid national
+ identification number. This checks the length, formatting, embedded
+ date and check digit."""
+ number = compact(number)
+ if not number.isdigit():
+ raise InvalidFormat()
+ if len(number) != 10:
+ 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 national
identification number. This checks the length, formatting, embedded
date and check digit."""
try:
- number = compact(number)
- except:
+ return bool(validate(number))
+ except ValidationError:
return False
- return number.isdigit() and len(number) == 10 and \
- calc_check_digit(number[:-1]) == number[-1]
diff --git a/stdnum/bg/vat.py b/stdnum/bg/vat.py
index 644af68..e04141d 100644
--- a/stdnum/bg/vat.py
+++ b/stdnum/bg/vat.py
@@ -1,7 +1,7 @@
# vat.py - functions for handling Bulgarian 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
@@ -26,14 +26,17 @@ others) long. Each type of number has it's own check digit algorithm.
>>> compact('BG 175 074 752')
'175074752'
->>> is_valid('175074752')
-True
->>> is_valid('175074751') # invalid check digit
-False
+>>> validate('175074752')
+'175074752'
+>>> validate('175074751') # invalid check digit
+Traceback (most recent call last):
+ ...
+InvalidChecksum: ...
"""
-from stdnum.util import clean
from stdnum.bg import egn, pnf
+from stdnum.exceptions import *
+from stdnum.util import clean
def compact(number):
@@ -61,19 +64,30 @@ def calc_check_digit_other(number):
return str((11 - sum(weights[i] * int(n) for i, n in enumerate(number))) % 11)
+def validate(number):
+ """Checks to see if the number provided is a valid VAT number. This
+ checks the length, formatting and check digit."""
+ number = compact(number)
+ if not number.isdigit():
+ raise InvalidFormat()
+ if len(number) == 9:
+ # 9 digit numbers are for legal entities
+ if number[-1] != calc_check_digit_legal(number[:-1]):
+ raise InvalidChecksum()
+ elif len(number) == 10:
+ # 10 digit numbers are for physical persons, foreigners and others
+ if not egn.is_valid(number) and not pnf.is_valid(number) and \
+ number[-1] != calc_check_digit_other(number[:-1]):
+ raise InvalidChecksum()
+ else:
+ raise InvalidLength()
+ 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:
- number = compact(number)
- except:
+ return bool(validate(number))
+ except ValidationError:
return False
- if len(number) == 9 and number.isdigit():
- # 9 digit numbers are for legal entities
- return number[-1] == calc_check_digit_legal(number[:-1])
- if len(number) == 10 and number.isdigit():
- # 10 digit numbers are for physical persons, foreigners and others
- return egn.is_valid(number) or \
- pnf.is_valid(number) or \
- number[-1] == calc_check_digit_other(number[:-1])
- return False