|
26 | 26 | from feast.type_map import ( |
27 | 27 | _proto_value_to_value_type, |
28 | 28 | _python_value_to_proto_value, |
29 | | - feast_value_type_to_python_type, |
30 | 29 | python_values_to_feast_value_type, |
31 | 30 | ) |
32 | 31 | from feast.value_type import ValueType |
@@ -63,14 +62,34 @@ def to_dict(self) -> Dict[str, Any]: |
63 | 62 | """ |
64 | 63 | Converts GetOnlineFeaturesResponse features into a dictionary form. |
65 | 64 | """ |
| 65 | + # Status for every Feature should be present in every record. |
66 | 66 | features_dict: Dict[str, List[Any]] = { |
67 | | - k: list() for row in self.field_values for k, _ in row.statuses.items() |
| 67 | + k: list() for k in self.field_values[0].statuses.keys() |
68 | 68 | } |
69 | | - |
70 | | - for row in self.field_values: |
71 | | - for feature in features_dict.keys(): |
72 | | - native_type_value = feast_value_type_to_python_type(row.fields[feature]) |
73 | | - features_dict[feature].append(native_type_value) |
| 69 | + rows = [record.fields for record in self.field_values] |
| 70 | + |
| 71 | + # Find the first non-null instance of each Feature to determine |
| 72 | + # which ValueType. |
| 73 | + val_types = {k: None for k in features_dict.keys()} |
| 74 | + for feature in features_dict.keys(): |
| 75 | + for row in rows: |
| 76 | + try: |
| 77 | + val_types[feature] = row[feature].WhichOneof("val") |
| 78 | + except KeyError: |
| 79 | + continue |
| 80 | + if val_types[feature] is not None: |
| 81 | + break |
| 82 | + |
| 83 | + # Now we know what attribute to fetch. |
| 84 | + for feature, val_type in val_types.items(): |
| 85 | + if val_type is None: |
| 86 | + features_dict[feature] = [None] * len(rows) |
| 87 | + else: |
| 88 | + for row in rows: |
| 89 | + val = getattr(row[feature], val_type) |
| 90 | + if "_list_" in val_type: |
| 91 | + val = list(val.val) |
| 92 | + features_dict[feature].append(val) |
74 | 93 |
|
75 | 94 | return features_dict |
76 | 95 |
|
|
0 commit comments