We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
performance issues of getting online features related to parsing protobuf data
**Is your feature request related to a problem? Please describe.**

The profiler of one application I am working on shows the `from_proto` method of the `FeatureView` class takes up 80% of the execution time. The result of cProfile is shown below.
```
    ncalls  tottime  percall  cumtime  percall filename:lineno(function)
         1    0.003    0.003   78.931   78.931 profiler.py:53(main)
       100    0.018    0.000   78.849    0.788 get_features.py:122(get_xxxx_features)
  1100/400    0.020    0.000   77.077    0.193 usage.py:274(wrapper)
 444200/9800    1.713    0.000   72.206    0.007 __init__.py:1030(wrapper)
       200    0.078    0.000   68.913    0.345 feature_store.py:1527(get_online_features)
       200    0.087    0.000   68.835    0.344 feature_store.py:1590(_get_online_features)
      3500    5.634    0.002   62.442    0.018 feature_view.py:369(from_proto)
       200    0.005    0.000   59.362    0.297 feature_store.py:2149(_get_feature_views_to_use)
       200    0.002    0.000   58.501    0.293 feature_store.py:281(_list_feature_views)
       200    0.001    0.000   58.499    0.292 registry.py:523(list_feature_views)
       200    0.016    0.000   58.495    0.292 proto_registry_utils.py:150(list_feature_views)
```
There are 3 feature views accessed by `get_xxxx_features`, however 100 calls of `get_xxxx_features` lead to 3500 calls of `from_proto`. There are 17 feature views in the feature store of this application and 3 of them are used by `get_xxxx_features`.

Environment: `continuumio/miniconda3:4.11.0` (linux/amd64) base image, `python==3.9.7`, `feast=0.31.1`, `protobuf==4.23.2`

**Describe the solution you'd like**

Instead of caching the protobuf blob of `FeatureView`, cache the `FeatureView` python object in memory.

**Describe alternatives you've considered**

modify the `get_online_features` [method](https://github.com/feast-dev/feast/blob/v0.31.1/sdk/python/feast/feature_store.py#L1528) to
```python
def get_online_features(
    self,
    features: Union[List[str], List[FeatureView], FeatureService],
    entity_rows: List[Dict[str, Any]],
    full_feature_names: bool = False,
):
``` 
so that the application developer has the option to cache the `FeatureView` objects and use them to get features directly (by passing the `get_feature_views_to_use` [step](https://github.com/feast-dev/feast/blob/v0.31.1/sdk/python/feast/feature_store.py#L1606-L1613) )
  

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sdk/python/feast/infra/registry/proto_registry_utils.py`
Content:
```
1 import uuid
2 from typing import List, Optional
3 
4 from feast import usage
5 from feast.data_source import DataSource
6 from feast.entity import Entity
7 from feast.errors import (
8     DataSourceObjectNotFoundException,
9     EntityNotFoundException,
10     FeatureServiceNotFoundException,
11     FeatureViewNotFoundException,
12     SavedDatasetNotFound,
13     ValidationReferenceNotFound,
14 )
15 from feast.feature_service import FeatureService
16 from feast.feature_view import FeatureView
17 from feast.on_demand_feature_view import OnDemandFeatureView
18 from feast.project_metadata import ProjectMetadata
19 from feast.protos.feast.core.Registry_pb2 import ProjectMetadata as ProjectMetadataProto
20 from feast.protos.feast.core.Registry_pb2 import Registry as RegistryProto
21 from feast.request_feature_view import RequestFeatureView
22 from feast.saved_dataset import SavedDataset, ValidationReference
23 from feast.stream_feature_view import StreamFeatureView
24 
25 
26 def init_project_metadata(cached_registry_proto: RegistryProto, project: str):
27     new_project_uuid = f"{uuid.uuid4()}"
28     usage.set_current_project_uuid(new_project_uuid)
29     cached_registry_proto.project_metadata.append(
30         ProjectMetadata(project_name=project, project_uuid=new_project_uuid).to_proto()
31     )
32 
33 
34 def get_project_metadata(
35     registry_proto: Optional[RegistryProto], project: str
36 ) -> Optional[ProjectMetadataProto]:
37     if not registry_proto:
38         return None
39     for pm in registry_proto.project_metadata:
40         if pm.project == project:
41             return pm
42     return None
43 
44 
45 def get_feature_service(
46     registry_proto: RegistryProto, name: str, project: str
47 ) -> FeatureService:
48     for feature_service_proto in registry_proto.feature_services:
49         if (
50             feature_service_proto.spec.project == project
51             and feature_service_proto.spec.name == name
52         ):
53             return FeatureService.from_proto(feature_service_proto)
54     raise FeatureServiceNotFoundException(name, project=project)
55 
56 
57 def get_feature_view(
58     registry_proto: RegistryProto, name: str, project: str
59 ) -> FeatureView:
60     for feature_view_proto in registry_proto.feature_views:
61         if (
62             feature_view_proto.spec.name == name
63             and feature_view_proto.spec.project == project
64         ):
65             return FeatureView.from_proto(feature_view_proto)
66     raise FeatureViewNotFoundException(name, project)
67 
68 
69 def get_stream_feature_view(
70     registry_proto: RegistryProto, name: str, project: str
71 ) -> StreamFeatureView:
72     for feature_view_proto in registry_proto.stream_feature_views:
73         if (
74             feature_view_proto.spec.name == name
75             and feature_view_proto.spec.project == project
76         ):
77             return StreamFeatureView.from_proto(feature_view_proto)
78     raise FeatureViewNotFoundException(name, project)
79 
80 
81 def get_request_feature_view(registry_proto: RegistryProto, name: str, project: str):
82     for feature_view_proto in registry_proto.feature_views:
83         if (
84             feature_view_proto.spec.name == name
85             and feature_view_proto.spec.project == project
86         ):
87             return RequestFeatureView.from_proto(feature_view_proto)
88     raise FeatureViewNotFoundException(name, project)
89 
90 
91 def get_on_demand_feature_view(
92     registry_proto: RegistryProto, name: str, project: str
93 ) -> OnDemandFeatureView:
94     for on_demand_feature_view in registry_proto.on_demand_feature_views:
95         if (
96             on_demand_feature_view.spec.project == project
97             and on_demand_feature_view.spec.name == name
98         ):
99             return OnDemandFeatureView.from_proto(on_demand_feature_view)
100     raise FeatureViewNotFoundException(name, project=project)
101 
102 
103 def get_data_source(
104     registry_proto: RegistryProto, name: str, project: str
105 ) -> DataSource:
106     for data_source in registry_proto.data_sources:
107         if data_source.project == project and data_source.name == name:
108             return DataSource.from_proto(data_source)
109     raise DataSourceObjectNotFoundException(name, project=project)
110 
111 
112 def get_entity(registry_proto: RegistryProto, name: str, project: str) -> Entity:
113     for entity_proto in registry_proto.entities:
114         if entity_proto.spec.name == name and entity_proto.spec.project == project:
115             return Entity.from_proto(entity_proto)
116     raise EntityNotFoundException(name, project=project)
117 
118 
119 def get_saved_dataset(
120     registry_proto: RegistryProto, name: str, project: str
121 ) -> SavedDataset:
122     for saved_dataset in registry_proto.saved_datasets:
123         if saved_dataset.spec.name == name and saved_dataset.spec.project == project:
124             return SavedDataset.from_proto(saved_dataset)
125     raise SavedDatasetNotFound(name, project=project)
126 
127 
128 def get_validation_reference(
129     registry_proto: RegistryProto, name: str, project: str
130 ) -> ValidationReference:
131     for validation_reference in registry_proto.validation_references:
132         if (
133             validation_reference.name == name
134             and validation_reference.project == project
135         ):
136             return ValidationReference.from_proto(validation_reference)
137     raise ValidationReferenceNotFound(name, project=project)
138 
139 
140 def list_feature_services(
141     registry_proto: RegistryProto, project: str, allow_cache: bool = False
142 ) -> List[FeatureService]:
143     feature_services = []
144     for feature_service_proto in registry_proto.feature_services:
145         if feature_service_proto.spec.project == project:
146             feature_services.append(FeatureService.from_proto(feature_service_proto))
147     return feature_services
148 
149 
150 def list_feature_views(
151     registry_proto: RegistryProto, project: str
152 ) -> List[FeatureView]:
153     feature_views: List[FeatureView] = []
154     for feature_view_proto in registry_proto.feature_views:
155         if feature_view_proto.spec.project == project:
156             feature_views.append(FeatureView.from_proto(feature_view_proto))
157     return feature_views
158 
159 
160 def list_request_feature_views(
161     registry_proto: RegistryProto, project: str
162 ) -> List[RequestFeatureView]:
163     feature_views: List[RequestFeatureView] = []
164     for request_feature_view_proto in registry_proto.request_feature_views:
165         if request_feature_view_proto.spec.project == project:
166             feature_views.append(
167                 RequestFeatureView.from_proto(request_feature_view_proto)
168             )
169     return feature_views
170 
171 
172 def list_stream_feature_views(
173     registry_proto: RegistryProto, project: str
174 ) -> List[StreamFeatureView]:
175     stream_feature_views = []
176     for stream_feature_view in registry_proto.stream_feature_views:
177         if stream_feature_view.spec.project == project:
178             stream_feature_views.append(
179                 StreamFeatureView.from_proto(stream_feature_view)
180             )
181     return stream_feature_views
182 
183 
184 def list_on_demand_feature_views(
185     registry_proto: RegistryProto, project: str
186 ) -> List[OnDemandFeatureView]:
187     on_demand_feature_views = []
188     for on_demand_feature_view in registry_proto.on_demand_feature_views:
189         if on_demand_feature_view.spec.project == project:
190             on_demand_feature_views.append(
191                 OnDemandFeatureView.from_proto(on_demand_feature_view)
192             )
193     return on_demand_feature_views
194 
195 
196 def list_entities(registry_proto: RegistryProto, project: str) -> List[Entity]:
197     entities = []
198     for entity_proto in registry_proto.entities:
199         if entity_proto.spec.project == project:
200             entities.append(Entity.from_proto(entity_proto))
201     return entities
202 
203 
204 def list_data_sources(registry_proto: RegistryProto, project: str) -> List[DataSource]:
205     data_sources = []
206     for data_source_proto in registry_proto.data_sources:
207         if data_source_proto.project == project:
208             data_sources.append(DataSource.from_proto(data_source_proto))
209     return data_sources
210 
211 
212 def list_saved_datasets(
213     registry_proto: RegistryProto, project: str
214 ) -> List[SavedDataset]:
215     saved_datasets = []
216     for saved_dataset in registry_proto.saved_datasets:
217         if saved_dataset.project == project:
218             saved_datasets.append(SavedDataset.from_proto(saved_dataset))
219     return saved_datasets
220 
221 
222 def list_validation_references(
223     registry_proto: RegistryProto, project: str
224 ) -> List[ValidationReference]:
225     validation_references = []
226     for validation_reference in registry_proto.validation_references:
227         if validation_reference.project == project:
228             validation_references.append(
229                 ValidationReference.from_proto(validation_reference)
230             )
231     return validation_references
232 
233 
234 def list_project_metadata(
235     registry_proto: RegistryProto, project: str
236 ) -> List[ProjectMetadata]:
237     return [
238         ProjectMetadata.from_proto(project_metadata)
239         for project_metadata in registry_proto.project_metadata
240         if project_metadata.project == project
241     ]
242
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sdk/python/feast/infra/registry/proto_registry_utils.py b/sdk/python/feast/infra/registry/proto_registry_utils.py
--- a/sdk/python/feast/infra/registry/proto_registry_utils.py
+++ b/sdk/python/feast/infra/registry/proto_registry_utils.py
@@ -1,4 +1,5 @@
 import uuid
+from functools import wraps
 from typing import List, Optional
 
 from feast import usage
@@ -23,6 +24,26 @@
 from feast.stream_feature_view import StreamFeatureView
 
 
+def registry_proto_cache(func):
+    cache_key = None
+    cache_value = None
+
+    @wraps(func)
+    def wrapper(registry_proto: RegistryProto, project: str):
+        nonlocal cache_key, cache_value
+
+        key = tuple([id(registry_proto), registry_proto.version_id, project])
+
+        if key == cache_key:
+            return cache_value
+        else:
+            cache_value = func(registry_proto, project)
+            cache_key = key
+            return cache_value
+
+    return wrapper
+
+
 def init_project_metadata(cached_registry_proto: RegistryProto, project: str):
     new_project_uuid = f"{uuid.uuid4()}"
     usage.set_current_project_uuid(new_project_uuid)
@@ -137,8 +158,9 @@
     raise ValidationReferenceNotFound(name, project=project)
 
 
+@registry_proto_cache
 def list_feature_services(
-    registry_proto: RegistryProto, project: str, allow_cache: bool = False
+    registry_proto: RegistryProto, project: str
 ) -> List[FeatureService]:
     feature_services = []
     for feature_service_proto in registry_proto.feature_services:
@@ -147,6 +169,7 @@
     return feature_services
 
 
+@registry_proto_cache
 def list_feature_views(
     registry_proto: RegistryProto, project: str
 ) -> List[FeatureView]:
@@ -157,6 +180,7 @@
     return feature_views
 
 
+@registry_proto_cache
 def list_request_feature_views(
     registry_proto: RegistryProto, project: str
 ) -> List[RequestFeatureView]:
@@ -169,6 +193,7 @@
     return feature_views
 
 
+@registry_proto_cache
 def list_stream_feature_views(
     registry_proto: RegistryProto, project: str
 ) -> List[StreamFeatureView]:
@@ -181,6 +206,7 @@
     return stream_feature_views
 
 
+@registry_proto_cache
 def list_on_demand_feature_views(
     registry_proto: RegistryProto, project: str
 ) -> List[OnDemandFeatureView]:
@@ -193,6 +219,7 @@
     return on_demand_feature_views
 
 
+@registry_proto_cache
 def list_entities(registry_proto: RegistryProto, project: str) -> List[Entity]:
     entities = []
     for entity_proto in registry_proto.entities:
@@ -201,6 +228,7 @@
     return entities
 
 
+@registry_proto_cache
 def list_data_sources(registry_proto: RegistryProto, project: str) -> List[DataSource]:
     data_sources = []
     for data_source_proto in registry_proto.data_sources:
@@ -209,6 +237,7 @@
     return data_sources
 
 
+@registry_proto_cache
 def list_saved_datasets(
     registry_proto: RegistryProto, project: str
 ) -> List[SavedDataset]:
@@ -219,6 +248,7 @@
     return saved_datasets
 
 
+@registry_proto_cache
 def list_validation_references(
     registry_proto: RegistryProto, project: str
 ) -> List[ValidationReference]:
@@ -231,6 +261,7 @@
     return validation_references
 
 
+@registry_proto_cache
 def list_project_metadata(
     registry_proto: RegistryProto, project: str
 ) -> List[ProjectMetadata]:

{"golden_diff": "diff --git a/sdk/python/feast/infra/registry/proto_registry_utils.py b/sdk/python/feast/infra/registry/proto_registry_utils.py\n--- a/sdk/python/feast/infra/registry/proto_registry_utils.py\n+++ b/sdk/python/feast/infra/registry/proto_registry_utils.py\n@@ -1,4 +1,5 @@\n import uuid\n+from functools import wraps\n from typing import List, Optional\n \n from feast import usage\n@@ -23,6 +24,26 @@\n from feast.stream_feature_view import StreamFeatureView\n \n \n+def registry_proto_cache(func):\n+    cache_key = None\n+    cache_value = None\n+\n+    @wraps(func)\n+    def wrapper(registry_proto: RegistryProto, project: str):\n+        nonlocal cache_key, cache_value\n+\n+        key = tuple([id(registry_proto), registry_proto.version_id, project])\n+\n+        if key == cache_key:\n+            return cache_value\n+        else:\n+            cache_value = func(registry_proto, project)\n+            cache_key = key\n+            return cache_value\n+\n+    return wrapper\n+\n+\n def init_project_metadata(cached_registry_proto: RegistryProto, project: str):\n     new_project_uuid = f\"{uuid.uuid4()}\"\n     usage.set_current_project_uuid(new_project_uuid)\n@@ -137,8 +158,9 @@\n     raise ValidationReferenceNotFound(name, project=project)\n \n \n+@registry_proto_cache\n def list_feature_services(\n-    registry_proto: RegistryProto, project: str, allow_cache: bool = False\n+    registry_proto: RegistryProto, project: str\n ) -> List[FeatureService]:\n     feature_services = []\n     for feature_service_proto in registry_proto.feature_services:\n@@ -147,6 +169,7 @@\n     return feature_services\n \n \n+@registry_proto_cache\n def list_feature_views(\n     registry_proto: RegistryProto, project: str\n ) -> List[FeatureView]:\n@@ -157,6 +180,7 @@\n     return feature_views\n \n \n+@registry_proto_cache\n def list_request_feature_views(\n     registry_proto: RegistryProto, project: str\n ) -> List[RequestFeatureView]:\n@@ -169,6 +193,7 @@\n     return feature_views\n \n \n+@registry_proto_cache\n def list_stream_feature_views(\n     registry_proto: RegistryProto, project: str\n ) -> List[StreamFeatureView]:\n@@ -181,6 +206,7 @@\n     return stream_feature_views\n \n \n+@registry_proto_cache\n def list_on_demand_feature_views(\n     registry_proto: RegistryProto, project: str\n ) -> List[OnDemandFeatureView]:\n@@ -193,6 +219,7 @@\n     return on_demand_feature_views\n \n \n+@registry_proto_cache\n def list_entities(registry_proto: RegistryProto, project: str) -> List[Entity]:\n     entities = []\n     for entity_proto in registry_proto.entities:\n@@ -201,6 +228,7 @@\n     return entities\n \n \n+@registry_proto_cache\n def list_data_sources(registry_proto: RegistryProto, project: str) -> List[DataSource]:\n     data_sources = []\n     for data_source_proto in registry_proto.data_sources:\n@@ -209,6 +237,7 @@\n     return data_sources\n \n \n+@registry_proto_cache\n def list_saved_datasets(\n     registry_proto: RegistryProto, project: str\n ) -> List[SavedDataset]:\n@@ -219,6 +248,7 @@\n     return saved_datasets\n \n \n+@registry_proto_cache\n def list_validation_references(\n     registry_proto: RegistryProto, project: str\n ) -> List[ValidationReference]:\n@@ -231,6 +261,7 @@\n     return validation_references\n \n \n+@registry_proto_cache\n def list_project_metadata(\n     registry_proto: RegistryProto, project: str\n ) -> List[ProjectMetadata]:\n", "issue": "performance issues of getting online features related to parsing protobuf data\n**Is your feature request related to a problem? Please describe.**\r\n\r\nThe profiler of one application I am working on shows the `from_proto` method of the `FeatureView` class takes up 80% of the execution time. The result of cProfile is shown below.\r\n```\r\n    ncalls  tottime  percall  cumtime  percall filename:lineno(function)\r\n         1    0.003    0.003   78.931   78.931 profiler.py:53(main)\r\n       100    0.018    0.000   78.849    0.788 get_features.py:122(get_xxxx_features)\r\n  1100/400    0.020    0.000   77.077    0.193 usage.py:274(wrapper)\r\n 444200/9800    1.713    0.000   72.206    0.007 __init__.py:1030(wrapper)\r\n       200    0.078    0.000   68.913    0.345 feature_store.py:1527(get_online_features)\r\n       200    0.087    0.000   68.835    0.344 feature_store.py:1590(_get_online_features)\r\n      3500    5.634    0.002   62.442    0.018 feature_view.py:369(from_proto)\r\n       200    0.005    0.000   59.362    0.297 feature_store.py:2149(_get_feature_views_to_use)\r\n       200    0.002    0.000   58.501    0.293 feature_store.py:281(_list_feature_views)\r\n       200    0.001    0.000   58.499    0.292 registry.py:523(list_feature_views)\r\n       200    0.016    0.000   58.495    0.292 proto_registry_utils.py:150(list_feature_views)\r\n```\r\nThere are 3 feature views accessed by `get_xxxx_features`, however 100 calls of `get_xxxx_features` lead to 3500 calls of `from_proto`. There are 17 feature views in the feature store of this application and 3 of them are used by `get_xxxx_features`.\r\n\r\nEnvironment: `continuumio/miniconda3:4.11.0` (linux/amd64) base image, `python==3.9.7`, `feast=0.31.1`, `protobuf==4.23.2`\r\n\r\n**Describe the solution you'd like**\r\n\r\nInstead of caching the protobuf blob of `FeatureView`, cache the `FeatureView` python object in memory.\r\n\r\n**Describe alternatives you've considered**\r\n\r\nmodify the `get_online_features` [method](https://github.com/feast-dev/feast/blob/v0.31.1/sdk/python/feast/feature_store.py#L1528) to\r\n```python\r\ndef get_online_features(\r\n    self,\r\n    features: Union[List[str], List[FeatureView], FeatureService],\r\n    entity_rows: List[Dict[str, Any]],\r\n    full_feature_names: bool = False,\r\n):\r\n``` \r\nso that the application developer has the option to cache the `FeatureView` objects and use them to get features directly (by passing the `get_feature_views_to_use` [step](https://github.com/feast-dev/feast/blob/v0.31.1/sdk/python/feast/feature_store.py#L1606-L1613) )\r\n  \n", "before_files": [{"content": "import uuid\nfrom typing import List, Optional\n\nfrom feast import usage\nfrom feast.data_source import DataSource\nfrom feast.entity import Entity\nfrom feast.errors import (\n    DataSourceObjectNotFoundException,\n    EntityNotFoundException,\n    FeatureServiceNotFoundException,\n    FeatureViewNotFoundException,\n    SavedDatasetNotFound,\n    ValidationReferenceNotFound,\n)\nfrom feast.feature_service import FeatureService\nfrom feast.feature_view import FeatureView\nfrom feast.on_demand_feature_view import OnDemandFeatureView\nfrom feast.project_metadata import ProjectMetadata\nfrom feast.protos.feast.core.Registry_pb2 import ProjectMetadata as ProjectMetadataProto\nfrom feast.protos.feast.core.Registry_pb2 import Registry as RegistryProto\nfrom feast.request_feature_view import RequestFeatureView\nfrom feast.saved_dataset import SavedDataset, ValidationReference\nfrom feast.stream_feature_view import StreamFeatureView\n\n\ndef init_project_metadata(cached_registry_proto: RegistryProto, project: str):\n    new_project_uuid = f\"{uuid.uuid4()}\"\n    usage.set_current_project_uuid(new_project_uuid)\n    cached_registry_proto.project_metadata.append(\n        ProjectMetadata(project_name=project, project_uuid=new_project_uuid).to_proto()\n    )\n\n\ndef get_project_metadata(\n    registry_proto: Optional[RegistryProto], project: str\n) -> Optional[ProjectMetadataProto]:\n    if not registry_proto:\n        return None\n    for pm in registry_proto.project_metadata:\n        if pm.project == project:\n            return pm\n    return None\n\n\ndef get_feature_service(\n    registry_proto: RegistryProto, name: str, project: str\n) -> FeatureService:\n    for feature_service_proto in registry_proto.feature_services:\n        if (\n            feature_service_proto.spec.project == project\n            and feature_service_proto.spec.name == name\n        ):\n            return FeatureService.from_proto(feature_service_proto)\n    raise FeatureServiceNotFoundException(name, project=project)\n\n\ndef get_feature_view(\n    registry_proto: RegistryProto, name: str, project: str\n) -> FeatureView:\n    for feature_view_proto in registry_proto.feature_views:\n        if (\n            feature_view_proto.spec.name == name\n            and feature_view_proto.spec.project == project\n        ):\n            return FeatureView.from_proto(feature_view_proto)\n    raise FeatureViewNotFoundException(name, project)\n\n\ndef get_stream_feature_view(\n    registry_proto: RegistryProto, name: str, project: str\n) -> StreamFeatureView:\n    for feature_view_proto in registry_proto.stream_feature_views:\n        if (\n            feature_view_proto.spec.name == name\n            and feature_view_proto.spec.project == project\n        ):\n            return StreamFeatureView.from_proto(feature_view_proto)\n    raise FeatureViewNotFoundException(name, project)\n\n\ndef get_request_feature_view(registry_proto: RegistryProto, name: str, project: str):\n    for feature_view_proto in registry_proto.feature_views:\n        if (\n            feature_view_proto.spec.name == name\n            and feature_view_proto.spec.project == project\n        ):\n            return RequestFeatureView.from_proto(feature_view_proto)\n    raise FeatureViewNotFoundException(name, project)\n\n\ndef get_on_demand_feature_view(\n    registry_proto: RegistryProto, name: str, project: str\n) -> OnDemandFeatureView:\n    for on_demand_feature_view in registry_proto.on_demand_feature_views:\n        if (\n            on_demand_feature_view.spec.project == project\n            and on_demand_feature_view.spec.name == name\n        ):\n            return OnDemandFeatureView.from_proto(on_demand_feature_view)\n    raise FeatureViewNotFoundException(name, project=project)\n\n\ndef get_data_source(\n    registry_proto: RegistryProto, name: str, project: str\n) -> DataSource:\n    for data_source in registry_proto.data_sources:\n        if data_source.project == project and data_source.name == name:\n            return DataSource.from_proto(data_source)\n    raise DataSourceObjectNotFoundException(name, project=project)\n\n\ndef get_entity(registry_proto: RegistryProto, name: str, project: str) -> Entity:\n    for entity_proto in registry_proto.entities:\n        if entity_proto.spec.name == name and entity_proto.spec.project == project:\n            return Entity.from_proto(entity_proto)\n    raise EntityNotFoundException(name, project=project)\n\n\ndef get_saved_dataset(\n    registry_proto: RegistryProto, name: str, project: str\n) -> SavedDataset:\n    for saved_dataset in registry_proto.saved_datasets:\n        if saved_dataset.spec.name == name and saved_dataset.spec.project == project:\n            return SavedDataset.from_proto(saved_dataset)\n    raise SavedDatasetNotFound(name, project=project)\n\n\ndef get_validation_reference(\n    registry_proto: RegistryProto, name: str, project: str\n) -> ValidationReference:\n    for validation_reference in registry_proto.validation_references:\n        if (\n            validation_reference.name == name\n            and validation_reference.project == project\n        ):\n            return ValidationReference.from_proto(validation_reference)\n    raise ValidationReferenceNotFound(name, project=project)\n\n\ndef list_feature_services(\n    registry_proto: RegistryProto, project: str, allow_cache: bool = False\n) -> List[FeatureService]:\n    feature_services = []\n    for feature_service_proto in registry_proto.feature_services:\n        if feature_service_proto.spec.project == project:\n            feature_services.append(FeatureService.from_proto(feature_service_proto))\n    return feature_services\n\n\ndef list_feature_views(\n    registry_proto: RegistryProto, project: str\n) -> List[FeatureView]:\n    feature_views: List[FeatureView] = []\n    for feature_view_proto in registry_proto.feature_views:\n        if feature_view_proto.spec.project == project:\n            feature_views.append(FeatureView.from_proto(feature_view_proto))\n    return feature_views\n\n\ndef list_request_feature_views(\n    registry_proto: RegistryProto, project: str\n) -> List[RequestFeatureView]:\n    feature_views: List[RequestFeatureView] = []\n    for request_feature_view_proto in registry_proto.request_feature_views:\n        if request_feature_view_proto.spec.project == project:\n            feature_views.append(\n                RequestFeatureView.from_proto(request_feature_view_proto)\n            )\n    return feature_views\n\n\ndef list_stream_feature_views(\n    registry_proto: RegistryProto, project: str\n) -> List[StreamFeatureView]:\n    stream_feature_views = []\n    for stream_feature_view in registry_proto.stream_feature_views:\n        if stream_feature_view.spec.project == project:\n            stream_feature_views.append(\n                StreamFeatureView.from_proto(stream_feature_view)\n            )\n    return stream_feature_views\n\n\ndef list_on_demand_feature_views(\n    registry_proto: RegistryProto, project: str\n) -> List[OnDemandFeatureView]:\n    on_demand_feature_views = []\n    for on_demand_feature_view in registry_proto.on_demand_feature_views:\n        if on_demand_feature_view.spec.project == project:\n            on_demand_feature_views.append(\n                OnDemandFeatureView.from_proto(on_demand_feature_view)\n            )\n    return on_demand_feature_views\n\n\ndef list_entities(registry_proto: RegistryProto, project: str) -> List[Entity]:\n    entities = []\n    for entity_proto in registry_proto.entities:\n        if entity_proto.spec.project == project:\n            entities.append(Entity.from_proto(entity_proto))\n    return entities\n\n\ndef list_data_sources(registry_proto: RegistryProto, project: str) -> List[DataSource]:\n    data_sources = []\n    for data_source_proto in registry_proto.data_sources:\n        if data_source_proto.project == project:\n            data_sources.append(DataSource.from_proto(data_source_proto))\n    return data_sources\n\n\ndef list_saved_datasets(\n    registry_proto: RegistryProto, project: str\n) -> List[SavedDataset]:\n    saved_datasets = []\n    for saved_dataset in registry_proto.saved_datasets:\n        if saved_dataset.project == project:\n            saved_datasets.append(SavedDataset.from_proto(saved_dataset))\n    return saved_datasets\n\n\ndef list_validation_references(\n    registry_proto: RegistryProto, project: str\n) -> List[ValidationReference]:\n    validation_references = []\n    for validation_reference in registry_proto.validation_references:\n        if validation_reference.project == project:\n            validation_references.append(\n                ValidationReference.from_proto(validation_reference)\n            )\n    return validation_references\n\n\ndef list_project_metadata(\n    registry_proto: RegistryProto, project: str\n) -> List[ProjectMetadata]:\n    return [\n        ProjectMetadata.from_proto(project_metadata)\n        for project_metadata in registry_proto.project_metadata\n        if project_metadata.project == project\n    ]\n", "path": "sdk/python/feast/infra/registry/proto_registry_utils.py"}], "after_files": [{"content": "import uuid\nfrom functools import wraps\nfrom typing import List, Optional\n\nfrom feast import usage\nfrom feast.data_source import DataSource\nfrom feast.entity import Entity\nfrom feast.errors import (\n    DataSourceObjectNotFoundException,\n    EntityNotFoundException,\n    FeatureServiceNotFoundException,\n    FeatureViewNotFoundException,\n    SavedDatasetNotFound,\n    ValidationReferenceNotFound,\n)\nfrom feast.feature_service import FeatureService\nfrom feast.feature_view import FeatureView\nfrom feast.on_demand_feature_view import OnDemandFeatureView\nfrom feast.project_metadata import ProjectMetadata\nfrom feast.protos.feast.core.Registry_pb2 import ProjectMetadata as ProjectMetadataProto\nfrom feast.protos.feast.core.Registry_pb2 import Registry as RegistryProto\nfrom feast.request_feature_view import RequestFeatureView\nfrom feast.saved_dataset import SavedDataset, ValidationReference\nfrom feast.stream_feature_view import StreamFeatureView\n\n\ndef registry_proto_cache(func):\n    cache_key = None\n    cache_value = None\n\n    @wraps(func)\n    def wrapper(registry_proto: RegistryProto, project: str):\n        nonlocal cache_key, cache_value\n\n        key = tuple([id(registry_proto), registry_proto.version_id, project])\n\n        if key == cache_key:\n            return cache_value\n        else:\n            cache_value = func(registry_proto, project)\n            cache_key = key\n            return cache_value\n\n    return wrapper\n\n\ndef init_project_metadata(cached_registry_proto: RegistryProto, project: str):\n    new_project_uuid = f\"{uuid.uuid4()}\"\n    usage.set_current_project_uuid(new_project_uuid)\n    cached_registry_proto.project_metadata.append(\n        ProjectMetadata(project_name=project, project_uuid=new_project_uuid).to_proto()\n    )\n\n\ndef get_project_metadata(\n    registry_proto: Optional[RegistryProto], project: str\n) -> Optional[ProjectMetadataProto]:\n    if not registry_proto:\n        return None\n    for pm in registry_proto.project_metadata:\n        if pm.project == project:\n            return pm\n    return None\n\n\ndef get_feature_service(\n    registry_proto: RegistryProto, name: str, project: str\n) -> FeatureService:\n    for feature_service_proto in registry_proto.feature_services:\n        if (\n            feature_service_proto.spec.project == project\n            and feature_service_proto.spec.name == name\n        ):\n            return FeatureService.from_proto(feature_service_proto)\n    raise FeatureServiceNotFoundException(name, project=project)\n\n\ndef get_feature_view(\n    registry_proto: RegistryProto, name: str, project: str\n) -> FeatureView:\n    for feature_view_proto in registry_proto.feature_views:\n        if (\n            feature_view_proto.spec.name == name\n            and feature_view_proto.spec.project == project\n        ):\n            return FeatureView.from_proto(feature_view_proto)\n    raise FeatureViewNotFoundException(name, project)\n\n\ndef get_stream_feature_view(\n    registry_proto: RegistryProto, name: str, project: str\n) -> StreamFeatureView:\n    for feature_view_proto in registry_proto.stream_feature_views:\n        if (\n            feature_view_proto.spec.name == name\n            and feature_view_proto.spec.project == project\n        ):\n            return StreamFeatureView.from_proto(feature_view_proto)\n    raise FeatureViewNotFoundException(name, project)\n\n\ndef get_request_feature_view(registry_proto: RegistryProto, name: str, project: str):\n    for feature_view_proto in registry_proto.feature_views:\n        if (\n            feature_view_proto.spec.name == name\n            and feature_view_proto.spec.project == project\n        ):\n            return RequestFeatureView.from_proto(feature_view_proto)\n    raise FeatureViewNotFoundException(name, project)\n\n\ndef get_on_demand_feature_view(\n    registry_proto: RegistryProto, name: str, project: str\n) -> OnDemandFeatureView:\n    for on_demand_feature_view in registry_proto.on_demand_feature_views:\n        if (\n            on_demand_feature_view.spec.project == project\n            and on_demand_feature_view.spec.name == name\n        ):\n            return OnDemandFeatureView.from_proto(on_demand_feature_view)\n    raise FeatureViewNotFoundException(name, project=project)\n\n\ndef get_data_source(\n    registry_proto: RegistryProto, name: str, project: str\n) -> DataSource:\n    for data_source in registry_proto.data_sources:\n        if data_source.project == project and data_source.name == name:\n            return DataSource.from_proto(data_source)\n    raise DataSourceObjectNotFoundException(name, project=project)\n\n\ndef get_entity(registry_proto: RegistryProto, name: str, project: str) -> Entity:\n    for entity_proto in registry_proto.entities:\n        if entity_proto.spec.name == name and entity_proto.spec.project == project:\n            return Entity.from_proto(entity_proto)\n    raise EntityNotFoundException(name, project=project)\n\n\ndef get_saved_dataset(\n    registry_proto: RegistryProto, name: str, project: str\n) -> SavedDataset:\n    for saved_dataset in registry_proto.saved_datasets:\n        if saved_dataset.spec.name == name and saved_dataset.spec.project == project:\n            return SavedDataset.from_proto(saved_dataset)\n    raise SavedDatasetNotFound(name, project=project)\n\n\ndef get_validation_reference(\n    registry_proto: RegistryProto, name: str, project: str\n) -> ValidationReference:\n    for validation_reference in registry_proto.validation_references:\n        if (\n            validation_reference.name == name\n            and validation_reference.project == project\n        ):\n            return ValidationReference.from_proto(validation_reference)\n    raise ValidationReferenceNotFound(name, project=project)\n\n\n@registry_proto_cache\ndef list_feature_services(\n    registry_proto: RegistryProto, project: str\n) -> List[FeatureService]:\n    feature_services = []\n    for feature_service_proto in registry_proto.feature_services:\n        if feature_service_proto.spec.project == project:\n            feature_services.append(FeatureService.from_proto(feature_service_proto))\n    return feature_services\n\n\n@registry_proto_cache\ndef list_feature_views(\n    registry_proto: RegistryProto, project: str\n) -> List[FeatureView]:\n    feature_views: List[FeatureView] = []\n    for feature_view_proto in registry_proto.feature_views:\n        if feature_view_proto.spec.project == project:\n            feature_views.append(FeatureView.from_proto(feature_view_proto))\n    return feature_views\n\n\n@registry_proto_cache\ndef list_request_feature_views(\n    registry_proto: RegistryProto, project: str\n) -> List[RequestFeatureView]:\n    feature_views: List[RequestFeatureView] = []\n    for request_feature_view_proto in registry_proto.request_feature_views:\n        if request_feature_view_proto.spec.project == project:\n            feature_views.append(\n                RequestFeatureView.from_proto(request_feature_view_proto)\n            )\n    return feature_views\n\n\n@registry_proto_cache\ndef list_stream_feature_views(\n    registry_proto: RegistryProto, project: str\n) -> List[StreamFeatureView]:\n    stream_feature_views = []\n    for stream_feature_view in registry_proto.stream_feature_views:\n        if stream_feature_view.spec.project == project:\n            stream_feature_views.append(\n                StreamFeatureView.from_proto(stream_feature_view)\n            )\n    return stream_feature_views\n\n\n@registry_proto_cache\ndef list_on_demand_feature_views(\n    registry_proto: RegistryProto, project: str\n) -> List[OnDemandFeatureView]:\n    on_demand_feature_views = []\n    for on_demand_feature_view in registry_proto.on_demand_feature_views:\n        if on_demand_feature_view.spec.project == project:\n            on_demand_feature_views.append(\n                OnDemandFeatureView.from_proto(on_demand_feature_view)\n            )\n    return on_demand_feature_views\n\n\n@registry_proto_cache\ndef list_entities(registry_proto: RegistryProto, project: str) -> List[Entity]:\n    entities = []\n    for entity_proto in registry_proto.entities:\n        if entity_proto.spec.project == project:\n            entities.append(Entity.from_proto(entity_proto))\n    return entities\n\n\n@registry_proto_cache\ndef list_data_sources(registry_proto: RegistryProto, project: str) -> List[DataSource]:\n    data_sources = []\n    for data_source_proto in registry_proto.data_sources:\n        if data_source_proto.project == project:\n            data_sources.append(DataSource.from_proto(data_source_proto))\n    return data_sources\n\n\n@registry_proto_cache\ndef list_saved_datasets(\n    registry_proto: RegistryProto, project: str\n) -> List[SavedDataset]:\n    saved_datasets = []\n    for saved_dataset in registry_proto.saved_datasets:\n        if saved_dataset.project == project:\n            saved_datasets.append(SavedDataset.from_proto(saved_dataset))\n    return saved_datasets\n\n\n@registry_proto_cache\ndef list_validation_references(\n    registry_proto: RegistryProto, project: str\n) -> List[ValidationReference]:\n    validation_references = []\n    for validation_reference in registry_proto.validation_references:\n        if validation_reference.project == project:\n            validation_references.append(\n                ValidationReference.from_proto(validation_reference)\n            )\n    return validation_references\n\n\n@registry_proto_cache\ndef list_project_metadata(\n    registry_proto: RegistryProto, project: str\n) -> List[ProjectMetadata]:\n    return [\n        ProjectMetadata.from_proto(project_metadata)\n        for project_metadata in registry_proto.project_metadata\n        if project_metadata.project == project\n    ]\n", "path": "sdk/python/feast/infra/registry/proto_registry_utils.py"}]}