def _infer_online_entity_rows( entity_rows: List[Union[GetOnlineFeaturesRequest.EntityRow, Dict[str, Any]]], ) -> List[GetOnlineFeaturesRequest.EntityRow]: """ Builds a list of EntityRow protos from Python native type format passed by user. Args: entity_rows: A list of dictionaries where each key is an entity and each value is feast.types.Value or Python native form. Returns: A list of EntityRow protos parsed from args. """ # Maintain backward compatibility with users providing EntityRow Proto if entity_rows and isinstance(entity_rows[0], GetOnlineFeaturesRequest.EntityRow): warnings.warn( "entity_rows parameter will only be accepting Dict format from Feast v0.7 onwards", DeprecationWarning, ) entity_rows_proto = cast( List[Union[GetOnlineFeaturesRequest.EntityRow]], entity_rows) return entity_rows_proto entity_rows_dicts = cast(List[Dict[str, Any]], entity_rows) entity_row_list = [] entity_type_map = dict() for entity in entity_rows_dicts: fields = {} for key, value in entity.items(): # Allow for feast.types.Value if isinstance(value, Value): proto_value = value else: # Infer the specific type for this row current_dtype = python_type_to_feast_value_type(name=key, value=value) if key not in entity_type_map: entity_type_map[key] = current_dtype else: if current_dtype != entity_type_map[key]: raise TypeError( f"Input entity {key} has mixed types, {current_dtype} and {entity_type_map[key]}. That is not allowed. " ) proto_value = _python_value_to_proto_value( current_dtype, value) fields[key] = proto_value entity_row_list.append( GetOnlineFeaturesRequest.EntityRow(fields=fields)) return entity_row_list
def _infer_online_entity_rows( entity_rows: List[Dict[str, Any]], ) -> List[GetOnlineFeaturesRequest.EntityRow]: """ Builds a list of EntityRow protos from Python native type format passed by user. Args: entity_rows: A list of dictionaries where each key is an entity and each value is feast.types.Value or Python native form. Returns: A list of EntityRow protos parsed from args. """ entity_rows_dicts = cast(List[Dict[str, Any]], entity_rows) entity_row_list = [] entity_type_map = dict() for entity in entity_rows_dicts: fields = {} for key, value in entity.items(): # Allow for feast.types.Value if isinstance(value, Value): proto_value = value else: # Infer the specific type for this row current_dtype = python_type_to_feast_value_type(name=key, value=value) if key not in entity_type_map: entity_type_map[key] = current_dtype else: if current_dtype != entity_type_map[key]: raise TypeError( f"Input entity {key} has mixed types, {current_dtype} and {entity_type_map[key]}. That is not allowed. " ) proto_value = _python_value_to_proto_value( current_dtype, value) fields[key] = proto_value entity_row_list.append( GetOnlineFeaturesRequest.EntityRow(fields=fields)) return entity_row_list
def _infer_online_entity_rows( entity_rows: List[Dict[str, Any]] ) -> List[GetOnlineFeaturesRequestV2.EntityRow]: """ Builds a list of EntityRow protos from Python native type format passed by user. Args: entity_rows: A list of dictionaries where each key-value is an entity-name, entity-value pair. Returns: A list of EntityRow protos parsed from args. """ entity_rows_dicts = cast(List[Dict[str, Any]], entity_rows) entity_row_list = [] entity_type_map: Dict[str, ValueType] = dict() entity_python_values_map = defaultdict(list) # Flatten keys-value dicts into lists for type inference for entity in entity_rows_dicts: for key, value in entity.items(): if isinstance(value, Value): inferred_type = _proto_value_to_value_type(value) # If any ProtoValues were present their types must all be the same if key in entity_type_map and entity_type_map.get( key) != inferred_type: raise TypeError( f"Input entity {key} has mixed types, {entity_type_map.get(key)} and {inferred_type}. That is not allowed." ) entity_type_map[key] = inferred_type else: entity_python_values_map[key].append(value) # Loop over all entities to infer dtype first in case of empty lists or nulls for key, values in entity_python_values_map.items(): inferred_type = python_values_to_feast_value_type(key, values) # If any ProtoValues were present their types must match the inferred type if key in entity_type_map and entity_type_map.get( key) != inferred_type: raise TypeError( f"Input entity {key} has mixed types, {entity_type_map.get(key)} and {inferred_type}. That is not allowed." ) entity_type_map[key] = inferred_type for entity in entity_rows_dicts: fields = {} for key, value in entity.items(): if key not in entity_type_map: raise ValueError( f"field {key} cannot have all null values for type inference." ) if isinstance(value, Value): proto_value = value else: proto_value = _python_value_to_proto_value( entity_type_map[key], value) fields[key] = proto_value entity_row_list.append( GetOnlineFeaturesRequestV2.EntityRow(fields=fields)) return entity_row_list