Skip to content

Commit 91decd6

Browse files
committed
add tags filtering capability to 'list' for objects
Signed-off-by: Tommy Hughes <[email protected]>
1 parent 849f590 commit 91decd6

File tree

19 files changed

+555
-157
lines changed

19 files changed

+555
-157
lines changed

protos/feast/registry/RegistryServer.proto

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ message GetEntityRequest {
117117
message ListEntitiesRequest {
118118
string project = 1;
119119
bool allow_cache = 2;
120+
map<string,string> tags = 3;
120121
}
121122

122123
message ListEntitiesResponse {
@@ -146,6 +147,7 @@ message GetDataSourceRequest {
146147
message ListDataSourcesRequest {
147148
string project = 1;
148149
bool allow_cache = 2;
150+
map<string,string> tags = 3;
149151
}
150152

151153
message ListDataSourcesResponse {
@@ -179,6 +181,7 @@ message GetFeatureViewRequest {
179181
message ListFeatureViewsRequest {
180182
string project = 1;
181183
bool allow_cache = 2;
184+
map<string,string> tags = 3;
182185
}
183186

184187
message ListFeatureViewsResponse {
@@ -202,6 +205,7 @@ message GetStreamFeatureViewRequest {
202205
message ListStreamFeatureViewsRequest {
203206
string project = 1;
204207
bool allow_cache = 2;
208+
map<string,string> tags = 3;
205209
}
206210

207211
message ListStreamFeatureViewsResponse {
@@ -219,6 +223,7 @@ message GetOnDemandFeatureViewRequest {
219223
message ListOnDemandFeatureViewsRequest {
220224
string project = 1;
221225
bool allow_cache = 2;
226+
map<string,string> tags = 3;
222227
}
223228

224229
message ListOnDemandFeatureViewsResponse {
@@ -242,6 +247,7 @@ message GetFeatureServiceRequest {
242247
message ListFeatureServicesRequest {
243248
string project = 1;
244249
bool allow_cache = 2;
250+
map<string,string> tags = 3;
245251
}
246252

247253
message ListFeatureServicesResponse {

sdk/python/feast/cli.py

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
from feast.utils import maybe_local_tz
4848

4949
_logger = logging.getLogger(__name__)
50+
tagsOption = click.option(
51+
"--tags",
52+
help="Filter by tags (e.g. 'key:value, key:value, ...')",
53+
multiple=True,
54+
)
5055

5156

5257
class NoOptionDefaultFormat(click.Command):
@@ -226,14 +231,16 @@ def data_source_describe(ctx: click.Context, name: str):
226231

227232

228233
@data_sources_cmd.command(name="list")
234+
@tagsOption
229235
@click.pass_context
230-
def data_source_list(ctx: click.Context):
236+
def data_source_list(ctx: click.Context, tags: Optional[str]):
231237
"""
232238
List all data sources
233239
"""
234240
store = create_feature_store(ctx)
235241
table = []
236-
for datasource in store.list_data_sources():
242+
tags_filter = utils.tags_str_to_dict(tags)
243+
for datasource in store.list_data_sources(tags=tags_filter):
237244
table.append([datasource.name, datasource.__class__])
238245

239246
from tabulate import tabulate
@@ -272,14 +279,16 @@ def entity_describe(ctx: click.Context, name: str):
272279

273280

274281
@entities_cmd.command(name="list")
282+
@tagsOption
275283
@click.pass_context
276-
def entity_list(ctx: click.Context):
284+
def entity_list(ctx: click.Context, tags: Optional[str]):
277285
"""
278286
List all entities
279287
"""
280288
store = create_feature_store(ctx)
281289
table = []
282-
for entity in store.list_entities():
290+
tags_filter = utils.tags_str_to_dict(tags)
291+
for entity in store.list_entities(tags=tags_filter):
283292
table.append([entity.name, entity.description, entity.value_type])
284293

285294
from tabulate import tabulate
@@ -320,14 +329,16 @@ def feature_service_describe(ctx: click.Context, name: str):
320329

321330

322331
@feature_services_cmd.command(name="list")
332+
@tagsOption
323333
@click.pass_context
324-
def feature_service_list(ctx: click.Context):
334+
def feature_service_list(ctx: click.Context, tags: Optional[str]):
325335
"""
326336
List all feature services
327337
"""
328338
store = create_feature_store(ctx)
329339
feature_services = []
330-
for feature_service in store.list_feature_services():
340+
tags_filter = utils.tags_str_to_dict(tags)
341+
for feature_service in store.list_feature_services(tags=tags_filter):
331342
feature_names = []
332343
for projection in feature_service.feature_view_projections:
333344
feature_names.extend(
@@ -371,16 +382,18 @@ def feature_view_describe(ctx: click.Context, name: str):
371382

372383

373384
@feature_views_cmd.command(name="list")
385+
@tagsOption
374386
@click.pass_context
375-
def feature_view_list(ctx: click.Context):
387+
def feature_view_list(ctx: click.Context, tags: Optional[str]):
376388
"""
377389
List all feature views
378390
"""
379391
store = create_feature_store(ctx)
380392
table = []
393+
tags_filter = utils.tags_str_to_dict(tags)
381394
for feature_view in [
382-
*store.list_feature_views(),
383-
*store.list_on_demand_feature_views(),
395+
*store.list_batch_feature_views(tags=tags_filter),
396+
*store.list_on_demand_feature_views(tags=tags_filter),
384397
]:
385398
entities = set()
386399
if isinstance(feature_view, FeatureView):
@@ -434,14 +447,16 @@ def on_demand_feature_view_describe(ctx: click.Context, name: str):
434447

435448

436449
@on_demand_feature_views_cmd.command(name="list")
450+
@tagsOption
437451
@click.pass_context
438-
def on_demand_feature_view_list(ctx: click.Context):
452+
def on_demand_feature_view_list(ctx: click.Context, tags: Optional[str]):
439453
"""
440454
[Experimental] List all on demand feature views
441455
"""
442456
store = create_feature_store(ctx)
443457
table = []
444-
for on_demand_feature_view in store.list_on_demand_feature_views():
458+
tags_filter = utils.tags_str_to_dict(tags)
459+
for on_demand_feature_view in store.list_on_demand_feature_views(tags=tags_filter):
445460
table.append([on_demand_feature_view.name])
446461

447462
from tabulate import tabulate

sdk/python/feast/feature_store.py

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -215,41 +215,52 @@ def refresh_registry(self):
215215

216216
self._registry = registry
217217

218-
def list_entities(self, allow_cache: bool = False) -> List[Entity]:
218+
def list_entities(
219+
self, allow_cache: bool = False, tags: Optional[dict[str, str]] = None
220+
) -> List[Entity]:
219221
"""
220222
Retrieves the list of entities from the registry.
221223
222224
Args:
223225
allow_cache: Whether to allow returning entities from a cached registry.
226+
tags: Filter by tags.
224227
225228
Returns:
226229
A list of entities.
227230
"""
228-
return self._list_entities(allow_cache)
231+
return self._list_entities(allow_cache, tags=tags)
229232

230233
def _list_entities(
231-
self, allow_cache: bool = False, hide_dummy_entity: bool = True
234+
self,
235+
allow_cache: bool = False,
236+
hide_dummy_entity: bool = True,
237+
tags: Optional[dict[str, str]] = None,
232238
) -> List[Entity]:
233239
all_entities = self._registry.list_entities(
234-
self.project, allow_cache=allow_cache
240+
self.project, allow_cache=allow_cache, tags=tags
235241
)
236242
return [
237243
entity
238244
for entity in all_entities
239245
if entity.name != DUMMY_ENTITY_NAME or not hide_dummy_entity
240246
]
241247

242-
def list_feature_services(self) -> List[FeatureService]:
248+
def list_feature_services(
249+
self, tags: Optional[dict[str, str]] = None
250+
) -> List[FeatureService]:
243251
"""
244252
Retrieves the list of feature services from the registry.
245253
254+
Args:
255+
tags: Filter by tags.
256+
246257
Returns:
247258
A list of feature services.
248259
"""
249-
return self._registry.list_feature_services(self.project)
260+
return self._registry.list_feature_services(self.project, tags=tags)
250261

251262
def list_all_feature_views(
252-
self, allow_cache: bool = False
263+
self, allow_cache: bool = False, tags: Optional[dict[str, str]] = None
253264
) -> List[Union[FeatureView, StreamFeatureView, OnDemandFeatureView]]:
254265
"""
255266
Retrieves the list of feature views from the registry.
@@ -260,14 +271,17 @@ def list_all_feature_views(
260271
Returns:
261272
A list of feature views.
262273
"""
263-
return self._list_all_feature_views(allow_cache)
274+
return self._list_all_feature_views(allow_cache, tags=tags)
264275

265-
def list_feature_views(self, allow_cache: bool = False) -> List[FeatureView]:
276+
def list_feature_views(
277+
self, allow_cache: bool = False, tags: Optional[dict[str, str]] = None
278+
) -> List[FeatureView]:
266279
"""
267280
Retrieves the list of feature views from the registry.
268281
269282
Args:
270283
allow_cache: Whether to allow returning entities from a cached registry.
284+
tags: Filter by tags.
271285
272286
Returns:
273287
A list of feature views.
@@ -276,31 +290,48 @@ def list_feature_views(self, allow_cache: bool = False) -> List[FeatureView]:
276290
"list_feature_views will make breaking changes. Please use list_batch_feature_views instead. "
277291
"list_feature_views will behave like list_all_feature_views in the future."
278292
)
279-
return self._list_feature_views(allow_cache)
293+
return self._list_feature_views(allow_cache=allow_cache, tags=tags)
294+
295+
def list_batch_feature_views(
296+
self, allow_cache: bool = False, tags: Optional[dict[str, str]] = None
297+
) -> List[FeatureView]:
298+
"""
299+
Retrieves the list of feature views from the registry.
300+
301+
Args:
302+
allow_cache: Whether to allow returning entities from a cached registry.
303+
tags: Filter by tags.
304+
305+
Returns:
306+
A list of feature views.
307+
"""
308+
return self._list_batch_feature_views(allow_cache=allow_cache, tags=tags)
280309

281310
def _list_all_feature_views(
282311
self,
283312
allow_cache: bool = False,
313+
tags: Optional[dict[str, str]] = None,
284314
) -> List[Union[FeatureView, StreamFeatureView, OnDemandFeatureView]]:
285315
all_feature_views = (
286-
self._list_feature_views(allow_cache)
287-
+ self._list_stream_feature_views(allow_cache)
288-
+ self.list_on_demand_feature_views(allow_cache)
316+
self._list_feature_views(allow_cache, tags=tags)
317+
+ self._list_stream_feature_views(allow_cache, tags=tags)
318+
+ self.list_on_demand_feature_views(allow_cache, tags=tags)
289319
)
290320
return all_feature_views
291321

292322
def _list_feature_views(
293323
self,
294324
allow_cache: bool = False,
295325
hide_dummy_entity: bool = True,
326+
tags: Optional[dict[str, str]] = None,
296327
) -> List[FeatureView]:
297328
logging.warning(
298329
"_list_feature_views will make breaking changes. Please use _list_batch_feature_views instead. "
299330
"_list_feature_views will behave like _list_all_feature_views in the future."
300331
)
301332
feature_views = []
302333
for fv in self._registry.list_feature_views(
303-
self.project, allow_cache=allow_cache
334+
self.project, allow_cache=allow_cache, tags=tags
304335
):
305336
if (
306337
hide_dummy_entity
@@ -316,10 +347,11 @@ def _list_batch_feature_views(
316347
self,
317348
allow_cache: bool = False,
318349
hide_dummy_entity: bool = True,
350+
tags: Optional[dict[str, str]] = None,
319351
) -> List[FeatureView]:
320352
feature_views = []
321353
for fv in self._registry.list_feature_views(
322-
self.project, allow_cache=allow_cache
354+
self.project, allow_cache=allow_cache, tags=tags
323355
):
324356
if (
325357
hide_dummy_entity
@@ -335,10 +367,11 @@ def _list_stream_feature_views(
335367
self,
336368
allow_cache: bool = False,
337369
hide_dummy_entity: bool = True,
370+
tags: Optional[dict[str, str]] = None,
338371
) -> List[StreamFeatureView]:
339372
stream_feature_views = []
340373
for sfv in self._registry.list_stream_feature_views(
341-
self.project, allow_cache=allow_cache
374+
self.project, allow_cache=allow_cache, tags=tags
342375
):
343376
if hide_dummy_entity and sfv.entities[0] == DUMMY_ENTITY_NAME:
344377
sfv.entities = []
@@ -347,40 +380,49 @@ def _list_stream_feature_views(
347380
return stream_feature_views
348381

349382
def list_on_demand_feature_views(
350-
self, allow_cache: bool = False
383+
self, allow_cache: bool = False, tags: Optional[dict[str, str]] = None
351384
) -> List[OnDemandFeatureView]:
352385
"""
353386
Retrieves the list of on demand feature views from the registry.
354387
388+
Args:
389+
allow_cache: Whether to allow returning entities from a cached registry.
390+
tags: Filter by tags.
391+
355392
Returns:
356393
A list of on demand feature views.
357394
"""
358395
return self._registry.list_on_demand_feature_views(
359-
self.project, allow_cache=allow_cache
396+
self.project, allow_cache=allow_cache, tags=tags
360397
)
361398

362399
def list_stream_feature_views(
363-
self, allow_cache: bool = False
400+
self, allow_cache: bool = False, tags: Optional[dict[str, str]] = None
364401
) -> List[StreamFeatureView]:
365402
"""
366403
Retrieves the list of stream feature views from the registry.
367404
368405
Returns:
369406
A list of stream feature views.
370407
"""
371-
return self._list_stream_feature_views(allow_cache)
408+
return self._list_stream_feature_views(allow_cache, tags=tags)
372409

373-
def list_data_sources(self, allow_cache: bool = False) -> List[DataSource]:
410+
def list_data_sources(
411+
self, allow_cache: bool = False, tags: Optional[dict[str, str]] = None
412+
) -> List[DataSource]:
374413
"""
375414
Retrieves the list of data sources from the registry.
376415
377416
Args:
378417
allow_cache: Whether to allow returning data sources from a cached registry.
418+
tags: Filter by tags.
379419
380420
Returns:
381421
A list of data sources.
382422
"""
383-
return self._registry.list_data_sources(self.project, allow_cache=allow_cache)
423+
return self._registry.list_data_sources(
424+
self.project, allow_cache=allow_cache, tags=tags
425+
)
384426

385427
def get_entity(self, name: str, allow_registry_cache: bool = False) -> Entity:
386428
"""

0 commit comments

Comments
 (0)