From 9b98eafccbf39b41186bfb3ebd36af20d57bd509 Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Mon, 25 Mar 2024 14:03:27 -0400 Subject: [PATCH] feat: Rename OnDemandTransformations to Transformations (#4038) * feat: updating protos to separate transformation Signed-off-by: Francisco Javier Arceo * fixed stuff...i think Signed-off-by: Francisco Javier Arceo * updated tests and registry diff function Signed-off-by: Francisco Javier Arceo * updated base registry Signed-off-by: Francisco Javier Arceo * updated react component Signed-off-by: Francisco Javier Arceo * formatted Signed-off-by: Francisco Javier Arceo * updated stream feature view proto Signed-off-by: Francisco Javier Arceo * making the proto changes backwards compatable Signed-off-by: Francisco Javier Arceo * trying to make this backwards compatible Signed-off-by: Francisco Javier Arceo * caught a bug and fixed the linter Signed-off-by: Francisco Javier Arceo * actually linted Signed-off-by: Francisco Javier Arceo * updated ui component Signed-off-by: Francisco Javier Arceo * accidentally commented out fixtures Signed-off-by: Francisco Javier Arceo * Updated Signed-off-by: Francisco Javier Arceo * incrementing protos Signed-off-by: Francisco Javier Arceo * updated tests Signed-off-by: Francisco Javier Arceo * fixed linting issue and made backwards compatible Signed-off-by: Francisco Javier Arceo * feat: Renaming OnDemandTransformations to Transformations Signed-off-by: Francisco Javier Arceo * updated proto name Signed-off-by: Francisco Javier Arceo * renamed substrait proto Signed-off-by: Francisco Javier Arceo * renamed substrait proto Signed-off-by: Francisco Javier Arceo * updated * updated Signed-off-by: Francisco Javier Arceo * updated integration test * missed one Signed-off-by: Francisco Javier Arceo * updated to include Substrait type * linter Signed-off-by: Francisco Javier Arceo --------- Signed-off-by: Francisco Javier Arceo --- protos/feast/core/OnDemandFeatureView.proto | 12 +--- protos/feast/core/Transformation.proto | 5 +- sdk/python/feast/diff/registry_diff.py | 18 +++--- .../feast/infra/registry/base_registry.py | 33 ++++++++-- sdk/python/feast/on_demand_feature_view.py | 62 +++++++++---------- sdk/python/feast/stream_feature_view.py | 10 ++- sdk/python/feast/transformation/__init__.py | 0 .../pandas_transformation.py} | 8 +-- .../substrait_transformation.py} | 20 +++--- .../feature_repos/universal/feature_views.py | 6 +- .../tests/unit/test_on_demand_feature_view.py | 25 +++----- 11 files changed, 102 insertions(+), 97 deletions(-) create mode 100644 sdk/python/feast/transformation/__init__.py rename sdk/python/feast/{on_demand_pandas_transformation.py => transformation/pandas_transformation.py} (85%) rename sdk/python/feast/{on_demand_substrait_transformation.py => transformation/substrait_transformation.py} (57%) diff --git a/protos/feast/core/OnDemandFeatureView.proto b/protos/feast/core/OnDemandFeatureView.proto index cd3ceba150..7a5fec1650 100644 --- a/protos/feast/core/OnDemandFeatureView.proto +++ b/protos/feast/core/OnDemandFeatureView.proto @@ -49,10 +49,8 @@ message OnDemandFeatureViewSpec { // Map of sources for this feature view. map sources = 4; - oneof transformation { - UserDefinedFunction user_defined_function = 5 [deprecated = true]; - OnDemandSubstraitTransformation on_demand_substrait_transformation = 9 [deprecated = true]; - } + UserDefinedFunction user_defined_function = 5 [deprecated = true]; + // Oneof with {user_defined_function, on_demand_substrait_transformation} FeatureTransformationV2 feature_transformation = 10; @@ -96,9 +94,3 @@ message UserDefinedFunction { // The string representation of the udf string body_text = 3; } - -message OnDemandSubstraitTransformation { - option deprecated = true; - - bytes substrait_plan = 1; -} diff --git a/protos/feast/core/Transformation.proto b/protos/feast/core/Transformation.proto index cde2833fa4..36f1e691fe 100644 --- a/protos/feast/core/Transformation.proto +++ b/protos/feast/core/Transformation.proto @@ -21,13 +21,12 @@ message UserDefinedFunctionV2 { // A feature transformation executed as a user-defined function message FeatureTransformationV2 { - // Note this Transformation starts at 5 for backwards compatibility oneof transformation { UserDefinedFunctionV2 user_defined_function = 1; - OnDemandSubstraitTransformationV2 on_demand_substrait_transformation = 2; + SubstraitTransformationV2 substrait_transformation = 2; } } -message OnDemandSubstraitTransformationV2 { +message SubstraitTransformationV2 { bytes substrait_plan = 1; } diff --git a/sdk/python/feast/diff/registry_diff.py b/sdk/python/feast/diff/registry_diff.py index 120f5d697a..41b2142226 100644 --- a/sdk/python/feast/diff/registry_diff.py +++ b/sdk/python/feast/diff/registry_diff.py @@ -1,4 +1,3 @@ -import warnings from dataclasses import dataclass from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, TypeVar, cast @@ -145,22 +144,23 @@ def diff_registry_objects( if _field.name in FIELDS_TO_IGNORE: continue elif getattr(current_spec, _field.name) != getattr(new_spec, _field.name): - # TODO: Delete "transformation" after we've safely deprecated it from the proto - if _field.name in ["transformation", "feature_transformation"]: - warnings.warn( - "transformation will be deprecated in the future please use feature_transformation instead.", - DeprecationWarning, - ) + if _field.name == "feature_transformation": current_spec = cast(OnDemandFeatureViewSpec, current_spec) new_spec = cast(OnDemandFeatureViewSpec, new_spec) # Check if the old proto is populated and use that if it is - deprecated_udf = current_spec.user_defined_function feature_transformation_udf = ( current_spec.feature_transformation.user_defined_function ) + if ( + current_spec.HasField("user_defined_function") + and not feature_transformation_udf + ): + deprecated_udf = current_spec.user_defined_function + else: + deprecated_udf = None current_udf = ( deprecated_udf - if deprecated_udf.body_text != "" + if deprecated_udf is not None else feature_transformation_udf ) new_udf = new_spec.feature_transformation.user_defined_function diff --git a/sdk/python/feast/infra/registry/base_registry.py b/sdk/python/feast/infra/registry/base_registry.py index d3d82a80b0..583206941e 100644 --- a/sdk/python/feast/infra/registry/base_registry.py +++ b/sdk/python/feast/infra/registry/base_registry.py @@ -33,6 +33,8 @@ from feast.request_feature_view import RequestFeatureView from feast.saved_dataset import SavedDataset, ValidationReference from feast.stream_feature_view import StreamFeatureView +from feast.transformation.pandas_transformation import PandasTransformation +from feast.transformation.substrait_transformation import SubstraitTransformation class BaseRegistry(ABC): @@ -670,10 +672,33 @@ def to_dict(self, project: str) -> Dict[str, List[Any]]: "We will be deprecating the usage of spec.userDefinedFunction in a future release please upgrade cautiously.", DeprecationWarning, ) - odfv_dict["spec"]["featureTransformation"]["userDefinedFunction"][ - "body" - ] = on_demand_feature_view.feature_transformation.udf_string - registry_dict["onDemandFeatureViews"].append(odfv_dict) + if on_demand_feature_view.feature_transformation: + if isinstance( + on_demand_feature_view.feature_transformation, PandasTransformation + ): + if "userDefinedFunction" not in odfv_dict["spec"]: + odfv_dict["spec"]["userDefinedFunction"] = {} + odfv_dict["spec"]["userDefinedFunction"][ + "body" + ] = on_demand_feature_view.feature_transformation.udf_string + odfv_dict["spec"]["featureTransformation"]["userDefinedFunction"][ + "body" + ] = on_demand_feature_view.feature_transformation.udf_string + elif isinstance( + on_demand_feature_view.feature_transformation, + SubstraitTransformation, + ): + odfv_dict["spec"]["featureTransformation"]["substraitPlan"][ + "body" + ] = on_demand_feature_view.feature_transformation.substrait_plan + else: + odfv_dict["spec"]["featureTransformation"]["userDefinedFunction"][ + "body" + ] = None + odfv_dict["spec"]["featureTransformation"]["substraitPlan"][ + "body" + ] = None + registry_dict["onDemandFeatureViews"].append(odfv_dict) for request_feature_view in sorted( self.list_request_feature_views(project=project), key=lambda request_feature_view: request_feature_view.name, diff --git a/sdk/python/feast/on_demand_feature_view.py b/sdk/python/feast/on_demand_feature_view.py index 61e55bb0c0..ce416fff2a 100644 --- a/sdk/python/feast/on_demand_feature_view.py +++ b/sdk/python/feast/on_demand_feature_view.py @@ -17,8 +17,6 @@ from feast.feature_view import FeatureView from feast.feature_view_projection import FeatureViewProjection from feast.field import Field, from_value_type -from feast.on_demand_pandas_transformation import OnDemandPandasTransformation -from feast.on_demand_substrait_transformation import OnDemandSubstraitTransformation from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( OnDemandFeatureView as OnDemandFeatureViewProto, ) @@ -33,6 +31,8 @@ from feast.protos.feast.core.Transformation_pb2 import ( UserDefinedFunctionV2 as UserDefinedFunctionProto, ) +from feast.transformation.pandas_transformation import PandasTransformation +from feast.transformation.substrait_transformation import SubstraitTransformation from feast.type_map import ( feast_value_type_to_pandas_type, python_type_to_feast_value_type, @@ -57,7 +57,7 @@ class OnDemandFeatureView(BaseFeatureView): sources with type FeatureViewProjection. source_request_sources: A map from input source names to the actual input sources with type RequestSource. - transformation: The user defined transformation. + feature_transformation: The user defined transformation. description: A human-readable description. tags: A dictionary of key-value pairs to store arbitrary metadata. owner: The owner of the on demand feature view, typically the email of the primary @@ -68,8 +68,7 @@ class OnDemandFeatureView(BaseFeatureView): features: List[Field] source_feature_view_projections: Dict[str, FeatureViewProjection] source_request_sources: Dict[str, RequestSource] - transformation: Union[OnDemandPandasTransformation] - feature_transformation: Union[OnDemandPandasTransformation] + feature_transformation: Union[PandasTransformation, SubstraitTransformation] description: str tags: Dict[str, str] owner: str @@ -89,8 +88,9 @@ def __init__( # noqa: C901 ], udf: Optional[FunctionType] = None, udf_string: str = "", - transformation: Optional[Union[OnDemandPandasTransformation]] = None, - feature_transformation: Optional[Union[OnDemandPandasTransformation]] = None, + feature_transformation: Optional[ + Union[PandasTransformation, SubstraitTransformation] + ] = None, description: str = "", tags: Optional[Dict[str, str]] = None, owner: str = "", @@ -108,7 +108,6 @@ def __init__( # noqa: C901 udf (deprecated): The user defined transformation function, which must take pandas dataframes as inputs. udf_string (deprecated): The source code version of the udf (for diffing and displaying in Web UI) - transformation: The user defined transformation. feature_transformation: The user defined transformation. description (optional): A human-readable description. tags (optional): A dictionary of key-value pairs to store arbitrary metadata. @@ -123,13 +122,13 @@ def __init__( # noqa: C901 owner=owner, ) - if not transformation: + if not feature_transformation: if udf: warnings.warn( "udf and udf_string parameters are deprecated. Please use transformation=OnDemandPandasTransformation(udf, udf_string) instead.", DeprecationWarning, ) - transformation = OnDemandPandasTransformation(udf, udf_string) + feature_transformation = PandasTransformation(udf, udf_string) else: raise Exception( "OnDemandFeatureView needs to be initialized with either transformation or udf arguments" @@ -147,8 +146,7 @@ def __init__( # noqa: C901 odfv_source.name ] = odfv_source.projection - self.transformation = transformation - self.feature_transformation = self.transformation + self.feature_transformation = feature_transformation @property def proto_class(self) -> Type[OnDemandFeatureViewProto]: @@ -160,8 +158,7 @@ def __copy__(self): schema=self.features, sources=list(self.source_feature_view_projections.values()) + list(self.source_request_sources.values()), - transformation=self.transformation, - feature_transformation=self.transformation, + feature_transformation=self.feature_transformation, description=self.description, tags=self.tags, owner=self.owner, @@ -182,7 +179,6 @@ def __eq__(self, other): self.source_feature_view_projections != other.source_feature_view_projections or self.source_request_sources != other.source_request_sources - or self.transformation != other.transformation or self.feature_transformation != other.feature_transformation ): return False @@ -218,12 +214,12 @@ def to_proto(self) -> OnDemandFeatureViewProto: ) feature_transformation = FeatureTransformationProto( - user_defined_function=self.transformation.to_proto() - if type(self.transformation) == OnDemandPandasTransformation + user_defined_function=self.feature_transformation.to_proto() + if isinstance(self.feature_transformation, PandasTransformation) + else None, + substrait_transformation=self.feature_transformation.to_proto() + if isinstance(self.feature_transformation, SubstraitTransformation) else None, - on_demand_substrait_transformation=self.transformation.to_proto() - if type(self.transformation) == OnDemandSubstraitTransformation - else None, # type: ignore ) spec = OnDemandFeatureViewSpec( name=self.name, @@ -276,17 +272,17 @@ def from_proto(cls, on_demand_feature_view_proto: OnDemandFeatureViewProto): and on_demand_feature_view_proto.spec.feature_transformation.user_defined_function.body_text != "" ): - transformation = OnDemandPandasTransformation.from_proto( + transformation = PandasTransformation.from_proto( on_demand_feature_view_proto.spec.feature_transformation.user_defined_function ) elif ( on_demand_feature_view_proto.spec.feature_transformation.WhichOneof( "transformation" ) - == "on_demand_substrait_transformation" + == "substrait_transformation" ): - transformation = OnDemandSubstraitTransformation.from_proto( - on_demand_feature_view_proto.spec.feature_transformation.on_demand_substrait_transformation + transformation = SubstraitTransformation.from_proto( + on_demand_feature_view_proto.spec.feature_transformation.substrait_transformation ) elif ( hasattr(on_demand_feature_view_proto.spec, "user_defined_function") @@ -298,7 +294,7 @@ def from_proto(cls, on_demand_feature_view_proto: OnDemandFeatureViewProto): body=on_demand_feature_view_proto.spec.user_defined_function.body, body_text=on_demand_feature_view_proto.spec.user_defined_function.body_text, ) - transformation = OnDemandPandasTransformation.from_proto( + transformation = PandasTransformation.from_proto( user_defined_function_proto=backwards_compatible_udf, ) else: @@ -314,7 +310,7 @@ def from_proto(cls, on_demand_feature_view_proto: OnDemandFeatureViewProto): for feature in on_demand_feature_view_proto.spec.features ], sources=sources, - transformation=transformation, + feature_transformation=transformation, 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, @@ -374,7 +370,9 @@ def get_transformed_features_df( # Compute transformed values and apply to each result row - df_with_transformed_features = self.transformation.transform(df_with_features) + df_with_transformed_features = self.feature_transformation.transform( + df_with_features + ) # Work out whether the correct columns names are used. rename_columns: Dict[str, str] = {} @@ -424,7 +422,7 @@ def infer_features(self) -> None: dtype = feast_value_type_to_pandas_type(field.dtype.to_value_type()) sample_val = rand_df_value[dtype] if dtype in rand_df_value else None df[f"{field.name}"] = pd.Series(sample_val, dtype=dtype) - output_df: pd.DataFrame = self.transformation.transform(df) + output_df: pd.DataFrame = self.feature_transformation.transform(df) inferred_features = [] for f, dt in zip(output_df.columns, output_df.dtypes): inferred_features.append( @@ -521,7 +519,7 @@ def decorator(user_function): input_fields: Field = [] for s in sources: - if type(s) == FeatureView: + if isinstance(s, FeatureView): fields = s.projection.features else: fields = s.features @@ -540,19 +538,19 @@ def decorator(user_function): expr = user_function(ibis.table(input_fields, "t")) - transformation = OnDemandSubstraitTransformation( + transformation = SubstraitTransformation( substrait_plan=compiler.compile(expr).SerializeToString() ) else: udf_string = dill.source.getsource(user_function) mainify(user_function) - transformation = OnDemandPandasTransformation(user_function, udf_string) + transformation = PandasTransformation(user_function, udf_string) on_demand_feature_view_obj = OnDemandFeatureView( name=user_function.__name__, sources=sources, schema=schema, - transformation=transformation, + feature_transformation=transformation, description=description, tags=tags, owner=owner, diff --git a/sdk/python/feast/stream_feature_view.py b/sdk/python/feast/stream_feature_view.py index e8741a75fe..0d1125d2bd 100644 --- a/sdk/python/feast/stream_feature_view.py +++ b/sdk/python/feast/stream_feature_view.py @@ -15,7 +15,6 @@ from feast.entity import Entity from feast.feature_view import FeatureView from feast.field import Field -from feast.on_demand_pandas_transformation import OnDemandPandasTransformation from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( UserDefinedFunction as UserDefinedFunctionProto, @@ -32,6 +31,7 @@ from feast.protos.feast.core.Transformation_pb2 import ( UserDefinedFunctionV2 as UserDefinedFunctionProtoV2, ) +from feast.transformation.pandas_transformation import PandasTransformation warnings.simplefilter("once", RuntimeWarning) @@ -80,7 +80,7 @@ class StreamFeatureView(FeatureView): materialization_intervals: List[Tuple[datetime, datetime]] udf: Optional[FunctionType] udf_string: Optional[str] - feature_transformation: Optional[OnDemandPandasTransformation] + feature_transformation: Optional[PandasTransformation] def __init__( self, @@ -99,7 +99,7 @@ def __init__( timestamp_field: Optional[str] = "", udf: Optional[FunctionType] = None, udf_string: Optional[str] = "", - feature_transformation: Optional[Union[OnDemandPandasTransformation]] = None, + feature_transformation: Optional[Union[PandasTransformation]] = None, ): if not flags_helper.is_test(): warnings.warn( @@ -371,9 +371,7 @@ def decorator(user_function): schema=schema, udf=user_function, udf_string=udf_string, - feature_transformation=OnDemandPandasTransformation( - user_function, udf_string - ), + feature_transformation=PandasTransformation(user_function, udf_string), description=description, tags=tags, online=online, diff --git a/sdk/python/feast/transformation/__init__.py b/sdk/python/feast/transformation/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sdk/python/feast/on_demand_pandas_transformation.py b/sdk/python/feast/transformation/pandas_transformation.py similarity index 85% rename from sdk/python/feast/on_demand_pandas_transformation.py rename to sdk/python/feast/transformation/pandas_transformation.py index 48f5263051..76f17e2106 100644 --- a/sdk/python/feast/on_demand_pandas_transformation.py +++ b/sdk/python/feast/transformation/pandas_transformation.py @@ -8,7 +8,7 @@ ) -class OnDemandPandasTransformation: +class PandasTransformation: def __init__(self, udf: FunctionType, udf_string: str = ""): """ Creates an OnDemandPandasTransformation object. @@ -25,9 +25,9 @@ def transform(self, df: pd.DataFrame) -> pd.DataFrame: return self.udf.__call__(df) def __eq__(self, other): - if not isinstance(other, OnDemandPandasTransformation): + if not isinstance(other, PandasTransformation): raise TypeError( - "Comparisons should only involve OnDemandPandasTransformation class objects." + "Comparisons should only involve PandasTransformation class objects." ) if ( @@ -47,7 +47,7 @@ def to_proto(self) -> UserDefinedFunctionProto: @classmethod def from_proto(cls, user_defined_function_proto: UserDefinedFunctionProto): - return OnDemandPandasTransformation( + return PandasTransformation( udf=dill.loads(user_defined_function_proto.body), udf_string=user_defined_function_proto.body_text, ) diff --git a/sdk/python/feast/on_demand_substrait_transformation.py b/sdk/python/feast/transformation/substrait_transformation.py similarity index 57% rename from sdk/python/feast/on_demand_substrait_transformation.py rename to sdk/python/feast/transformation/substrait_transformation.py index 0666739125..b3dbe7a4b4 100644 --- a/sdk/python/feast/on_demand_substrait_transformation.py +++ b/sdk/python/feast/transformation/substrait_transformation.py @@ -3,14 +3,14 @@ import pyarrow.substrait as substrait # type: ignore # noqa from feast.protos.feast.core.Transformation_pb2 import ( - OnDemandSubstraitTransformationV2 as OnDemandSubstraitTransformationProto, + SubstraitTransformationV2 as SubstraitTransformationProto, ) -class OnDemandSubstraitTransformation: +class SubstraitTransformation: def __init__(self, substrait_plan: bytes): """ - Creates an OnDemandSubstraitTransformation object. + Creates an SubstraitTransformation object. Args: substrait_plan: The user-provided substrait plan. @@ -27,9 +27,9 @@ def table_provider(names, schema: pyarrow.Schema): return table.to_pandas() def __eq__(self, other): - if not isinstance(other, OnDemandSubstraitTransformation): + if not isinstance(other, SubstraitTransformation): raise TypeError( - "Comparisons should only involve OnDemandSubstraitTransformation class objects." + "Comparisons should only involve SubstraitTransformation class objects." ) if not super().__eq__(other): @@ -37,14 +37,14 @@ def __eq__(self, other): return self.substrait_plan == other.substrait_plan - def to_proto(self) -> OnDemandSubstraitTransformationProto: - return OnDemandSubstraitTransformationProto(substrait_plan=self.substrait_plan) + def to_proto(self) -> SubstraitTransformationProto: + return SubstraitTransformationProto(substrait_plan=self.substrait_plan) @classmethod def from_proto( cls, - on_demand_substrait_transformation_proto: OnDemandSubstraitTransformationProto, + substrait_transformation_proto: SubstraitTransformationProto, ): - return OnDemandSubstraitTransformation( - substrait_plan=on_demand_substrait_transformation_proto.substrait_plan + return SubstraitTransformation( + substrait_plan=substrait_transformation_proto.substrait_plan ) diff --git a/sdk/python/tests/integration/feature_repos/universal/feature_views.py b/sdk/python/tests/integration/feature_repos/universal/feature_views.py index 421ef41601..55d2ed8425 100644 --- a/sdk/python/tests/integration/feature_repos/universal/feature_views.py +++ b/sdk/python/tests/integration/feature_repos/universal/feature_views.py @@ -15,7 +15,7 @@ ) from feast.data_source import DataSource, RequestSource from feast.feature_view_projection import FeatureViewProjection -from feast.on_demand_feature_view import OnDemandPandasTransformation +from feast.on_demand_feature_view import PandasTransformation from feast.types import Array, FeastType, Float32, Float64, Int32, Int64 from tests.integration.feature_repos.universal.entities import ( customer, @@ -71,7 +71,7 @@ def conv_rate_plus_100_feature_view( name=conv_rate_plus_100.__name__, schema=[] if infer_features else _features, sources=sources, - transformation=OnDemandPandasTransformation( + feature_transformation=PandasTransformation( udf=conv_rate_plus_100, udf_string="raw udf source" ), ) @@ -110,7 +110,7 @@ def similarity_feature_view( name=similarity.__name__, sources=sources, schema=[] if infer_features else _fields, - transformation=OnDemandPandasTransformation( + feature_transformation=PandasTransformation( udf=similarity, udf_string="similarity raw udf" ), ) diff --git a/sdk/python/tests/unit/test_on_demand_feature_view.py b/sdk/python/tests/unit/test_on_demand_feature_view.py index b83449519f..d561bd8e84 100644 --- a/sdk/python/tests/unit/test_on_demand_feature_view.py +++ b/sdk/python/tests/unit/test_on_demand_feature_view.py @@ -18,10 +18,7 @@ from feast.feature_view import FeatureView from feast.field import Field from feast.infra.offline_stores.file_source import FileSource -from feast.on_demand_feature_view import ( - OnDemandFeatureView, - OnDemandPandasTransformation, -) +from feast.on_demand_feature_view import OnDemandFeatureView, PandasTransformation from feast.types import Float32 @@ -59,7 +56,7 @@ def test_hash(): Field(name="output1", dtype=Float32), Field(name="output2", dtype=Float32), ], - transformation=OnDemandPandasTransformation( + feature_transformation=PandasTransformation( udf=udf1, udf_string="udf1 source code" ), ) @@ -70,7 +67,7 @@ def test_hash(): Field(name="output1", dtype=Float32), Field(name="output2", dtype=Float32), ], - transformation=OnDemandPandasTransformation( + feature_transformation=PandasTransformation( udf=udf1, udf_string="udf1 source code" ), ) @@ -81,7 +78,7 @@ def test_hash(): Field(name="output1", dtype=Float32), Field(name="output2", dtype=Float32), ], - transformation=OnDemandPandasTransformation( + feature_transformation=PandasTransformation( udf=udf2, udf_string="udf2 source code" ), ) @@ -92,7 +89,7 @@ def test_hash(): Field(name="output1", dtype=Float32), Field(name="output2", dtype=Float32), ], - transformation=OnDemandPandasTransformation( + feature_transformation=PandasTransformation( udf=udf2, udf_string="udf2 source code" ), description="test", @@ -126,17 +123,13 @@ def test_hash(): } assert len(s4) == 3 - assert on_demand_feature_view_5.transformation == OnDemandPandasTransformation( + assert on_demand_feature_view_5.feature_transformation == PandasTransformation( udf2, "udf2 source code" ) - assert ( - on_demand_feature_view_5.feature_transformation - == on_demand_feature_view_5.transformation - ) @pytest.mark.filterwarnings("ignore:udf and udf_string parameters are deprecated") -def test_from_proto_backwards_compatable_udf(): +def test_from_proto_backwards_compatible_udf(): file_source = FileSource(name="my-file-source", path="test.parquet") feature_view = FeatureView( name="my-feature-view", @@ -155,7 +148,7 @@ def test_from_proto_backwards_compatable_udf(): Field(name="output1", dtype=Float32), Field(name="output2", dtype=Float32), ], - transformation=OnDemandPandasTransformation( + feature_transformation=PandasTransformation( udf=udf1, udf_string="udf1 source code" ), ) @@ -164,7 +157,7 @@ def test_from_proto_backwards_compatable_udf(): # and to populate it in feature_transformation proto = on_demand_feature_view.to_proto() assert ( - on_demand_feature_view.transformation.udf_string + on_demand_feature_view.feature_transformation.udf_string == proto.spec.feature_transformation.user_defined_function.body_text ) # Because of the current set of code this is just confirming it is empty