From 45e9a6a480b47b2b8f6fee3a6fde61d54e9676cb Mon Sep 17 00:00:00 2001 From: AMin Date: Sun, 25 Oct 2026 13:54:57 +0800 Subject: [PATCH 1/2] Accept lowercase prefixes in Spanish NIE validation --- src/validators/i18n/es.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validators/i18n/es.py b/src/validators/i18n/es.py index c2761708..ecc4597f 100644 --- a/src/validators/i18n/es.py +++ b/src/validators/i18n/es.py @@ -135,7 +135,7 @@ def es_nie(value: str, /): """ number_by_letter = {"X": "0", "Y": "1", "Z": "2"} # NIE must must start with X Y or Z - if value and value[0] in number_by_letter: + if value and value[0].upper() in number_by_letter: return _nif_nie_validation(value, number_by_letter) return False From 4082eb9639436b7e79e4f686e55a91025ea08ffa Mon Sep 17 00:00:00 2001 From: AMin Date: Sun, 25 Oct 2026 13:55:57 +0800 Subject: [PATCH 2/2] Test lowercase NIE prefixes and checksum rejection --- tests/i18n/test_es.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/i18n/test_es.py b/tests/i18n/test_es.py index 55790400..4254484b 100644 --- a/tests/i18n/test_es.py +++ b/tests/i18n/test_es.py @@ -63,6 +63,21 @@ def test_returns_true_on_valid_nie(value: str): assert es_nie(value) +@pytest.mark.parametrize("validate", [es_nie, es_doi]) +@pytest.mark.parametrize("value", ["X0095892M", "Y2584969J", "Z2915723H"]) +def test_nie_accepts_lowercase_prefix(validate: Callable[[str], object], value: str): + """Accept lowercase NIE prefixes consistently with NIF and CIF letters.""" + assert validate(value[0].lower() + value[1:]) is True + assert validate(value.lower()) is True + + +@pytest.mark.parametrize("validate", [es_nie, es_doi]) +@pytest.mark.parametrize("value", ["x0095892x", "y2584969x", "z2915723x"]) +def test_lowercase_nie_still_checks_checksum(validate: Callable[[str], object], value: str): + """Do not accept an invalid checksum after normalizing the prefix.""" + assert isinstance(validate(value), ValidationError) + + @pytest.mark.parametrize( ("value",), [