Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 12 additions & 16 deletions redisvl/schema/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,22 +174,18 @@ def _validate_vector(cls, value):
raise ValueError(
f"Vector field '{fname}' must have {dims} dimensions, got {len(value)}"
)
# Validate data types
datatype_str = str(datatype).upper()
# Integer-based datatypes
if datatype_str in ("INT8", "UINT8"):
# Check range for INT8
if datatype_str == "INT8":
if any(v < -128 or v > 127 for v in value):
raise ValueError(
f"Vector field '{fname}' contains values outside the INT8 range (-128 to 127)"
)
# Check range for UINT8
elif datatype_str == "UINT8":
if any(v < 0 or v > 255 for v in value):
raise ValueError(
f"Vector field '{fname}' contains values outside the UINT8 range (0 to 255)"
)
# Check range for INT8
if datatype == VectorDataType.INT8:
if any(v < -128 or v > 127 for v in value):
raise ValueError(
f"Vector field '{fname}' contains values outside the INT8 range (-128 to 127)"
)
# Check range for UINT8
elif datatype == VectorDataType.UINT8:
if any(v < 0 or v > 255 for v in value):
raise ValueError(
f"Vector field '{fname}' contains values outside the UINT8 range (0 to 255)"
)
return value

return _validate_vector
Expand Down
53 changes: 53 additions & 0 deletions tests/unit/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,59 @@ def test_vector_field_validation(
)


class TestIntegerVectorRangeValidation:
"""Range checks for INT8 and UINT8 vectors given as lists (JSON storage)."""

@pytest.fixture
def int_vector_schema(self):
return IndexSchema.from_dict(
{
"index": {"name": "int-vectors", "storage_type": "json"},
"fields": [
{
"name": field_name,
"type": "vector",
"attrs": {
"algorithm": "flat",
"dims": 2,
"datatype": datatype,
"distance_metric": "l2",
},
}
for field_name, datatype in (("i8", "int8"), ("u8", "uint8"))
],
}
)

@pytest.mark.parametrize(
"field_name,value",
[
("i8", [-128, 127]),
("u8", [0, 255]),
],
)
def test_in_range_values_accepted(self, int_vector_schema, field_name, value):
assert validate_object(int_vector_schema, {field_name: value}) == {
field_name: value
}

@pytest.mark.parametrize(
"field_name,value,error_text",
[
("i8", [999, -999], "INT8 range"),
("i8", [-129, 0], "INT8 range"),
("i8", [0, 128], "INT8 range"),
("u8", [-1, 0], "UINT8 range"),
("u8", [0, 256], "UINT8 range"),
],
)
def test_out_of_range_values_rejected(
self, int_vector_schema, field_name, value, error_text
):
with pytest.raises(ValueError, match=error_text):
validate_object(int_vector_schema, {field_name: value})


class TestNestedJsonValidation:
"""Tests for JSON path-based validation with nested structures."""

Expand Down
Loading