Skip to content

Commit bb2151f

Browse files
committed
add tags filtering capability to object 'list'
Signed-off-by: Tommy Hughes <[email protected]>
1 parent 2478831 commit bb2151f

File tree

19 files changed

+553
-151
lines changed

19 files changed

+553
-151
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
@@ -46,6 +46,11 @@
4646
from feast.utils import maybe_local_tz
4747

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

5055

5156
class NoOptionDefaultFormat(click.Command):
@@ -225,14 +230,16 @@ def data_source_describe(ctx: click.Context, name: str):
225230

226231

227232
@data_sources_cmd.command(name="list")
233+
@tagsOption
228234
@click.pass_context
229-
def data_source_list(ctx: click.Context):
235+
def data_source_list(ctx: click.Context, tags: Optional[str]):
230236
"""
231237
List all data sources
232238
"""
233239
store = create_feature_store(ctx)
234240
table = []
235-
for datasource in store.list_data_sources():
241+
tags_filter = utils.tags_str_to_dict(tags)
242+
for datasource in store.list_data_sources(tags=tags_filter):
236243
table.append([datasource.name, datasource.__class__])
237244

238245
from tabulate import tabulate
@@ -271,14 +278,16 @@ def entity_describe(ctx: click.Context, name: str):
271278

272279

273280
@entities_cmd.command(name="list")
281+
@tagsOption
274282
@click.pass_context
275-
def entity_list(ctx: click.Context):
283+
def entity_list(ctx: click.Context, tags: Optional[str]):
276284
"""
277285
List all entities
278286
"""
279287
store = create_feature_store(ctx)
280288
table = []
281-
for entity in store.list_entities():
289+
tags_filter = utils.tags_str_to_dict(tags)
290+
for entity in store.list_entities(tags=tags_filter):
282291
table.append([entity.name, entity.description, entity.value_type])
283292

284293
from tabulate import tabulate
@@ -319,14 +328,16 @@ def feature_service_describe(ctx: click.Context, name: str):
319328

320329

321330
@feature_services_cmd.command(name="list")
331+
@tagsOption
322332
@click.pass_context
323-
def feature_service_list(ctx: click.Context):
333+
def feature_service_list(ctx: click.Context, tags: Optional[str]):
324334
"""
325335
List all feature services
326336
"""
327337
store = create_feature_store(ctx)
328338
feature_services = []
329-
for feature_service in store.list_feature_services():
339+
tags_filter = utils.tags_str_to_dict(tags)
340+
for feature_service in store.list_feature_services(tags=tags_filter):
330341
feature_names = []
331342
for projection in feature_service.feature_view_projections:
332343
feature_names.extend(
@@ -370,16 +381,18 @@ def feature_view_describe(ctx: click.Context, name: str):
370381

371382

372383
@feature_views_cmd.command(name="list")
384+
@tagsOption
373385
@click.pass_context
374-
def feature_view_list(ctx: click.Context):
386+
def feature_view_list(ctx: click.Context, tags: Optional[str]):
375387
"""
376388
List all feature views
377389
"""
378390
store = create_feature_store(ctx)
379391
table = []
392+
tags_filter = utils.tags_str_to_dict(tags)
380393
for feature_view in [
381-
*store.list_feature_views(),
382-
*store.list_on_demand_feature_views(),
394+
*store.list_batch_feature_views(tags=tags_filter),
395+
*store.list_on_demand_feature_views(tags=tags_filter),
383396
]:
384397
entities = set()
385398
if isinstance(feature_view, FeatureView):
@@ -433,14 +446,16 @@ def on_demand_feature_view_describe(ctx: click.Context, name: str):
433446

434447

435448
@on_demand_feature_views_cmd.command(name="list")
449+
@tagsOption
436450
@click.pass_context
437-
def on_demand_feature_view_list(ctx: click.Context):
451+
def on_demand_feature_view_list(ctx: click.Context, tags: Optional[str]):
438452
"""
439453
[Experimental] List all on demand feature views
440454
"""
441455
store = create_feature_store(ctx)
442456
table = []
443-
for on_demand_feature_view in store.list_on_demand_feature_views():
457+
tags_filter = utils.tags_str_to_dict(tags)
458+
for on_demand_feature_view in store.list_on_demand_feature_views(tags=tags_filter):
444459
table.append([on_demand_feature_view.name])
445460

446461
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)