Pewarta Proxy

📋 Server Request & Proxy Logs

Loading active proxy settings...
Developed by Khairul Adha (adhexa.id)
Mengambil log server...

⚙️ Pengaturan Proxy Target

Skip to content

Commit b2f2909

Browse files
fix: warn on scalar_map_val; fix test_unix_timestamp_list_val; document set-type behavior
Signed-off-by: abhijeet-dhumal <abhijeetdhumal652@gmail.com>
1 parent 5fff274 commit b2f2909

2 files changed

Lines changed: 59 additions & 2 deletions

File tree

‎sdk/python/feast/feature_server_utils.py‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
Values are serialized as native Python types (not wrapped dicts).
55
"""
66

7+
import logging
78
from datetime import datetime, timezone
89
from typing import Any, Dict, Optional
910

1011
from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesResponse
1112
from feast.protos.feast.types.Value_pb2 import Value
1213

14+
logger = logging.getLogger(__name__)
15+
1316
# FieldStatus enum mapping (protos/feast/serving/ServingService.proto)
1417
_STATUS_NAMES: Dict[int, str] = {
1518
0: "INVALID",
@@ -74,8 +77,12 @@ def _value_to_native(v: Value) -> Optional[Any]:
7477
{k: _value_to_native(vv) for k, vv in m.val.items()}
7578
for m in getattr(v, which).val
7679
]
77-
# scalar_map_val has non-string keys and is not JSON-serializable without extra work
80+
# scalar_map_val has non-string keys; full conversion requires extra work and
81+
# this type is not returned by standard get_online_features paths today.
7882
elif which == "scalar_map_val":
83+
logger.warning(
84+
"scalar_map_val is not yet supported by convert_response_to_dict; value will be None"
85+
)
7986
return None
8087
# All simple list/set types (.val is a repeated scalar field)
8188
elif "_list_" in which or "_set_" in which:

‎sdk/python/tests/unit/test_feature_server_utils.py‎

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
Related issue: https://github.com/feast-dev/feast/issues/6013
2222
"""
2323

24+
import json
2425
import time
2526

2627
import pytest
@@ -146,7 +147,7 @@ def test_bytes_list_val(self):
146147
assert result == [b"\x00\x01", b"\x02\x03"]
147148

148149
def test_unix_timestamp_list_val(self):
149-
v = Value(int64_list_val=Int64List(val=[1609459200, 1609545600]))
150+
v = Value(unix_timestamp_list_val=Int64List(val=[1609459200, 1609545600]))
150151
result = _value_to_native(v)
151152
assert result == [1609459200, 1609545600]
152153

@@ -447,6 +448,24 @@ def test_float_val_precision_matches_message_to_dict(self):
447448
== standard_result["results"][0]["values"]
448449
)
449450

451+
def test_set_types_return_flat_list(self):
452+
"""set types (string_set_val, int64_set_val, etc.) return flat lists.
453+
454+
Note: proto_json.patch() does not explicitly handle _set_ types — they fall
455+
through to the else branch and return the raw proto object, which MessageToDict
456+
then serializes as {"val": [...]}. Our implementation normalizes these to flat
457+
lists, which is more useful for API consumers and consistent with list types.
458+
"""
459+
response = GetOnlineFeaturesResponse()
460+
fv = response.results.add()
461+
fv.values.append(Value(string_set_val=StringSet(val=["a", "b", "c"])))
462+
fv.statuses.append(FieldStatus.PRESENT)
463+
464+
result = convert_response_to_dict(response)
465+
values = result["results"][0]["values"]
466+
assert isinstance(values[0], list), "set type should be a flat list"
467+
assert set(values[0]) == {"a", "b", "c"}
468+
450469
def test_bytes_values_match_patched_message_to_dict(self):
451470
"""Ensure bytes serialization matches proto_json.patch() format (raw bytes)."""
452471
response = GetOnlineFeaturesResponse()
@@ -463,6 +482,37 @@ def test_bytes_values_match_patched_message_to_dict(self):
463482
)
464483

465484

485+
class TestJsonSerializability:
486+
"""Ensure convert_response_to_dict output is always JSON-serializable."""
487+
488+
def test_complex_types_are_json_serializable(self):
489+
"""map_val, list_val, set_val must not leave proto objects in the output."""
490+
response = GetOnlineFeaturesResponse()
491+
fv = response.results.add()
492+
493+
# map_val
494+
m = Map()
495+
m.val["k"].CopyFrom(Value(int64_val=1))
496+
fv.values.append(Value(map_val=m))
497+
498+
# list_val (RepeatedValue)
499+
inner = RepeatedValue()
500+
inner.val.append(Value(string_val="a"))
501+
fv.values.append(Value(list_val=inner))
502+
503+
# int64_set_val
504+
fv.values.append(Value(int64_set_val=Int64Set(val=[10, 20])))
505+
506+
fv.statuses.extend(
507+
[FieldStatus.PRESENT, FieldStatus.PRESENT, FieldStatus.PRESENT]
508+
)
509+
510+
result = convert_response_to_dict(response)
511+
# must not raise
512+
serialized = json.dumps(result)
513+
assert serialized # non-empty
514+
515+
466516
class TestPerformance:
467517
"""Performance tests to validate the optimization claim."""
468518

0 commit comments

Comments
 (0)