diff --git a/src/validators/uuid.py b/src/validators/uuid.py index ca6b1ba0..c3f149a7 100644 --- a/src/validators/uuid.py +++ b/src/validators/uuid.py @@ -35,9 +35,9 @@ def uuid(value: Union[str, UUID], /): return False if isinstance(value, UUID): return True - try: - return UUID(value) or re.match( - r"^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$", value - ) - except ValueError: - return False + # Not UUID(value): it drops hyphens wherever they are and reads the rest with int(), + # which also takes "0x", signs, underscores, surrounding spaces and non-ASCII digits. + return re.fullmatch( + r"(?:urn:uuid:)?(\{)?[0-9a-fA-F]{8}(-?)(?:[0-9a-fA-F]{4}\2){3}[0-9a-fA-F]{12}(?(1)\})", + value, + ) diff --git a/tests/test_uuid.py b/tests/test_uuid.py index b4f40d29..c0c03d35 100644 --- a/tests/test_uuid.py +++ b/tests/test_uuid.py @@ -18,6 +18,10 @@ ("2bc1c94f-0deb-43e9-92a1-4775189ec9f8",), (uuid4(),), ("888256d7c49341f19fa33f29d3f820d7",), + ("2BC1C94F-0DEB-43E9-92A1-4775189EC9F8",), + ("{2bc1c94f-0deb-43e9-92a1-4775189ec9f8}",), + ("{888256d7c49341f19fa33f29d3f820d7}",), + ("urn:uuid:2bc1c94f-0deb-43e9-92a1-4775189ec9f8",), ], ) def test_returns_true_on_valid_uuid(value: Union[str, UUID]): @@ -32,6 +36,13 @@ def test_returns_true_on_valid_uuid(value: Union[str, UUID]): ("2bc1c94f-0deb-43e9-92a1-4775189ec9f",), ("gbc1c94f-0deb-43e9-92a1-4775189ec9f8",), ("2bc1c94f 0deb-43e9-92a1-4775189ec9f8",), + ("2bc1c94f-0deb4-3e9-92a1-4775189ec9f8",), + ("2bc1c94f-0deb43e992a14775189ec9f8",), + ("0xc1c94f0deb43e992a14775189ec9f8",), + ("+bc1c94f0deb43e992a14775189ec9f8",), + ("2bc1c94f_deb43e992a14775189ec9f8",), + (" bc1c94f0deb43e992a14775189ec9f ",), + ("2bc1c94f-0deb-43e9-92a1-4775189ec9f8}",), ], ) def test_returns_failed_validation_on_invalid_uuid(value: Union[str, UUID]):