diff --git a/docs/index.rst b/docs/index.rst index 212302b7..070a201b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -208,6 +208,16 @@ fi_ssn .. autofunction:: fi_ssn +Iran +------- + +.. module:: validators.i18n.ir + +ir_national_code +^^^^^^^^^^^^^^ + +.. autofunction:: ir_national_code + Internals ========= diff --git a/tests/i18n/test_ir.py b/tests/i18n/test_ir.py new file mode 100644 index 00000000..bb41ee8c --- /dev/null +++ b/tests/i18n/test_ir.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +import pytest + +from validators import ir_national_code +import random + +# from https://gist.github.com/Alireza2n/5708c361ca8417dec0f355d8eb51bc2b +def random_national_code_generator(): + number_list = [] + _sum = 0 + out = "" + for i in reversed(range(2, 11)): + _j = random.randint(0, 9) + number_list.append(str(_j)) + _sum += _j * i + _m = _sum % 11 + if _m < 2: + number_list.append(str(_m)) + elif _m >= 2: + number_list.append(str(11 - _m)) + return out.join(number_list) + +@pytest.mark.parametrize(('value',), [ + (random_national_code_generator(),), + (random_national_code_generator(),), + ('1111111111',), # same number is not invalid http://www.fardanews.com/fa/news/127747 + +]) +def test_returns_true_on_valid_national_code(value): + assert ir_national_code(value) + +@pytest.mark.parametrize(('value',), [ + (None,), + ('0000000000',), + ('1234567890',), + ('123456789',), + ('',), +]) +def test_returns_True_on_not_valid_national_code(value): + assert not ir_national_code(value) diff --git a/validators/__init__.py b/validators/__init__.py index e4ccfd53..88aaa9e9 100644 --- a/validators/__init__.py +++ b/validators/__init__.py @@ -3,7 +3,7 @@ from .email import email # noqa from .extremes import Max, Min # noqa from .hashes import md5, sha1, sha224, sha256, sha512 # noqa -from .i18n import fi_business_id, fi_ssn # noqa +from .i18n import fi_business_id, fi_ssn, ir_national_code # noqa from .iban import iban # noqa from .ip_address import ipv4, ipv6 # noqa from .length import length # noqa @@ -14,4 +14,4 @@ from .utils import ValidationFailure, validator # noqa from .uuid import uuid # noqa -__version__ = '0.12.3' +__version__ = '0.12.4' diff --git a/validators/i18n/__init__.py b/validators/i18n/__init__.py index 49652f68..0bd4e2b9 100644 --- a/validators/i18n/__init__.py +++ b/validators/i18n/__init__.py @@ -1 +1,2 @@ from .fi import fi_business_id, fi_ssn # noqa +from .ir import ir_national_code \ No newline at end of file diff --git a/validators/i18n/ir.py b/validators/i18n/ir.py new file mode 100644 index 00000000..d73481df --- /dev/null +++ b/validators/i18n/ir.py @@ -0,0 +1,38 @@ +import re + +from validators.utils import validator + +@validator +def ir_national_code(input): # forked from : https://gist.github.com/ebraminio/5292017 + """ + Validate a Iranian National Code. + + Each person in Iran has a uniq national code. For more + information see `Identity Number`_ + + .. _Identity Number: + https://en.wikipedia.org/wiki/Iranian_passport#Identity_Number + + Examples:: + + >>> ir_national_code('4608968882') # Generated by random generator + True + + >>> ir_national_code('4608968872') + ValidationFailure(func=ir_national_code, args={'input': '4608968872'}) + + + :param national_code: national_code to validate + """ + if input == '0000000000': + return False + + if re.search(r'^\d{10}$', input): + pass + if not re.search(r'^\d{10}$', input): + return False + + check = int(input[9]) + s = sum([int(input[x]) * (10 - x) for x in range(9)]) % 11 + return (s < 2 and check == s) or (s >= 2 and check + s == 11) +