From 5f640116a787311718354a8a127458ea987fe8ce Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Tue, 4 Jun 2024 14:55:26 -0400 Subject: [PATCH 01/10] feature: Adding type to base feature view Signed-off-by: Francisco Javier Arceo --- protos/feast/core/FeatureView.proto | 1 + protos/feast/core/OnDemandFeatureView.proto | 1 + protos/feast/core/StreamFeatureView.proto | 1 + sdk/python/feast/base_feature_view.py | 11 +++++++++++ sdk/python/feast/feature_view.py | 17 ++++++++++++++++- sdk/python/feast/on_demand_feature_view.py | 11 ++++++++++- sdk/python/feast/stream_feature_view.py | 18 ++++++++++++------ 7 files changed, 52 insertions(+), 8 deletions(-) diff --git a/protos/feast/core/FeatureView.proto b/protos/feast/core/FeatureView.proto index c9e38bf344..3af96b711a 100644 --- a/protos/feast/core/FeatureView.proto +++ b/protos/feast/core/FeatureView.proto @@ -61,6 +61,7 @@ message FeatureViewSpec { // Owner of the feature view. string owner = 11; + string feature_view_type = 13; // Features in this feature view can only be retrieved from online serving // younger than ttl. Ttl is measured as the duration of time between diff --git a/protos/feast/core/OnDemandFeatureView.proto b/protos/feast/core/OnDemandFeatureView.proto index 7a5fec1650..586942119d 100644 --- a/protos/feast/core/OnDemandFeatureView.proto +++ b/protos/feast/core/OnDemandFeatureView.proto @@ -63,6 +63,7 @@ message OnDemandFeatureViewSpec { // Owner of the on demand feature view. string owner = 8; string mode = 11; + string feature_view_type = 12; } message OnDemandFeatureViewMeta { diff --git a/protos/feast/core/StreamFeatureView.proto b/protos/feast/core/StreamFeatureView.proto index cb7da0faf3..8b4b1e1f53 100644 --- a/protos/feast/core/StreamFeatureView.proto +++ b/protos/feast/core/StreamFeatureView.proto @@ -62,6 +62,7 @@ message StreamFeatureViewSpec { // Owner of the feature view. string owner = 8; + string feature_view_type = 18; // Features in this feature view can only be retrieved from online serving // younger than ttl. Ttl is measured as the duration of time between diff --git a/sdk/python/feast/base_feature_view.py b/sdk/python/feast/base_feature_view.py index 31140e2899..c96a2afaa7 100644 --- a/sdk/python/feast/base_feature_view.py +++ b/sdk/python/feast/base_feature_view.py @@ -13,6 +13,7 @@ # limitations under the License. from abc import ABC, abstractmethod from datetime import datetime +from enum import Enum from typing import Dict, List, Optional, Type, Union from google.protobuf.json_format import MessageToJson @@ -29,6 +30,12 @@ ) +class FeatureViewType(Enum): + BATCH = "Batch" + ON_DEMAND = "On Demand" + STREAM = "Stream" + + class BaseFeatureView(ABC): """ A BaseFeatureView defines a logical group of features. @@ -55,6 +62,7 @@ class BaseFeatureView(ABC): projection: FeatureViewProjection created_timestamp: Optional[datetime] last_updated_timestamp: Optional[datetime] + feature_view_type: Optional[FeatureViewType] @abstractmethod def __init__( @@ -65,6 +73,7 @@ def __init__( description: str = "", tags: Optional[Dict[str, str]] = None, owner: str = "", + feature_view_type: FeatureViewType = FeatureViewType.BATCH, ): """ Creates a BaseFeatureView object. @@ -76,6 +85,7 @@ def __init__( tags (optional): A dictionary of key-value pairs to store arbitrary metadata. owner (optional): The owner of the base feature view, typically the email of the primary maintainer. + feature_view_type (optional): The type of the feature view. Defaults to BATCH. Raises: ValueError: A field mapping conflicts with an Entity or a Feature. @@ -89,6 +99,7 @@ def __init__( self.projection = FeatureViewProjection.from_definition(self) self.created_timestamp = None self.last_updated_timestamp = None + self.feature_view_type = feature_view_type or FeatureViewType.BATCH @property @abstractmethod diff --git a/sdk/python/feast/feature_view.py b/sdk/python/feast/feature_view.py index ff41400eac..cd57ac2241 100644 --- a/sdk/python/feast/feature_view.py +++ b/sdk/python/feast/feature_view.py @@ -21,7 +21,7 @@ from typeguard import typechecked from feast import utils -from feast.base_feature_view import BaseFeatureView +from feast.base_feature_view import BaseFeatureView, FeatureViewType from feast.data_source import DataSource, KafkaSource, KinesisSource, PushSource from feast.entity import Entity from feast.feature_view_projection import FeatureViewProjection @@ -78,6 +78,7 @@ class FeatureView(BaseFeatureView): tags: A dictionary of key-value pairs to store arbitrary metadata. owner: The owner of the feature view, typically the email of the primary maintainer. + feature_view_type: The type of the feature view, one of "Batch", "On Demand", or "Stream". Defaults to "Batch". """ name: str @@ -92,6 +93,7 @@ class FeatureView(BaseFeatureView): tags: Dict[str, str] owner: str materialization_intervals: List[Tuple[datetime, datetime]] + feature_view_type: FeatureViewType def __init__( self, @@ -105,6 +107,7 @@ def __init__( description: str = "", tags: Optional[Dict[str, str]] = None, owner: str = "", + feature_view_type: FeatureViewType = FeatureViewType.BATCH, ): """ Creates a FeatureView object. @@ -126,6 +129,7 @@ def __init__( tags (optional): A dictionary of key-value pairs to store arbitrary metadata. owner (optional): The owner of the feature view, typically the email of the primary maintainer. + feature_view_type (optional): The type of the feature view, one of "Batch", "On Demand", or "Streaming". Defaults to "Batch". Raises: ValueError: A field mapping conflicts with an Entity or a Feature. @@ -133,6 +137,7 @@ def __init__( self.name = name self.entities = [e.name for e in entities] if entities else [DUMMY_ENTITY_NAME] self.ttl = ttl + self.feature_view_type = feature_view_type schema = schema or [] # Initialize data sources. @@ -206,6 +211,7 @@ def __init__( description=description, tags=tags, owner=owner, + feature_view_type=feature_view_type, ) self.online = online self.materialization_intervals = [] @@ -221,6 +227,7 @@ def __copy__(self): schema=self.schema, tags=self.tags, online=self.online, + feature_view_type=self.feature_view_type, ) # This is deliberately set outside of the FV initialization as we do not have the Entity objects. @@ -228,6 +235,7 @@ def __copy__(self): fv.features = copy.copy(self.features) fv.entity_columns = copy.copy(self.entity_columns) fv.projection = copy.copy(self.projection) + fv.feature_view_type = copy.copy(self.feature_view_type) return fv def __eq__(self, other): @@ -246,6 +254,7 @@ def __eq__(self, other): or self.batch_source != other.batch_source or self.stream_source != other.stream_source or sorted(self.entity_columns) != sorted(other.entity_columns) + or self.feature_view_type != other.feature_view_type ): return False @@ -341,6 +350,7 @@ def to_proto(self) -> FeatureViewProto: online=self.online, batch_source=batch_source_proto, stream_source=stream_source_proto, + feature_view_type=self.feature_view_type.value, ) return FeatureViewProto(spec=spec, meta=meta) @@ -356,6 +366,10 @@ def to_proto_meta(self): interval_proto.start_time.FromDatetime(interval[0]) interval_proto.end_time.FromDatetime(interval[1]) meta.materialization_intervals.append(interval_proto) + if self.feature_view_type: + meta.feature_view_type = self.feature_view_type + else: + meta.feature_view_type = FeatureViewType.BATCH return meta def get_ttl_duration(self): @@ -394,6 +408,7 @@ def from_proto(cls, feature_view_proto: FeatureViewProto): else feature_view_proto.spec.ttl.ToTimedelta() ), source=batch_source, + feature_view_type=feature_view_proto.spec.feature_view_type, ) if stream_source: feature_view.stream_source = stream_source diff --git a/sdk/python/feast/on_demand_feature_view.py b/sdk/python/feast/on_demand_feature_view.py index 839ce4d64c..a8380febf4 100644 --- a/sdk/python/feast/on_demand_feature_view.py +++ b/sdk/python/feast/on_demand_feature_view.py @@ -11,7 +11,7 @@ import pyarrow from typeguard import typechecked -from feast.base_feature_view import BaseFeatureView +from feast.base_feature_view import BaseFeatureView, FeatureViewType from feast.data_source import RequestSource from feast.errors import RegistryInferenceFailure, SpecifiedFeaturesNotPresentError from feast.feature_view import FeatureView @@ -71,6 +71,7 @@ class OnDemandFeatureView(BaseFeatureView): description: str tags: dict[str, str] owner: str + feature_view_type: FeatureViewType def __init__( # noqa: C901 self, @@ -93,6 +94,7 @@ def __init__( # noqa: C901 description: str = "", tags: Optional[dict[str, str]] = None, owner: str = "", + feature_view_type: FeatureViewType = FeatureViewType.ON_DEMAND, ): """ Creates an OnDemandFeatureView object. @@ -113,6 +115,7 @@ def __init__( # noqa: C901 tags (optional): A dictionary of key-value pairs to store arbitrary metadata. owner (optional): The owner of the on demand feature view, typically the email of the primary maintainer. + feature_view_type: The type of the feature view, one of "Batch", "On Demand", or "Streaming". Defaults to "On Demand". """ super().__init__( name=name, @@ -120,6 +123,7 @@ def __init__( # noqa: C901 description=description, tags=tags, owner=owner, + feature_view_type=feature_view_type, ) self.mode = mode.lower() @@ -174,6 +178,7 @@ def __copy__(self): description=self.description, tags=self.tags, owner=self.owner, + feature_view_type=self.feature_view_type, ) fv.projection = copy.copy(self.projection) return fv @@ -193,6 +198,7 @@ def __eq__(self, other): or self.source_request_sources != other.source_request_sources or self.mode != other.mode or self.feature_transformation != other.feature_transformation + or self.feature_view_type != other.feature_view_type ): return False @@ -246,6 +252,7 @@ def to_proto(self) -> OnDemandFeatureViewProto: description=self.description, tags=self.tags, owner=self.owner, + feature_view_type=FeatureViewType.ON_DEMAND, ) return OnDemandFeatureViewProto(spec=spec, meta=meta) @@ -350,6 +357,7 @@ def from_proto( description=on_demand_feature_view_proto.spec.description, tags=dict(on_demand_feature_view_proto.spec.tags), owner=on_demand_feature_view_proto.spec.owner, + feature_view_type=on_demand_feature_view_proto.spec.feature_view_type, ) # FeatureViewProjections are not saved in the OnDemandFeatureView proto. @@ -664,6 +672,7 @@ def decorator(user_function): description=description, tags=tags, owner=owner, + feature_view_type=FeatureViewType.ON_DEMAND, ) functools.update_wrapper( wrapper=on_demand_feature_view_obj, wrapped=user_function diff --git a/sdk/python/feast/stream_feature_view.py b/sdk/python/feast/stream_feature_view.py index 50e1a22145..35a3603a49 100644 --- a/sdk/python/feast/stream_feature_view.py +++ b/sdk/python/feast/stream_feature_view.py @@ -13,7 +13,7 @@ from feast.aggregation import Aggregation from feast.data_source import DataSource from feast.entity import Entity -from feast.feature_view import FeatureView +from feast.feature_view import FeatureView, FeatureViewType from feast.field import Field from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( @@ -61,6 +61,7 @@ class StreamFeatureView(FeatureView): tags: A dictionary of key-value pairs to store arbitrary metadata. owner: The owner of the stream feature view, typically the email of the primary maintainer. udf: The user defined transformation function. This transformation function should have all of the corresponding imports imported within the function. + feature_view_type: The type of the feature view, one of "Batch", "On Demand", or "Streaming". Defaults to "Stream". """ name: str @@ -81,6 +82,7 @@ class StreamFeatureView(FeatureView): udf: Optional[FunctionType] udf_string: Optional[str] feature_transformation: Optional[PandasTransformation] + feature_view_type = FeatureViewType.STREAM def __init__( self, @@ -100,6 +102,7 @@ def __init__( udf: Optional[FunctionType] = None, udf_string: Optional[str] = "", feature_transformation: Optional[Union[PandasTransformation]] = None, + feature_view_type=FeatureViewType.STREAM, ): if not flags_helper.is_test(): warnings.warn( @@ -128,6 +131,7 @@ def __init__( self.udf = udf self.udf_string = udf_string self.feature_transformation = feature_transformation + self.feature_view_type = feature_view_type super().__init__( name=name, @@ -139,6 +143,7 @@ def __init__( owner=owner, schema=schema, source=source, + feature_view_type=feature_view_type, ) def __eq__(self, other): @@ -159,6 +164,7 @@ def __eq__(self, other): or self.udf.__code__.co_code != other.udf.__code__.co_code or self.udf_string != other.udf_string or self.aggregations != other.aggregations + or self.feature_view_type != other.feature_view_type ): return False @@ -215,6 +221,7 @@ def to_proto(self): timestamp_field=self.timestamp_field, aggregations=[agg.to_proto() for agg in self.aggregations], mode=self.mode, + feature_view_type=self.feature_view_type, ) return StreamFeatureViewProto(spec=spec, meta=meta) @@ -241,11 +248,6 @@ def from_proto(cls, sfv_proto): if sfv_proto.spec.HasField("user_defined_function") else None ) - # feature_transformation = ( - # sfv_proto.spec.feature_transformation.user_defined_function.body_text - # if sfv_proto.spec.HasField("feature_transformation") - # else None - # ) stream_feature_view = cls( name=sfv_proto.spec.name, description=sfv_proto.spec.description, @@ -272,6 +274,7 @@ def from_proto(cls, sfv_proto): for agg_proto in sfv_proto.spec.aggregations ], timestamp_field=sfv_proto.spec.timestamp_field, + feature_view_type=sfv_proto.spec.feature_view_type, ) if batch_source: @@ -324,6 +327,7 @@ def __copy__(self): source=self.stream_source if self.stream_source else self.batch_source, udf=self.udf, feature_transformation=self.feature_transformation, + feature_view_type=self.feature_view_type, ) fv.entities = self.entities fv.features = copy.copy(self.features) @@ -349,6 +353,7 @@ def stream_feature_view( aggregations: Optional[List[Aggregation]] = None, mode: Optional[str] = "spark", timestamp_field: Optional[str] = "", + feature_view_type=FeatureViewType.STREAM, ): """ Creates an StreamFeatureView object with the given user function as udf. @@ -381,6 +386,7 @@ def decorator(user_function): aggregations=aggregations, mode=mode, timestamp_field=timestamp_field, + feature_view_type=feature_view_type, ) functools.update_wrapper(wrapper=stream_feature_view_obj, wrapped=user_function) return stream_feature_view_obj From 7d4b807ae1e33ed3901a524f40548aff7a2a7f07 Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Tue, 4 Jun 2024 21:39:41 -0400 Subject: [PATCH 02/10] fixed linter Signed-off-by: Francisco Javier Arceo --- sdk/python/feast/feature_view.py | 9 ++++++++- sdk/python/feast/on_demand_feature_view.py | 10 ++++++++-- sdk/python/feast/stream_feature_view.py | 9 ++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/sdk/python/feast/feature_view.py b/sdk/python/feast/feature_view.py index cd57ac2241..6fa1adda8e 100644 --- a/sdk/python/feast/feature_view.py +++ b/sdk/python/feast/feature_view.py @@ -396,6 +396,13 @@ def from_proto(cls, feature_view_proto: FeatureViewProto): if feature_view_proto.spec.HasField("stream_source") else None ) + + feature_view_type = ( + FeatureViewType(feature_view_proto.spec.feature_view_type) + if feature_view_proto.spec.feature_view_type != "" + else FeatureViewType.BATCH + ) + feature_view = cls( name=feature_view_proto.spec.name, description=feature_view_proto.spec.description, @@ -408,7 +415,7 @@ def from_proto(cls, feature_view_proto: FeatureViewProto): else feature_view_proto.spec.ttl.ToTimedelta() ), source=batch_source, - feature_view_type=feature_view_proto.spec.feature_view_type, + feature_view_type=feature_view_type, ) if stream_source: feature_view.stream_source = stream_source diff --git a/sdk/python/feast/on_demand_feature_view.py b/sdk/python/feast/on_demand_feature_view.py index a8380febf4..9e14b3923f 100644 --- a/sdk/python/feast/on_demand_feature_view.py +++ b/sdk/python/feast/on_demand_feature_view.py @@ -252,7 +252,7 @@ def to_proto(self) -> OnDemandFeatureViewProto: description=self.description, tags=self.tags, owner=self.owner, - feature_view_type=FeatureViewType.ON_DEMAND, + feature_view_type=self.feature_view_type.value, ) return OnDemandFeatureViewProto(spec=spec, meta=meta) @@ -342,6 +342,12 @@ def from_proto( else: raise ValueError("At least one transformation type needs to be provided") + feature_view_type = ( + FeatureViewType(on_demand_feature_view_proto.spec.feature_view_type) + if on_demand_feature_view_proto.spec.feature_view_type != "" + else FeatureViewType.ON_DEMAND + ) + on_demand_feature_view_obj = cls( name=on_demand_feature_view_proto.spec.name, schema=[ @@ -357,7 +363,7 @@ def from_proto( description=on_demand_feature_view_proto.spec.description, tags=dict(on_demand_feature_view_proto.spec.tags), owner=on_demand_feature_view_proto.spec.owner, - feature_view_type=on_demand_feature_view_proto.spec.feature_view_type, + feature_view_type=feature_view_type, ) # FeatureViewProjections are not saved in the OnDemandFeatureView proto. diff --git a/sdk/python/feast/stream_feature_view.py b/sdk/python/feast/stream_feature_view.py index 35a3603a49..f573797c0c 100644 --- a/sdk/python/feast/stream_feature_view.py +++ b/sdk/python/feast/stream_feature_view.py @@ -248,6 +248,13 @@ def from_proto(cls, sfv_proto): if sfv_proto.spec.HasField("user_defined_function") else None ) + + feature_view_type = ( + FeatureViewType(sfv_proto.spec.feature_view_type) + if sfv_proto.spec.feature_view_type != "" + else FeatureViewType.STREAM + ) + stream_feature_view = cls( name=sfv_proto.spec.name, description=sfv_proto.spec.description, @@ -274,7 +281,7 @@ def from_proto(cls, sfv_proto): for agg_proto in sfv_proto.spec.aggregations ], timestamp_field=sfv_proto.spec.timestamp_field, - feature_view_type=sfv_proto.spec.feature_view_type, + feature_view_type=feature_view_type, ) if batch_source: From 7d928a9a7a79e21380a12eddd3fe890e0997d121 Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Tue, 4 Jun 2024 21:55:18 -0400 Subject: [PATCH 03/10] fixed type and meta Signed-off-by: Francisco Javier Arceo --- sdk/python/feast/feature_view.py | 4 ---- sdk/python/feast/stream_feature_view.py | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/sdk/python/feast/feature_view.py b/sdk/python/feast/feature_view.py index 6fa1adda8e..fb4337fa07 100644 --- a/sdk/python/feast/feature_view.py +++ b/sdk/python/feast/feature_view.py @@ -366,10 +366,6 @@ def to_proto_meta(self): interval_proto.start_time.FromDatetime(interval[0]) interval_proto.end_time.FromDatetime(interval[1]) meta.materialization_intervals.append(interval_proto) - if self.feature_view_type: - meta.feature_view_type = self.feature_view_type - else: - meta.feature_view_type = FeatureViewType.BATCH return meta def get_ttl_duration(self): diff --git a/sdk/python/feast/stream_feature_view.py b/sdk/python/feast/stream_feature_view.py index f573797c0c..7c2a2da4e1 100644 --- a/sdk/python/feast/stream_feature_view.py +++ b/sdk/python/feast/stream_feature_view.py @@ -221,7 +221,7 @@ def to_proto(self): timestamp_field=self.timestamp_field, aggregations=[agg.to_proto() for agg in self.aggregations], mode=self.mode, - feature_view_type=self.feature_view_type, + feature_view_type=self.feature_view_type.value, ) return StreamFeatureViewProto(spec=spec, meta=meta) From dc98cd861561067fa48fb7d782a2e7eba967b982 Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Tue, 4 Jun 2024 22:58:33 -0400 Subject: [PATCH 04/10] adding new listing Signed-off-by: Francisco Javier Arceo --- sdk/python/feast/feature_store.py | 69 +++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index 8a0ebc6ddf..55dbd4c88f 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -257,27 +257,63 @@ def list_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: Returns: A list of feature views. """ - return self._list_feature_views(allow_cache) + return self._list_batch_feature_views(allow_cache) + def _list_feature_views( - self, - allow_cache: bool = False, - hide_dummy_entity: bool = True, + self, + allow_cache: bool = False, + hide_dummy_entity: bool = True, + ) -> List[FeatureView]: + return self._list_batch_feature_views(allow_cache) + + + def list_all_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: + """ + Retrieves the list of feature views from the registry. + + Args: + allow_cache: Whether to allow returning entities from a cached registry. + + Returns: + A list of feature views. + """ + return self._list_all_feature_views(allow_cache) + + + def list_batch_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: + """ + Retrieves the list of batch feature views from the registry. + + Args: + allow_cache: Whether to allow returning entities from a cached registry. + + Returns: + A list of feature views. + """ + return self._list_batch_feature_views(allow_cache) + + def _list_batch_feature_views( + self, + allow_cache: bool = False, + hide_dummy_entity: bool = True, ) -> List[FeatureView]: feature_views = [] for fv in self._registry.list_feature_views( - self.project, allow_cache=allow_cache + self.project, allow_cache=allow_cache ): if ( - hide_dummy_entity - and fv.entities - and fv.entities[0] == DUMMY_ENTITY_NAME + hide_dummy_entity + and fv.entities + and fv.entities[0] == DUMMY_ENTITY_NAME ): fv.entities = [] fv.entity_columns = [] feature_views.append(fv) return feature_views + + def _list_stream_feature_views( self, allow_cache: bool = False, @@ -317,6 +353,23 @@ def list_stream_feature_views( """ return self._list_stream_feature_views(allow_cache) + + def _list_all_feature_views( + self, + allow_cache: bool = False, + hide_dummy_entity: bool = True, + ) -> List[FeatureView]: + """ + Retrieves the list of all feature views from the registry. + + Returns: + A list of all feature views. + """ + return self._list_batch_feature_views(allow_cache, hide_dummy_entity) + \ + self._list_stream_feature_views(allow_cache, hide_dummy_entity) + \ + self.list_on_demand_feature_views(allow_cache) + + def list_data_sources(self, allow_cache: bool = False) -> List[DataSource]: """ Retrieves the list of data sources from the registry. From 86ec8b74785abbdcdca0a5c724b8b1ad042faa0e Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Tue, 4 Jun 2024 23:25:52 -0400 Subject: [PATCH 05/10] updated Signed-off-by: Francisco Javier Arceo --- sdk/python/feast/feature_store.py | 47 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index 55dbd4c88f..eab707904d 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -259,16 +259,16 @@ def list_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: """ return self._list_batch_feature_views(allow_cache) - def _list_feature_views( - self, - allow_cache: bool = False, - hide_dummy_entity: bool = True, + self, + allow_cache: bool = False, + hide_dummy_entity: bool = True, ) -> List[FeatureView]: return self._list_batch_feature_views(allow_cache) - - def list_all_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: + def list_all_feature_views( + self, allow_cache: bool = False + ) -> List[Union[FeatureView, StreamFeatureView, OnDemandFeatureView]]: """ Retrieves the list of feature views from the registry. @@ -280,7 +280,6 @@ def list_all_feature_views(self, allow_cache: bool = False) -> List[FeatureView] """ return self._list_all_feature_views(allow_cache) - def list_batch_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: """ Retrieves the list of batch feature views from the registry. @@ -294,26 +293,24 @@ def list_batch_feature_views(self, allow_cache: bool = False) -> List[FeatureVie return self._list_batch_feature_views(allow_cache) def _list_batch_feature_views( - self, - allow_cache: bool = False, - hide_dummy_entity: bool = True, + self, + allow_cache: bool = False, + hide_dummy_entity: bool = True, ) -> List[FeatureView]: feature_views = [] for fv in self._registry.list_feature_views( - self.project, allow_cache=allow_cache + self.project, allow_cache=allow_cache ): if ( - hide_dummy_entity - and fv.entities - and fv.entities[0] == DUMMY_ENTITY_NAME + hide_dummy_entity + and fv.entities + and fv.entities[0] == DUMMY_ENTITY_NAME ): fv.entities = [] fv.entity_columns = [] feature_views.append(fv) return feature_views - - def _list_stream_feature_views( self, allow_cache: bool = False, @@ -353,22 +350,22 @@ def list_stream_feature_views( """ return self._list_stream_feature_views(allow_cache) - def _list_all_feature_views( - self, - allow_cache: bool = False, - hide_dummy_entity: bool = True, - ) -> List[FeatureView]: + self, + allow_cache: bool = False, + hide_dummy_entity: bool = True, + ) -> List[Union[FeatureView, StreamFeatureView, OnDemandFeatureView]]: """ Retrieves the list of all feature views from the registry. Returns: A list of all feature views. """ - return self._list_batch_feature_views(allow_cache, hide_dummy_entity) + \ - self._list_stream_feature_views(allow_cache, hide_dummy_entity) + \ - self.list_on_demand_feature_views(allow_cache) - + return ( + self._list_batch_feature_views(allow_cache, hide_dummy_entity) + + self._list_stream_feature_views(allow_cache, hide_dummy_entity) + + self.list_on_demand_feature_views(allow_cache) + ) def list_data_sources(self, allow_cache: bool = False) -> List[DataSource]: """ From 838377ccf2eac9c92c8534138b79b73ec2f45379 Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Wed, 5 Jun 2024 20:49:56 -0400 Subject: [PATCH 06/10] cleaning up changes Signed-off-by: Francisco Javier Arceo --- protos/feast/core/OnDemandFeatureView.proto | 1 - protos/feast/core/StreamFeatureView.proto | 1 - sdk/python/feast/base_feature_view.py | 11 --------- sdk/python/feast/feature_view.py | 20 +---------------- sdk/python/feast/on_demand_feature_view.py | 17 +------------- sdk/python/feast/stream_feature_view.py | 25 +++++---------------- 6 files changed, 8 insertions(+), 67 deletions(-) diff --git a/protos/feast/core/OnDemandFeatureView.proto b/protos/feast/core/OnDemandFeatureView.proto index 586942119d..7a5fec1650 100644 --- a/protos/feast/core/OnDemandFeatureView.proto +++ b/protos/feast/core/OnDemandFeatureView.proto @@ -63,7 +63,6 @@ message OnDemandFeatureViewSpec { // Owner of the on demand feature view. string owner = 8; string mode = 11; - string feature_view_type = 12; } message OnDemandFeatureViewMeta { diff --git a/protos/feast/core/StreamFeatureView.proto b/protos/feast/core/StreamFeatureView.proto index 8b4b1e1f53..cb7da0faf3 100644 --- a/protos/feast/core/StreamFeatureView.proto +++ b/protos/feast/core/StreamFeatureView.proto @@ -62,7 +62,6 @@ message StreamFeatureViewSpec { // Owner of the feature view. string owner = 8; - string feature_view_type = 18; // Features in this feature view can only be retrieved from online serving // younger than ttl. Ttl is measured as the duration of time between diff --git a/sdk/python/feast/base_feature_view.py b/sdk/python/feast/base_feature_view.py index c96a2afaa7..31140e2899 100644 --- a/sdk/python/feast/base_feature_view.py +++ b/sdk/python/feast/base_feature_view.py @@ -13,7 +13,6 @@ # limitations under the License. from abc import ABC, abstractmethod from datetime import datetime -from enum import Enum from typing import Dict, List, Optional, Type, Union from google.protobuf.json_format import MessageToJson @@ -30,12 +29,6 @@ ) -class FeatureViewType(Enum): - BATCH = "Batch" - ON_DEMAND = "On Demand" - STREAM = "Stream" - - class BaseFeatureView(ABC): """ A BaseFeatureView defines a logical group of features. @@ -62,7 +55,6 @@ class BaseFeatureView(ABC): projection: FeatureViewProjection created_timestamp: Optional[datetime] last_updated_timestamp: Optional[datetime] - feature_view_type: Optional[FeatureViewType] @abstractmethod def __init__( @@ -73,7 +65,6 @@ def __init__( description: str = "", tags: Optional[Dict[str, str]] = None, owner: str = "", - feature_view_type: FeatureViewType = FeatureViewType.BATCH, ): """ Creates a BaseFeatureView object. @@ -85,7 +76,6 @@ def __init__( tags (optional): A dictionary of key-value pairs to store arbitrary metadata. owner (optional): The owner of the base feature view, typically the email of the primary maintainer. - feature_view_type (optional): The type of the feature view. Defaults to BATCH. Raises: ValueError: A field mapping conflicts with an Entity or a Feature. @@ -99,7 +89,6 @@ def __init__( self.projection = FeatureViewProjection.from_definition(self) self.created_timestamp = None self.last_updated_timestamp = None - self.feature_view_type = feature_view_type or FeatureViewType.BATCH @property @abstractmethod diff --git a/sdk/python/feast/feature_view.py b/sdk/python/feast/feature_view.py index fb4337fa07..ff41400eac 100644 --- a/sdk/python/feast/feature_view.py +++ b/sdk/python/feast/feature_view.py @@ -21,7 +21,7 @@ from typeguard import typechecked from feast import utils -from feast.base_feature_view import BaseFeatureView, FeatureViewType +from feast.base_feature_view import BaseFeatureView from feast.data_source import DataSource, KafkaSource, KinesisSource, PushSource from feast.entity import Entity from feast.feature_view_projection import FeatureViewProjection @@ -78,7 +78,6 @@ class FeatureView(BaseFeatureView): tags: A dictionary of key-value pairs to store arbitrary metadata. owner: The owner of the feature view, typically the email of the primary maintainer. - feature_view_type: The type of the feature view, one of "Batch", "On Demand", or "Stream". Defaults to "Batch". """ name: str @@ -93,7 +92,6 @@ class FeatureView(BaseFeatureView): tags: Dict[str, str] owner: str materialization_intervals: List[Tuple[datetime, datetime]] - feature_view_type: FeatureViewType def __init__( self, @@ -107,7 +105,6 @@ def __init__( description: str = "", tags: Optional[Dict[str, str]] = None, owner: str = "", - feature_view_type: FeatureViewType = FeatureViewType.BATCH, ): """ Creates a FeatureView object. @@ -129,7 +126,6 @@ def __init__( tags (optional): A dictionary of key-value pairs to store arbitrary metadata. owner (optional): The owner of the feature view, typically the email of the primary maintainer. - feature_view_type (optional): The type of the feature view, one of "Batch", "On Demand", or "Streaming". Defaults to "Batch". Raises: ValueError: A field mapping conflicts with an Entity or a Feature. @@ -137,7 +133,6 @@ def __init__( self.name = name self.entities = [e.name for e in entities] if entities else [DUMMY_ENTITY_NAME] self.ttl = ttl - self.feature_view_type = feature_view_type schema = schema or [] # Initialize data sources. @@ -211,7 +206,6 @@ def __init__( description=description, tags=tags, owner=owner, - feature_view_type=feature_view_type, ) self.online = online self.materialization_intervals = [] @@ -227,7 +221,6 @@ def __copy__(self): schema=self.schema, tags=self.tags, online=self.online, - feature_view_type=self.feature_view_type, ) # This is deliberately set outside of the FV initialization as we do not have the Entity objects. @@ -235,7 +228,6 @@ def __copy__(self): fv.features = copy.copy(self.features) fv.entity_columns = copy.copy(self.entity_columns) fv.projection = copy.copy(self.projection) - fv.feature_view_type = copy.copy(self.feature_view_type) return fv def __eq__(self, other): @@ -254,7 +246,6 @@ def __eq__(self, other): or self.batch_source != other.batch_source or self.stream_source != other.stream_source or sorted(self.entity_columns) != sorted(other.entity_columns) - or self.feature_view_type != other.feature_view_type ): return False @@ -350,7 +341,6 @@ def to_proto(self) -> FeatureViewProto: online=self.online, batch_source=batch_source_proto, stream_source=stream_source_proto, - feature_view_type=self.feature_view_type.value, ) return FeatureViewProto(spec=spec, meta=meta) @@ -392,13 +382,6 @@ def from_proto(cls, feature_view_proto: FeatureViewProto): if feature_view_proto.spec.HasField("stream_source") else None ) - - feature_view_type = ( - FeatureViewType(feature_view_proto.spec.feature_view_type) - if feature_view_proto.spec.feature_view_type != "" - else FeatureViewType.BATCH - ) - feature_view = cls( name=feature_view_proto.spec.name, description=feature_view_proto.spec.description, @@ -411,7 +394,6 @@ def from_proto(cls, feature_view_proto: FeatureViewProto): else feature_view_proto.spec.ttl.ToTimedelta() ), source=batch_source, - feature_view_type=feature_view_type, ) if stream_source: feature_view.stream_source = stream_source diff --git a/sdk/python/feast/on_demand_feature_view.py b/sdk/python/feast/on_demand_feature_view.py index 9e14b3923f..839ce4d64c 100644 --- a/sdk/python/feast/on_demand_feature_view.py +++ b/sdk/python/feast/on_demand_feature_view.py @@ -11,7 +11,7 @@ import pyarrow from typeguard import typechecked -from feast.base_feature_view import BaseFeatureView, FeatureViewType +from feast.base_feature_view import BaseFeatureView from feast.data_source import RequestSource from feast.errors import RegistryInferenceFailure, SpecifiedFeaturesNotPresentError from feast.feature_view import FeatureView @@ -71,7 +71,6 @@ class OnDemandFeatureView(BaseFeatureView): description: str tags: dict[str, str] owner: str - feature_view_type: FeatureViewType def __init__( # noqa: C901 self, @@ -94,7 +93,6 @@ def __init__( # noqa: C901 description: str = "", tags: Optional[dict[str, str]] = None, owner: str = "", - feature_view_type: FeatureViewType = FeatureViewType.ON_DEMAND, ): """ Creates an OnDemandFeatureView object. @@ -115,7 +113,6 @@ def __init__( # noqa: C901 tags (optional): A dictionary of key-value pairs to store arbitrary metadata. owner (optional): The owner of the on demand feature view, typically the email of the primary maintainer. - feature_view_type: The type of the feature view, one of "Batch", "On Demand", or "Streaming". Defaults to "On Demand". """ super().__init__( name=name, @@ -123,7 +120,6 @@ def __init__( # noqa: C901 description=description, tags=tags, owner=owner, - feature_view_type=feature_view_type, ) self.mode = mode.lower() @@ -178,7 +174,6 @@ def __copy__(self): description=self.description, tags=self.tags, owner=self.owner, - feature_view_type=self.feature_view_type, ) fv.projection = copy.copy(self.projection) return fv @@ -198,7 +193,6 @@ def __eq__(self, other): or self.source_request_sources != other.source_request_sources or self.mode != other.mode or self.feature_transformation != other.feature_transformation - or self.feature_view_type != other.feature_view_type ): return False @@ -252,7 +246,6 @@ def to_proto(self) -> OnDemandFeatureViewProto: description=self.description, tags=self.tags, owner=self.owner, - feature_view_type=self.feature_view_type.value, ) return OnDemandFeatureViewProto(spec=spec, meta=meta) @@ -342,12 +335,6 @@ def from_proto( else: raise ValueError("At least one transformation type needs to be provided") - feature_view_type = ( - FeatureViewType(on_demand_feature_view_proto.spec.feature_view_type) - if on_demand_feature_view_proto.spec.feature_view_type != "" - else FeatureViewType.ON_DEMAND - ) - on_demand_feature_view_obj = cls( name=on_demand_feature_view_proto.spec.name, schema=[ @@ -363,7 +350,6 @@ def from_proto( description=on_demand_feature_view_proto.spec.description, tags=dict(on_demand_feature_view_proto.spec.tags), owner=on_demand_feature_view_proto.spec.owner, - feature_view_type=feature_view_type, ) # FeatureViewProjections are not saved in the OnDemandFeatureView proto. @@ -678,7 +664,6 @@ def decorator(user_function): description=description, tags=tags, owner=owner, - feature_view_type=FeatureViewType.ON_DEMAND, ) functools.update_wrapper( wrapper=on_demand_feature_view_obj, wrapped=user_function diff --git a/sdk/python/feast/stream_feature_view.py b/sdk/python/feast/stream_feature_view.py index 7c2a2da4e1..50e1a22145 100644 --- a/sdk/python/feast/stream_feature_view.py +++ b/sdk/python/feast/stream_feature_view.py @@ -13,7 +13,7 @@ from feast.aggregation import Aggregation from feast.data_source import DataSource from feast.entity import Entity -from feast.feature_view import FeatureView, FeatureViewType +from feast.feature_view import FeatureView from feast.field import Field from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( @@ -61,7 +61,6 @@ class StreamFeatureView(FeatureView): tags: A dictionary of key-value pairs to store arbitrary metadata. owner: The owner of the stream feature view, typically the email of the primary maintainer. udf: The user defined transformation function. This transformation function should have all of the corresponding imports imported within the function. - feature_view_type: The type of the feature view, one of "Batch", "On Demand", or "Streaming". Defaults to "Stream". """ name: str @@ -82,7 +81,6 @@ class StreamFeatureView(FeatureView): udf: Optional[FunctionType] udf_string: Optional[str] feature_transformation: Optional[PandasTransformation] - feature_view_type = FeatureViewType.STREAM def __init__( self, @@ -102,7 +100,6 @@ def __init__( udf: Optional[FunctionType] = None, udf_string: Optional[str] = "", feature_transformation: Optional[Union[PandasTransformation]] = None, - feature_view_type=FeatureViewType.STREAM, ): if not flags_helper.is_test(): warnings.warn( @@ -131,7 +128,6 @@ def __init__( self.udf = udf self.udf_string = udf_string self.feature_transformation = feature_transformation - self.feature_view_type = feature_view_type super().__init__( name=name, @@ -143,7 +139,6 @@ def __init__( owner=owner, schema=schema, source=source, - feature_view_type=feature_view_type, ) def __eq__(self, other): @@ -164,7 +159,6 @@ def __eq__(self, other): or self.udf.__code__.co_code != other.udf.__code__.co_code or self.udf_string != other.udf_string or self.aggregations != other.aggregations - or self.feature_view_type != other.feature_view_type ): return False @@ -221,7 +215,6 @@ def to_proto(self): timestamp_field=self.timestamp_field, aggregations=[agg.to_proto() for agg in self.aggregations], mode=self.mode, - feature_view_type=self.feature_view_type.value, ) return StreamFeatureViewProto(spec=spec, meta=meta) @@ -248,13 +241,11 @@ def from_proto(cls, sfv_proto): if sfv_proto.spec.HasField("user_defined_function") else None ) - - feature_view_type = ( - FeatureViewType(sfv_proto.spec.feature_view_type) - if sfv_proto.spec.feature_view_type != "" - else FeatureViewType.STREAM - ) - + # feature_transformation = ( + # sfv_proto.spec.feature_transformation.user_defined_function.body_text + # if sfv_proto.spec.HasField("feature_transformation") + # else None + # ) stream_feature_view = cls( name=sfv_proto.spec.name, description=sfv_proto.spec.description, @@ -281,7 +272,6 @@ def from_proto(cls, sfv_proto): for agg_proto in sfv_proto.spec.aggregations ], timestamp_field=sfv_proto.spec.timestamp_field, - feature_view_type=feature_view_type, ) if batch_source: @@ -334,7 +324,6 @@ def __copy__(self): source=self.stream_source if self.stream_source else self.batch_source, udf=self.udf, feature_transformation=self.feature_transformation, - feature_view_type=self.feature_view_type, ) fv.entities = self.entities fv.features = copy.copy(self.features) @@ -360,7 +349,6 @@ def stream_feature_view( aggregations: Optional[List[Aggregation]] = None, mode: Optional[str] = "spark", timestamp_field: Optional[str] = "", - feature_view_type=FeatureViewType.STREAM, ): """ Creates an StreamFeatureView object with the given user function as udf. @@ -393,7 +381,6 @@ def decorator(user_function): aggregations=aggregations, mode=mode, timestamp_field=timestamp_field, - feature_view_type=feature_view_type, ) functools.update_wrapper(wrapper=stream_feature_view_obj, wrapped=user_function) return stream_feature_view_obj From c404579bb088450a83faa8c36cd0f309bc109002 Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Wed, 5 Jun 2024 20:50:21 -0400 Subject: [PATCH 07/10] reverting FV proto Signed-off-by: Francisco Javier Arceo --- protos/feast/core/FeatureView.proto | 1 - 1 file changed, 1 deletion(-) diff --git a/protos/feast/core/FeatureView.proto b/protos/feast/core/FeatureView.proto index 3af96b711a..c9e38bf344 100644 --- a/protos/feast/core/FeatureView.proto +++ b/protos/feast/core/FeatureView.proto @@ -61,7 +61,6 @@ message FeatureViewSpec { // Owner of the feature view. string owner = 11; - string feature_view_type = 13; // Features in this feature view can only be retrieved from online serving // younger than ttl. Ttl is measured as the duration of time between From 55c9879edd14139f9973b870df25b5ff895a148b Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Wed, 5 Jun 2024 21:18:29 -0400 Subject: [PATCH 08/10] doing simple way Signed-off-by: Francisco Javier Arceo --- sdk/python/feast/feature_store.py | 57 ++++++++----------------------- 1 file changed, 15 insertions(+), 42 deletions(-) diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index eab707904d..3c0e1437cb 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -247,7 +247,7 @@ def list_feature_services(self) -> List[FeatureService]: """ return self._registry.list_feature_services(self.project) - def list_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: + def list_all_feature_views(self, allow_cache: bool = False) -> List[Union[FeatureView, StreamFeatureView, OnDemandFeatureView]]: """ Retrieves the list of feature views from the registry. @@ -257,18 +257,9 @@ def list_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: Returns: A list of feature views. """ - return self._list_batch_feature_views(allow_cache) - - def _list_feature_views( - self, - allow_cache: bool = False, - hide_dummy_entity: bool = True, - ) -> List[FeatureView]: - return self._list_batch_feature_views(allow_cache) + return self._list_all_feature_views(allow_cache) - def list_all_feature_views( - self, allow_cache: bool = False - ) -> List[Union[FeatureView, StreamFeatureView, OnDemandFeatureView]]: + def list_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: """ Retrieves the list of feature views from the registry. @@ -278,21 +269,20 @@ def list_all_feature_views( Returns: A list of feature views. """ - return self._list_all_feature_views(allow_cache) - - def list_batch_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: - """ - Retrieves the list of batch feature views from the registry. - - Args: - allow_cache: Whether to allow returning entities from a cached registry. + return self._list_feature_views(allow_cache) - Returns: - A list of feature views. - """ - return self._list_batch_feature_views(allow_cache) + def _list_all_feature_views( + self, + allow_cache: bool = False, + ) -> List[Union[FeatureView, StreamFeatureView, OnDemandFeatureView]]: + all_feature_views = ( + self._list_feature_views(allow_cache) + + self._list_stream_feature_views(allow_cache) + + self.list_on_demand_feature_views(allow_cache) + ) + return all_feature_views - def _list_batch_feature_views( + def _list_feature_views( self, allow_cache: bool = False, hide_dummy_entity: bool = True, @@ -350,23 +340,6 @@ def list_stream_feature_views( """ return self._list_stream_feature_views(allow_cache) - def _list_all_feature_views( - self, - allow_cache: bool = False, - hide_dummy_entity: bool = True, - ) -> List[Union[FeatureView, StreamFeatureView, OnDemandFeatureView]]: - """ - Retrieves the list of all feature views from the registry. - - Returns: - A list of all feature views. - """ - return ( - self._list_batch_feature_views(allow_cache, hide_dummy_entity) - + self._list_stream_feature_views(allow_cache, hide_dummy_entity) - + self.list_on_demand_feature_views(allow_cache) - ) - def list_data_sources(self, allow_cache: bool = False) -> List[DataSource]: """ Retrieves the list of data sources from the registry. From a9fd5867ce7ab30939293173b53c62ad6f68730d Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Wed, 5 Jun 2024 21:47:31 -0400 Subject: [PATCH 09/10] added a test Signed-off-by: Francisco Javier Arceo --- sdk/python/feast/feature_store.py | 4 +++- sdk/python/tests/unit/test_on_demand_python_transformation.py | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index 3c0e1437cb..f4f1717ca7 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -247,7 +247,9 @@ def list_feature_services(self) -> List[FeatureService]: """ return self._registry.list_feature_services(self.project) - def list_all_feature_views(self, allow_cache: bool = False) -> List[Union[FeatureView, StreamFeatureView, OnDemandFeatureView]]: + def list_all_feature_views( + self, allow_cache: bool = False + ) -> List[Union[FeatureView, StreamFeatureView, OnDemandFeatureView]]: """ Retrieves the list of feature views from the registry. diff --git a/sdk/python/tests/unit/test_on_demand_python_transformation.py b/sdk/python/tests/unit/test_on_demand_python_transformation.py index ebe797ffdb..72e9b53a10 100644 --- a/sdk/python/tests/unit/test_on_demand_python_transformation.py +++ b/sdk/python/tests/unit/test_on_demand_python_transformation.py @@ -159,6 +159,10 @@ def python_singleton_view(inputs: dict[str, Any]) -> dict[str, Any]: self.store.write_to_online_store( feature_view_name="driver_hourly_stats", df=driver_df ) + assert len(self.store.list_all_feature_views()) == 4 + assert len(self.store.list_feature_views()) == 1 + assert len(self.store.list_on_demand_feature_views()) == 3 + assert len(self.store.list_stream_feature_views()) == 0 def test_python_pandas_parity(self): entity_rows = [ From dc754fdb772edac14a9c57b7c118f1445b5b3f31 Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Fri, 7 Jun 2024 22:11:23 -0400 Subject: [PATCH 10/10] updated to add warnings Signed-off-by: Francisco Javier Arceo --- sdk/python/feast/feature_store.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index f4f1717ca7..97b7c5456f 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -13,6 +13,7 @@ # limitations under the License. import copy import itertools +import logging import os import warnings from collections import Counter, defaultdict @@ -271,6 +272,10 @@ def list_feature_views(self, allow_cache: bool = False) -> List[FeatureView]: Returns: A list of feature views. """ + logging.warning( + "list_feature_views will make breaking changes. Please use list_batch_feature_views instead. " + "list_feature_views will behave like list_all_feature_views in the future." + ) return self._list_feature_views(allow_cache) def _list_all_feature_views( @@ -288,6 +293,29 @@ def _list_feature_views( self, allow_cache: bool = False, hide_dummy_entity: bool = True, + ) -> List[FeatureView]: + logging.warning( + "_list_feature_views will make breaking changes. Please use _list_batch_feature_views instead. " + "_list_feature_views will behave like _list_all_feature_views in the future." + ) + feature_views = [] + for fv in self._registry.list_feature_views( + self.project, allow_cache=allow_cache + ): + if ( + hide_dummy_entity + and fv.entities + and fv.entities[0] == DUMMY_ENTITY_NAME + ): + fv.entities = [] + fv.entity_columns = [] + feature_views.append(fv) + return feature_views + + def _list_batch_feature_views( + self, + allow_cache: bool = False, + hide_dummy_entity: bool = True, ) -> List[FeatureView]: feature_views = [] for fv in self._registry.list_feature_views(