@@ -59,12 +59,12 @@ class OnDemandFeatureView(BaseFeatureView):
5959 maintainer.
6060 """
6161
62- # TODO(adchia): remove inputs from proto and declaration
6362 name : str
6463 features : List [Field ]
6564 source_feature_view_projections : Dict [str , FeatureViewProjection ]
6665 source_request_sources : Dict [str , RequestSource ]
6766 udf : FunctionType
67+ udf_string : str
6868 description : str
6969 tags : Dict [str , str ]
7070 owner : str
@@ -83,6 +83,7 @@ def __init__( # noqa: C901
8383 ]
8484 ],
8585 udf : FunctionType ,
86+ udf_string : str = "" ,
8687 description : str = "" ,
8788 tags : Optional [Dict [str , str ]] = None ,
8889 owner : str = "" ,
@@ -99,6 +100,7 @@ def __init__( # noqa: C901
99100 which will refer to them by name.
100101 udf: The user defined transformation function, which must take pandas
101102 dataframes as inputs.
103+ udf_string: The source code version of the udf (for diffing and displaying in Web UI)
102104 description (optional): A human-readable description.
103105 tags (optional): A dictionary of key-value pairs to store arbitrary metadata.
104106 owner (optional): The owner of the on demand feature view, typically the email
@@ -125,6 +127,7 @@ def __init__( # noqa: C901
125127 ] = odfv_source .projection
126128
127129 self .udf = udf # type: ignore
130+ self .udf_string = udf_string
128131
129132 @property
130133 def proto_class (self ) -> Type [OnDemandFeatureViewProto ]:
@@ -137,6 +140,7 @@ def __copy__(self):
137140 sources = list (self .source_feature_view_projections .values ())
138141 + list (self .source_request_sources .values ()),
139142 udf = self .udf ,
143+ udf_string = self .udf_string ,
140144 description = self .description ,
141145 tags = self .tags ,
142146 owner = self .owner ,
@@ -157,6 +161,7 @@ def __eq__(self, other):
157161 self .source_feature_view_projections
158162 != other .source_feature_view_projections
159163 or self .source_request_sources != other .source_request_sources
164+ or self .udf_string != other .udf_string
160165 or self .udf .__code__ .co_code != other .udf .__code__ .co_code
161166 ):
162167 return False
@@ -198,6 +203,7 @@ def to_proto(self) -> OnDemandFeatureViewProto:
198203 user_defined_function = UserDefinedFunctionProto (
199204 name = self .udf .__name__ ,
200205 body = dill .dumps (self .udf , recurse = True ),
206+ body_text = self .udf_string ,
201207 ),
202208 description = self .description ,
203209 tags = self .tags ,
@@ -250,6 +256,7 @@ def from_proto(cls, on_demand_feature_view_proto: OnDemandFeatureViewProto):
250256 udf = dill .loads (
251257 on_demand_feature_view_proto .spec .user_defined_function .body
252258 ),
259+ udf_string = on_demand_feature_view_proto .spec .user_defined_function .body_text ,
253260 description = on_demand_feature_view_proto .spec .description ,
254261 tags = dict (on_demand_feature_view_proto .spec .tags ),
255262 owner = on_demand_feature_view_proto .spec .owner ,
@@ -438,6 +445,7 @@ def mainify(obj):
438445 obj .__module__ = "__main__"
439446
440447 def decorator (user_function ):
448+ udf_string = dill .source .getsource (user_function )
441449 mainify (user_function )
442450 on_demand_feature_view_obj = OnDemandFeatureView (
443451 name = user_function .__name__ ,
@@ -447,6 +455,7 @@ def decorator(user_function):
447455 description = description ,
448456 tags = tags ,
449457 owner = owner ,
458+ udf_string = udf_string ,
450459 )
451460 functools .update_wrapper (
452461 wrapper = on_demand_feature_view_obj , wrapped = user_function
0 commit comments