Skip to content

Commit a4d98cf

Browse files
vertex-sdk-botcopybara-github
authored andcommitted
chore: add list_feature_views() in feature views
PiperOrigin-RevId: 711554371
1 parent 67358fa commit a4d98cf

File tree

5 files changed

+81
-59
lines changed

5 files changed

+81
-59
lines changed

tests/unit/vertexai/conftest.py

+11
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
_TEST_FG1_F1,
6464
_TEST_FG1_F2,
6565
_TEST_FG1_FM1,
66+
_TEST_FV_LIST,
6667
_TEST_FV1,
6768
_TEST_FV3,
6869
_TEST_OPTIMIZED_EMBEDDING_FV,
@@ -443,6 +444,16 @@ def get_rag_fv_mock():
443444
yield get_rag_fv_mock
444445

445446

447+
@pytest.fixture
448+
def list_fv_mock():
449+
with patch.object(
450+
feature_online_store_admin_service_client.FeatureOnlineStoreAdminServiceClient,
451+
"list_feature_views",
452+
) as list_fv:
453+
list_fv.return_value = _TEST_FV_LIST
454+
yield list_fv
455+
456+
446457
@pytest.fixture
447458
def create_bq_fv_mock():
448459
with patch.object(

tests/unit/vertexai/test_feature_online_store.py

+25-48
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,15 @@
4242
_TEST_ESF_OPTIMIZED_FOS_LABELS,
4343
_TEST_ESF_OPTIMIZED_FOS_PATH,
4444
_TEST_FOS_LIST,
45+
_TEST_FV_LIST,
4546
_TEST_FV1_BQ_URI,
4647
_TEST_FV1_ENTITY_ID_COLUMNS,
4748
_TEST_FV1_ID,
4849
_TEST_FV1_LABELS,
4950
_TEST_FV1_PATH,
50-
_TEST_FV3_BQ_URI,
51+
_TEST_FV2_ID,
52+
_TEST_FV2_LABELS,
53+
_TEST_FV2_PATH,
5154
_TEST_FV3_ID,
5255
_TEST_FV3_LABELS,
5356
_TEST_FV3_PATH,
@@ -617,65 +620,39 @@ def test_create_rag_fv_bad_uri_raises_error(get_fos_mock):
617620
)
618621

619622

620-
@pytest.mark.parametrize("create_request_timeout", [None, 1.0])
621-
@pytest.mark.parametrize("sync", [True, False])
622-
def test_create_rag_fv(
623-
create_request_timeout,
624-
sync,
623+
def test_list_feature_views(
625624
get_fos_mock,
626-
create_rag_fv_mock,
627-
get_rag_fv_mock,
628-
fos_logger_mock,
625+
list_fv_mock,
629626
):
630627
aiplatform.init(project=_TEST_PROJECT, location=_TEST_LOCATION)
631-
fos = FeatureOnlineStore(_TEST_BIGTABLE_FOS1_ID)
632628

633-
rag_fv = fos.create_feature_view(
634-
_TEST_FV3_ID,
635-
FeatureViewVertexRagSource(uri=_TEST_FV3_BQ_URI),
636-
labels=_TEST_FV3_LABELS,
637-
create_request_timeout=create_request_timeout,
638-
)
629+
fos = FeatureOnlineStore(_TEST_BIGTABLE_FOS1_ID)
630+
feature_views = fos.list_feature_views()
639631

640-
if not sync:
641-
fos.wait()
632+
list_fv_mock.assert_called_once_with(request={"parent": _TEST_BIGTABLE_FOS1_PATH})
633+
assert len(feature_views) == len(_TEST_FV_LIST)
642634

643-
# When creating, the FeatureView object doesn't have the path set.
644-
expected_fv = types.feature_view.FeatureView(
645-
vertex_rag_source=types.feature_view.FeatureView.VertexRagSource(
646-
uri=_TEST_FV3_BQ_URI,
647-
),
648-
labels=_TEST_FV3_LABELS,
635+
fv_eq(
636+
feature_views[0],
637+
name=_TEST_FV1_ID,
638+
resource_name=_TEST_FV1_PATH,
639+
project=_TEST_PROJECT,
640+
location=_TEST_LOCATION,
641+
labels=_TEST_FV1_LABELS,
649642
)
650-
create_rag_fv_mock.assert_called_with(
651-
parent=_TEST_BIGTABLE_FOS1_PATH,
652-
feature_view=expected_fv,
653-
feature_view_id=_TEST_FV3_ID,
654-
metadata=(),
655-
timeout=create_request_timeout,
643+
fv_eq(
644+
feature_views[1],
645+
name=_TEST_FV2_ID,
646+
resource_name=_TEST_FV2_PATH,
647+
project=_TEST_PROJECT,
648+
location=_TEST_LOCATION,
649+
labels=_TEST_FV2_LABELS,
656650
)
657-
658651
fv_eq(
659-
fv_to_check=rag_fv,
652+
feature_views[2],
660653
name=_TEST_FV3_ID,
661654
resource_name=_TEST_FV3_PATH,
662655
project=_TEST_PROJECT,
663656
location=_TEST_LOCATION,
664657
labels=_TEST_FV3_LABELS,
665658
)
666-
667-
fos_logger_mock.assert_has_calls(
668-
[
669-
call("Creating FeatureView"),
670-
call(
671-
f"Create FeatureView backing LRO: {create_rag_fv_mock.return_value.operation.name}"
672-
),
673-
call(
674-
"FeatureView created. Resource name: projects/test-project/locations/us-central1/featureOnlineStores/my_fos1/featureViews/my_fv3"
675-
),
676-
call("To use this FeatureView in another session:"),
677-
call(
678-
"feature_view = aiplatform.FeatureView('projects/test-project/locations/us-central1/featureOnlineStores/my_fos1/featureViews/my_fv3')"
679-
),
680-
]
681-
)

tests/unit/vertexai/test_feature_view.py

-10
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,6 @@ def fv_logger_mock():
8080
yield logger_mock
8181

8282

83-
@pytest.fixture
84-
def list_fv_mock():
85-
with patch.object(
86-
feature_online_store_admin_service_client.FeatureOnlineStoreAdminServiceClient,
87-
"list_feature_views",
88-
) as list_fv:
89-
list_fv.return_value = _TEST_FV_LIST
90-
yield list_fv
91-
92-
9383
@pytest.fixture
9484
def delete_fv_mock():
9585
with patch.object(

vertexai/resources/preview/feature_store/feature_online_store.py

+31
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import enum
1919
from typing import (
2020
Dict,
21+
List,
2122
Optional,
2223
Sequence,
2324
Tuple,
@@ -577,3 +578,33 @@ def create_feature_view(
577578
)
578579

579580
return feature_view_obj
581+
582+
def list_feature_views(
583+
self,
584+
project: Optional[str] = None,
585+
location: Optional[str] = None,
586+
credentials: Optional[auth_credentials.Credentials] = None,
587+
) -> List[FeatureView]:
588+
"""Lists feature views under this feature online store.
589+
590+
Args:
591+
project:
592+
Project to list feature views in. If unset, the project set in
593+
aiplatform.init will be used.
594+
location:
595+
Location to list feature views in. If not set, location set in
596+
aiplatform.init will be used.
597+
credentials:
598+
Custom credentials to use to list feature views. Overrides
599+
credentials set in aiplatform.init.
600+
601+
Returns:
602+
List of feature views under this feature online store.
603+
"""
604+
605+
return FeatureView.list(
606+
feature_online_store_id=self.name,
607+
project=project,
608+
location=location,
609+
credentials=credentials,
610+
)

vertexai/resources/preview/feature_store/feature_view.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ def list(
231231
cls,
232232
feature_online_store_id: str,
233233
filter: Optional[str] = None,
234+
project: Optional[str] = None,
235+
location: Optional[str] = None,
234236
credentials: Optional[auth_credentials.Credentials] = None,
235237
) -> List["FeatureView"]:
236238
"""List all feature view under feature_online_store_id.
@@ -246,6 +248,12 @@ def list(
246248
Parentfeature online store ID.
247249
filter:
248250
Filter to apply on the returned feature online store.
251+
project:
252+
Project to use to get a list of feature views. If unset, the
253+
project set in aiplatform.init will be used.
254+
location:
255+
Location to use to get a list feature views. If not set,
256+
location set in aiplatform.init will be used.
249257
credentials:
250258
Custom credentials to use to get a list of feature views.
251259
Overrides credentials set in aiplatform.init.
@@ -255,7 +263,12 @@ def list(
255263
"""
256264
from .feature_online_store import FeatureOnlineStore
257265

258-
fos = FeatureOnlineStore(name=feature_online_store_id)
266+
fos = FeatureOnlineStore(
267+
name=feature_online_store_id,
268+
project=project,
269+
location=location,
270+
credentials=credentials,
271+
)
259272
return cls._list(
260273
filter=filter, credentials=credentials, parent=fos.resource_name
261274
)

0 commit comments

Comments
 (0)