diff --git a/src/validators/__init__.py b/src/validators/__init__.py index 635a835..daa31f2 100644 --- a/src/validators/__init__.py +++ b/src/validators/__init__.py @@ -2,7 +2,7 @@ # local from .between import between -from .card import amex, card_number, diners, discover, jcb, mastercard, unionpay, visa +from .card import amex, card_number, diners, discover, jcb, mastercard, mir, unionpay, visa from .country import calling_code, country_code, currency from .cron import cron from .crypto_addresses import bsc_address, btc_address, eth_address, trx_address @@ -49,8 +49,9 @@ "discover", "jcb", "mastercard", - "visa", "unionpay", + "visa", + "mir", # country "calling_code", "country_code", diff --git a/src/validators/card.py b/src/validators/card.py index d95643c..94b6637 100644 --- a/src/validators/card.py +++ b/src/validators/card.py @@ -192,3 +192,25 @@ def discover(value: str, /): """ pattern = re.compile(r"^(60|64|65)") return card_number(value) and len(value) == 16 and pattern.match(value) + + +@validator +def mir(value: str, /): + """Return whether or not given value is a valid Mir card number. + + Examples: + >>> mir('2200123456789019') + True + >>> mir('4242424242424242') + ValidationError(func=mir, args={'value': '4242424242424242'}) + + Args: + value: + Mir card number string to validate. + + Returns: + (Literal[True]): If `value` is a valid Mir card number. + (ValidationError): If `value` is an invalid Mir card number. + """ + pattern = re.compile(r"^(220[0-4])") + return card_number(value) and len(value) == 16 and pattern.match(value) diff --git a/tests/test_card.py b/tests/test_card.py index 1eafa2f..d004392 100644 --- a/tests/test_card.py +++ b/tests/test_card.py @@ -12,6 +12,7 @@ discover, jcb, mastercard, + mir, unionpay, visa, ) @@ -23,6 +24,7 @@ diners_cards = ["3056930009020004", "36227206271667"] jcb_cards = ["3566002020360505"] discover_cards = ["6011111111111117", "6011000990139424"] +mir_cards = ["2200123456789019", "2204987654321098"] @pytest.mark.parametrize( @@ -33,14 +35,23 @@ + unionpay_cards + diners_cards + jcb_cards - + discover_cards, + + discover_cards + + mir_cards, ) def test_returns_true_on_valid_card_number(value: str): """Test returns true on valid card number.""" assert card_number(value) -@pytest.mark.parametrize("value", ["4242424242424240", "4000002760003180", "400000276000318X"]) +@pytest.mark.parametrize( + "value", + [ + "4242424242424240", + "4000002760003180", + "400000276000318X", + "220012345678901X", + ], +) def test_returns_failed_on_valid_card_number(value: str): """Test returns failed on valid card number.""" assert isinstance(card_number(value), ValidationError) @@ -84,7 +95,13 @@ def test_returns_true_on_valid_amex(value: str): @pytest.mark.parametrize( "value", - visa_cards + mastercard_cards + unionpay_cards + diners_cards + jcb_cards + discover_cards, + visa_cards + + mastercard_cards + + unionpay_cards + + diners_cards + + jcb_cards + + discover_cards + + mir_cards, ) def test_returns_failed_on_valid_amex(value: str): """Test returns failed on valid amex.""" @@ -99,7 +116,13 @@ def test_returns_true_on_valid_unionpay(value: str): @pytest.mark.parametrize( "value", - visa_cards + mastercard_cards + amex_cards + diners_cards + jcb_cards + discover_cards, + visa_cards + + mastercard_cards + + amex_cards + + diners_cards + + jcb_cards + + discover_cards + + mir_cards, ) def test_returns_failed_on_valid_unionpay(value: str): """Test returns failed on valid unionpay.""" @@ -114,7 +137,13 @@ def test_returns_true_on_valid_diners(value: str): @pytest.mark.parametrize( "value", - visa_cards + mastercard_cards + amex_cards + unionpay_cards + jcb_cards + discover_cards, + visa_cards + + mastercard_cards + + amex_cards + + unionpay_cards + + jcb_cards + + discover_cards + + mir_cards, ) def test_returns_failed_on_valid_diners(value: str): """Test returns failed on valid diners.""" @@ -129,7 +158,13 @@ def test_returns_true_on_valid_jcb(value: str): @pytest.mark.parametrize( "value", - visa_cards + mastercard_cards + amex_cards + unionpay_cards + diners_cards + discover_cards, + visa_cards + + mastercard_cards + + amex_cards + + unionpay_cards + + diners_cards + + discover_cards + + mir_cards, ) def test_returns_failed_on_valid_jcb(value: str): """Test returns failed on valid jcb.""" @@ -144,8 +179,35 @@ def test_returns_true_on_valid_discover(value: str): @pytest.mark.parametrize( "value", - visa_cards + mastercard_cards + amex_cards + unionpay_cards + diners_cards + jcb_cards, + visa_cards + + mastercard_cards + + amex_cards + + unionpay_cards + + diners_cards + + jcb_cards + + mir_cards, ) def test_returns_failed_on_valid_discover(value: str): """Test returns failed on valid discover.""" assert isinstance(discover(value), ValidationError) + + +@pytest.mark.parametrize("value", mir_cards) +def test_returns_true_on_valid_mir(value: str): + """Test returns true on valid Mir card.""" + assert mir(value) + + +@pytest.mark.parametrize( + "value", + visa_cards + + mastercard_cards + + amex_cards + + unionpay_cards + + diners_cards + + jcb_cards + + discover_cards, +) +def test_returns_failed_on_valid_mir(value: str): + """Test returns failed on invalid Mir card (other payment systems).""" + assert isinstance(mir(value), ValidationError)