Skip to content

Commit e8fa514

Browse files
Add owner field to FeatureService (#2321)
* Clean up FeatureViewProjection Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Clean up FeatureService Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Continue FeatureService and FeatureViewProjection cleanup Signed-off-by: Felix Wang <wangfelix98@gmail.com>
1 parent ff3a215 commit e8fa514

File tree

3 files changed

+79
-45
lines changed

3 files changed

+79
-45
lines changed

protos/feast/core/FeatureService.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ message FeatureServiceSpec {
3232

3333
// Description of the feature service.
3434
string description = 5;
35+
36+
// Owner of the feature service.
37+
string owner = 6;
3538
}
3639

3740

sdk/python/feast/feature_service.py

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,36 @@
1111
FeatureService as FeatureServiceProto,
1212
)
1313
from feast.protos.feast.core.FeatureService_pb2 import (
14-
FeatureServiceMeta,
15-
FeatureServiceSpec,
14+
FeatureServiceMeta as FeatureServiceMetaProto,
15+
)
16+
from feast.protos.feast.core.FeatureService_pb2 import (
17+
FeatureServiceSpec as FeatureServiceSpecProto,
1618
)
1719
from feast.usage import log_exceptions
1820

1921

2022
class FeatureService:
2123
"""
22-
A feature service is a logical grouping of features for retrieval (training or serving).
23-
The features grouped by a feature service may come from any number of feature views.
24-
25-
Args:
26-
name: Unique name of the feature service.
27-
features: A list of Features that are grouped as part of this FeatureService.
28-
The list may contain Feature Views, Feature Tables, or a subset of either.
29-
tags (optional): A dictionary of key-value pairs used for organizing Feature
30-
Services.
24+
A feature service defines a logical group of features from one or more feature views.
25+
This group of features can be retrieved together during training or serving.
26+
27+
Attributes:
28+
name: The unique name of the feature service.
29+
feature_view_projections: A list containing feature views and feature view
30+
projections, representing the features in the feature service.
31+
description: A human-readable description.
32+
tags: A dictionary of key-value pairs to store arbitrary metadata.
33+
owner: The owner of the feature service, typically the email of the primary
34+
maintainer.
35+
created_timestamp: The time when the feature service was created.
36+
last_updated_timestamp: The time when the feature service was last updated.
3137
"""
3238

3339
_name: str
3440
_feature_view_projections: List[FeatureViewProjection]
41+
_description: str
3542
_tags: Dict[str, str]
36-
_description: Optional[str] = None
43+
_owner: str
3744
_created_timestamp: Optional[datetime] = None
3845
_last_updated_timestamp: Optional[datetime] = None
3946

@@ -42,8 +49,9 @@ def __init__(
4249
self,
4350
name: str,
4451
features: List[Union[FeatureView, OnDemandFeatureView]],
45-
tags: Optional[Dict[str, str]] = None,
46-
description: Optional[str] = None,
52+
tags: Dict[str, str] = None,
53+
description: str = "",
54+
owner: str = "",
4755
):
4856
"""
4957
Creates a FeatureService object.
@@ -59,12 +67,13 @@ def __init__(
5967
self._feature_view_projections.append(feature_grouping.projection)
6068
else:
6169
raise ValueError(
62-
"The FeatureService {fs_name} has been provided with an invalid type"
70+
f"The feature service {name} has been provided with an invalid type "
6371
f'{type(feature_grouping)} as part of the "features" argument.)'
6472
)
6573

66-
self._tags = tags or {}
6774
self._description = description
75+
self._tags = tags or {}
76+
self._owner = owner
6877
self._created_timestamp = None
6978
self._last_updated_timestamp = None
7079

@@ -83,7 +92,13 @@ def __eq__(self, other):
8392
raise TypeError(
8493
"Comparisons should only involve FeatureService class objects."
8594
)
86-
if self.tags != other.tags or self.name != other.name:
95+
96+
if (
97+
self.name != other.name
98+
or self.description != other.description
99+
or self.tags != other.tags
100+
or self.owner != other.owner
101+
):
87102
return False
88103

89104
if sorted(self.feature_view_projections) != sorted(
@@ -111,6 +126,14 @@ def feature_view_projections(
111126
):
112127
self._feature_view_projections = feature_view_projections
113128

129+
@property
130+
def description(self) -> str:
131+
return self._description
132+
133+
@description.setter
134+
def description(self, description: str):
135+
self._description = description
136+
114137
@property
115138
def tags(self) -> Dict[str, str]:
116139
return self._tags
@@ -120,12 +143,12 @@ def tags(self, tags: Dict[str, str]):
120143
self._tags = tags
121144

122145
@property
123-
def description(self) -> Optional[str]:
124-
return self._description
146+
def owner(self) -> str:
147+
return self._owner
125148

126-
@description.setter
127-
def description(self, description: str):
128-
self._description = description
149+
@owner.setter
150+
def owner(self, owner: str):
151+
self._owner = owner
129152

130153
@property
131154
def created_timestamp(self) -> Optional[datetime]:
@@ -143,23 +166,20 @@ def last_updated_timestamp(self) -> Optional[datetime]:
143166
def last_updated_timestamp(self, last_updated_timestamp: datetime):
144167
self._last_updated_timestamp = last_updated_timestamp
145168

146-
@staticmethod
147-
def from_proto(feature_service_proto: FeatureServiceProto):
169+
@classmethod
170+
def from_proto(cls, feature_service_proto: FeatureServiceProto):
148171
"""
149172
Converts a FeatureServiceProto to a FeatureService object.
150173
151174
Args:
152175
feature_service_proto: A protobuf representation of a FeatureService.
153176
"""
154-
fs = FeatureService(
177+
fs = cls(
155178
name=feature_service_proto.spec.name,
156179
features=[],
157180
tags=dict(feature_service_proto.spec.tags),
158-
description=(
159-
feature_service_proto.spec.description
160-
if feature_service_proto.spec.description != ""
161-
else None
162-
),
181+
description=feature_service_proto.spec.description,
182+
owner=feature_service_proto.spec.owner,
163183
)
164184
fs.feature_view_projections.extend(
165185
[
@@ -181,29 +201,28 @@ def from_proto(feature_service_proto: FeatureServiceProto):
181201

182202
def to_proto(self) -> FeatureServiceProto:
183203
"""
184-
Converts a FeatureService to its protobuf representation.
204+
Converts a feature service to its protobuf representation.
185205
186206
Returns:
187207
A FeatureServiceProto protobuf.
188208
"""
189-
meta = FeatureServiceMeta()
209+
meta = FeatureServiceMetaProto()
190210
if self.created_timestamp:
191211
meta.created_timestamp.FromDatetime(self.created_timestamp)
212+
if self.last_updated_timestamp:
213+
meta.last_updated_timestamp.FromDatetime(self.last_updated_timestamp)
192214

193-
spec = FeatureServiceSpec(
215+
spec = FeatureServiceSpecProto(
194216
name=self.name,
195217
features=[
196218
projection.to_proto() for projection in self.feature_view_projections
197219
],
220+
tags=self.tags,
221+
description=self.description,
222+
owner=self.owner,
198223
)
199224

200-
if self.tags:
201-
spec.tags.update(self.tags)
202-
if self.description:
203-
spec.description = self.description
204-
205-
feature_service_proto = FeatureServiceProto(spec=spec, meta=meta)
206-
return feature_service_proto
225+
return FeatureServiceProto(spec=spec, meta=meta)
207226

208227
def validate(self):
209228
pass

sdk/python/feast/feature_view_projection.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@
1010

1111
@dataclass
1212
class FeatureViewProjection:
13+
"""
14+
A feature view projection represents a selection of one or more features from a
15+
single feature view.
16+
17+
Attributes:
18+
name: The unique name of the feature view from which this projection is created.
19+
name_alias: An optional alias for the name.
20+
features: The list of features represented by the feature view projection.
21+
join_key_map: A map to modify join key columns during retrieval of this feature
22+
view projection.
23+
"""
24+
1325
name: str
1426
name_alias: Optional[str]
1527
features: List[Feature]
@@ -18,10 +30,10 @@ class FeatureViewProjection:
1830
def name_to_use(self):
1931
return self.name_alias or self.name
2032

21-
def to_proto(self):
33+
def to_proto(self) -> FeatureViewProjectionProto:
2234
feature_reference_proto = FeatureViewProjectionProto(
2335
feature_view_name=self.name,
24-
feature_view_name_alias=self.name_alias,
36+
feature_view_name_alias=self.name_alias or "",
2537
join_key_map=self.join_key_map,
2638
)
2739
for feature in self.features:
@@ -31,16 +43,16 @@ def to_proto(self):
3143

3244
@staticmethod
3345
def from_proto(proto: FeatureViewProjectionProto):
34-
ref = FeatureViewProjection(
46+
feature_view_projection = FeatureViewProjection(
3547
name=proto.feature_view_name,
3648
name_alias=proto.feature_view_name_alias,
3749
features=[],
3850
join_key_map=dict(proto.join_key_map),
3951
)
4052
for feature_column in proto.feature_columns:
41-
ref.features.append(Feature.from_proto(feature_column))
53+
feature_view_projection.features.append(Feature.from_proto(feature_column))
4254

43-
return ref
55+
return feature_view_projection
4456

4557
@staticmethod
4658
def from_definition(feature_grouping):

0 commit comments

Comments
 (0)