@@ -140,7 +140,7 @@ class OnDemandFeatureView(BaseFeatureView):
140140 features : List [Field ]
141141 source_feature_view_projections : dict [str , FeatureViewProjection ]
142142 source_request_sources : dict [str , RequestSource ]
143- feature_transformation : Transformation
143+ feature_transformation : Optional [ Transformation ]
144144 mode : str
145145 description : str
146146 tags : dict [str , str ]
@@ -259,9 +259,12 @@ def __init__( # noqa: C901
259259 features .append (field )
260260
261261 self .features = features
262- self .feature_transformation = (
263- feature_transformation or self .get_feature_transformation ()
264- )
262+ if feature_transformation is not None :
263+ self .feature_transformation = feature_transformation
264+ elif self .udf is not None :
265+ self .feature_transformation = self .get_feature_transformation ()
266+ else :
267+ self .feature_transformation = None
265268 self .write_to_online_store = write_to_online_store
266269 self .singleton = singleton
267270 if self .singleton and self .mode != "python" :
@@ -578,11 +581,13 @@ def from_proto(
578581 A OnDemandFeatureView object based on the on-demand feature view protobuf.
579582 """
580583 # Parse sources from proto
581- sources = cls ._parse_sources_from_proto (on_demand_feature_view_proto )
584+ sources = cls ._parse_sources_from_proto (
585+ on_demand_feature_view_proto , skip_udf = skip_udf
586+ )
582587
583- # Parse transformation from proto
588+ # Parse transformation from proto (skip UDF deserialization if requested)
584589 transformation = cls ._parse_transformation_from_proto (
585- on_demand_feature_view_proto
590+ on_demand_feature_view_proto , skip_udf = skip_udf
586591 )
587592
588593 # Parse optional fields with defaults
@@ -643,7 +648,7 @@ def from_proto(
643648
644649 @classmethod
645650 def _parse_sources_from_proto (
646- cls , proto : OnDemandFeatureViewProto
651+ cls , proto : OnDemandFeatureViewProto , skip_udf : bool = False
647652 ) -> List [OnDemandSourceType ]:
648653 """Parse and convert sources from the protobuf representation."""
649654 sources : List [OnDemandSourceType ] = []
@@ -652,7 +657,9 @@ def _parse_sources_from_proto(
652657
653658 if source_type == "feature_view" :
654659 sources .append (
655- FeatureView .from_proto (on_demand_source .feature_view ).projection
660+ FeatureView .from_proto (
661+ on_demand_source .feature_view , skip_udf = skip_udf
662+ ).projection
656663 )
657664 elif source_type == "feature_view_projection" :
658665 sources .append (
@@ -673,9 +680,12 @@ def _parse_sources_from_proto(
673680
674681 @classmethod
675682 def _parse_transformation_from_proto (
676- cls , proto : OnDemandFeatureViewProto
677- ) -> Transformation :
683+ cls , proto : OnDemandFeatureViewProto , skip_udf : bool = False
684+ ) -> Optional [ Transformation ] :
678685 """Parse and convert the transformation from the protobuf representation."""
686+ if skip_udf :
687+ return None
688+
679689 feature_transformation = proto .spec .feature_transformation
680690 transformation_type = feature_transformation .WhichOneof ("transformation" )
681691 mode = proto .spec .mode
@@ -898,6 +908,7 @@ def transform_arrow(
898908 pa_table , columns_to_cleanup = self ._preprocess_arrow_table (pa_table )
899909
900910 # Apply the transformation
911+ assert self .feature_transformation is not None
901912 transformed_table = self .feature_transformation .transform_arrow (
902913 pa_table , self .features
903914 )
@@ -983,6 +994,7 @@ def transform_dict(
983994 )
984995
985996 # Apply the appropriate transformation based on mode
997+ assert self .feature_transformation is not None
986998 if self .singleton and self .mode == "python" :
987999 output_dict = self .feature_transformation .transform_singleton (
9881000 preprocessed_dict
@@ -1024,6 +1036,7 @@ def _preprocess_feature_dict(
10241036 return preprocessed_dict , columns_to_cleanup
10251037
10261038 def infer_features (self ) -> None :
1039+ assert self .feature_transformation is not None
10271040 random_input = self ._construct_random_input (singleton = self .singleton )
10281041 inferred_features = self .feature_transformation .infer_features (
10291042 random_input = random_input , singleton = self .singleton
0 commit comments