Skip to content
Open
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
11 changes: 9 additions & 2 deletions sdk/python/feast/type_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,22 @@ def feast_value_type_to_python_type(
if val_attr in ("uuid_val", "time_uuid_val"):
return uuid_module.UUID(val) if isinstance(val, str) else val
if val_attr in ("uuid_list_val", "time_uuid_list_val"):
return [uuid_module.UUID(v) if isinstance(v, str) else v for v in val]
# None elements are stored as "" (see _LIST_NONE_DEFAULTS)
return [
None if v == "" else uuid_module.UUID(v) if isinstance(v, str) else v
for v in val
]
if val_attr in ("uuid_set_val", "time_uuid_set_val"):
return {uuid_module.UUID(v) if isinstance(v, str) else v for v in val}

# Convert DECIMAL values to decimal.Decimal objects
if val_attr == "decimal_val":
return decimal.Decimal(val) if isinstance(val, str) else val
if val_attr == "decimal_list_val":
return [decimal.Decimal(v) if isinstance(v, str) else v for v in val]
return [
None if v == "" else decimal.Decimal(v) if isinstance(v, str) else v
for v in val
]
if val_attr == "decimal_set_val":
return {decimal.Decimal(v) if isinstance(v, str) else v for v in val}

Expand Down
29 changes: 29 additions & 0 deletions sdk/python/tests/unit/test_type_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -1630,6 +1630,24 @@ def test_time_uuid_object_list_roundtrip(self):
assert all(isinstance(r, uuid.UUID) for r in result)
assert result == test_uuids

def test_uuid_list_with_none_roundtrip(self):
"""None elements in a UUID list are read back as None."""
test_uuid = uuid.uuid4()
protos = python_values_to_proto_values(
[[None, test_uuid, None]], ValueType.UUID_LIST
)
result = feast_value_type_to_python_type(protos[0])
assert result == [None, test_uuid, None]

def test_time_uuid_list_with_none_roundtrip(self):
"""None elements in a TIME_UUID list are read back as None."""
test_uuid = uuid.uuid1()
protos = python_values_to_proto_values(
[[test_uuid, None]], ValueType.TIME_UUID_LIST
)
result = feast_value_type_to_python_type(protos[0])
assert result == [test_uuid, None]

def test_uuid_set_roundtrip(self):
"""UUID set -> proto -> set of uuid.UUID objects roundtrip."""
test_uuids = {uuid.uuid4(), uuid.uuid4(), uuid.uuid4()}
Expand Down Expand Up @@ -1760,6 +1778,17 @@ def test_decimal_object_list_roundtrip(self):
assert all(isinstance(r, decimal.Decimal) for r in result)
assert result == vals

def test_decimal_list_with_none_roundtrip(self):
"""None elements in a DECIMAL_LIST are read back as None."""
import decimal

val = decimal.Decimal("1.5")
protos = python_values_to_proto_values(
[[None, val, None]], ValueType.DECIMAL_LIST
)
result = feast_value_type_to_python_type(protos[0])
assert result == [None, val, None]

def test_decimal_set_roundtrip(self):
"""DECIMAL_SET -> proto -> set of decimal.Decimal roundtrip."""
import decimal
Expand Down
Loading