prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Incorrect projects-list.json generated by feast ui when using Postgres as a data source.
  ## Expected Behavior 
  Correct generation of the projects-list.json when running feast ui. 
  ## Current Behavior
  The generated projects-list.json does not contain a name in the dataSources field, causing the parser to fail.
  ## Steps to reproduce
  Setup feast with PostgreSQL as a data source.
  ### Specifications
  
  - Version:
  - Platform:
  - Subsystem:
  
  ## Possible Solution
  Adding name=self.name to to_proto() in postgres_source.py. And in general making the postgres_source.py file more similar to e.g., file_source.py.
  
  --- 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/offline_stores/contrib/postgres_offline_store/postgres_source.py`
  Content:
  ```
  1 import json
  2 from typing import Callable, Dict, Iterable, Optional, Tuple
  3 
  4 from feast.data_source import DataSource
  5 from feast.infra.utils.postgres.connection_utils import _get_conn
  6 from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto
  7 from feast.repo_config import RepoConfig
  8 from feast.type_map import pg_type_code_to_pg_type, pg_type_to_feast_value_type
  9 from feast.value_type import ValueType
  10 
  11 
  12 class PostgreSQLSource(DataSource):
  13     def __init__(
  14         self,
  15         name: str,
  16         query: str,
  17         timestamp_field: Optional[str] = "",
  18         created_timestamp_column: Optional[str] = "",
  19         field_mapping: Optional[Dict[str, str]] = None,
  20         date_partition_column: Optional[str] = "",
  21     ):
  22         self._postgres_options = PostgreSQLOptions(name=name, query=query)
  23 
  24         super().__init__(
  25             name=name,
  26             timestamp_field=timestamp_field,
  27             created_timestamp_column=created_timestamp_column,
  28             field_mapping=field_mapping,
  29             date_partition_column=date_partition_column,
  30         )
  31 
  32     def __hash__(self):
  33         return super().__hash__()
  34 
  35     def __eq__(self, other):
  36         if not isinstance(other, PostgreSQLSource):
  37             raise TypeError(
  38                 "Comparisons should only involve PostgreSQLSource class objects."
  39             )
  40 
  41         return (
  42             self._postgres_options._query == other._postgres_options._query
  43             and self.timestamp_field == other.timestamp_field
  44             and self.created_timestamp_column == other.created_timestamp_column
  45             and self.field_mapping == other.field_mapping
  46         )
  47 
  48     @staticmethod
  49     def from_proto(data_source: DataSourceProto):
  50         assert data_source.HasField("custom_options")
  51 
  52         postgres_options = json.loads(data_source.custom_options.configuration)
  53         return PostgreSQLSource(
  54             name=postgres_options["name"],
  55             query=postgres_options["query"],
  56             field_mapping=dict(data_source.field_mapping),
  57             timestamp_field=data_source.timestamp_field,
  58             created_timestamp_column=data_source.created_timestamp_column,
  59             date_partition_column=data_source.date_partition_column,
  60         )
  61 
  62     def to_proto(self) -> DataSourceProto:
  63         data_source_proto = DataSourceProto(
  64             type=DataSourceProto.CUSTOM_SOURCE,
  65             data_source_class_type="feast.infra.offline_stores.contrib.postgres_offline_store.postgres_source.PostgreSQLSource",
  66             field_mapping=self.field_mapping,
  67             custom_options=self._postgres_options.to_proto(),
  68         )
  69 
  70         data_source_proto.timestamp_field = self.timestamp_field
  71         data_source_proto.created_timestamp_column = self.created_timestamp_column
  72         data_source_proto.date_partition_column = self.date_partition_column
  73 
  74         return data_source_proto
  75 
  76     def validate(self, config: RepoConfig):
  77         pass
  78 
  79     @staticmethod
  80     def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]:
  81         return pg_type_to_feast_value_type
  82 
  83     def get_table_column_names_and_types(
  84         self, config: RepoConfig
  85     ) -> Iterable[Tuple[str, str]]:
  86         with _get_conn(config.offline_store) as conn, conn.cursor() as cur:
  87             cur.execute(
  88                 f"SELECT * FROM ({self.get_table_query_string()}) AS sub LIMIT 0"
  89             )
  90             return (
  91                 (c.name, pg_type_code_to_pg_type(c.type_code)) for c in cur.description
  92             )
  93 
  94     def get_table_query_string(self) -> str:
  95         return f"({self._postgres_options._query})"
  96 
  97 
  98 class PostgreSQLOptions:
  99     def __init__(self, name: str, query: Optional[str]):
  100         self._name = name
  101         self._query = query
  102 
  103     @classmethod
  104     def from_proto(cls, postgres_options_proto: DataSourceProto.CustomSourceOptions):
  105         config = json.loads(postgres_options_proto.configuration.decode("utf8"))
  106         postgres_options = cls(name=config["name"], query=config["query"])
  107 
  108         return postgres_options
  109 
  110     def to_proto(self) -> DataSourceProto.CustomSourceOptions:
  111         postgres_options_proto = DataSourceProto.CustomSourceOptions(
  112             configuration=json.dumps(
  113                 {"name": self._name, "query": self._query}
  114             ).encode()
  115         )
  116 
  117         return postgres_options_proto
  118
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres_source.py b/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres_source.py
  --- a/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres_source.py
  +++ b/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres_source.py
  @@ -18,6 +18,9 @@
           created_timestamp_column: Optional[str] = "",
           field_mapping: Optional[Dict[str, str]] = None,
           date_partition_column: Optional[str] = "",
  +        description: Optional[str] = "",
  +        tags: Optional[Dict[str, str]] = None,
  +        owner: Optional[str] = "",
       ):
           self._postgres_options = PostgreSQLOptions(name=name, query=query)
   
  @@ -27,6 +30,9 @@
               created_timestamp_column=created_timestamp_column,
               field_mapping=field_mapping,
               date_partition_column=date_partition_column,
  +            description=description,
  +            tags=tags,
  +            owner=owner,
           )
   
       def __hash__(self):
  @@ -57,14 +63,21 @@
               timestamp_field=data_source.timestamp_field,
               created_timestamp_column=data_source.created_timestamp_column,
               date_partition_column=data_source.date_partition_column,
  +            description=data_source.description,
  +            tags=dict(data_source.tags),
  +            owner=data_source.owner,
           )
   
       def to_proto(self) -> DataSourceProto:
           data_source_proto = DataSourceProto(
  +            name=self.name,
               type=DataSourceProto.CUSTOM_SOURCE,
               data_source_class_type="feast.infra.offline_stores.contrib.postgres_offline_store.postgres_source.PostgreSQLSource",
               field_mapping=self.field_mapping,
               custom_options=self._postgres_options.to_proto(),
  +            description=self.description,
  +            tags=self.tags,
  +            owner=self.owner,
           )
   
           data_source_proto.timestamp_field = self.timestamp_field
  
verification_info: {"golden_diff": "diff --git a/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres_source.py b/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres_source.py\n--- a/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres_source.py\n+++ b/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres_source.py\n@@ -18,6 +18,9 @@\n         created_timestamp_column: Optional[str] = \"\",\n         field_mapping: Optional[Dict[str, str]] = None,\n         date_partition_column: Optional[str] = \"\",\n+        description: Optional[str] = \"\",\n+        tags: Optional[Dict[str, str]] = None,\n+        owner: Optional[str] = \"\",\n     ):\n         self._postgres_options = PostgreSQLOptions(name=name, query=query)\n \n@@ -27,6 +30,9 @@\n             created_timestamp_column=created_timestamp_column,\n             field_mapping=field_mapping,\n             date_partition_column=date_partition_column,\n+            description=description,\n+            tags=tags,\n+            owner=owner,\n         )\n \n     def __hash__(self):\n@@ -57,14 +63,21 @@\n             timestamp_field=data_source.timestamp_field,\n             created_timestamp_column=data_source.created_timestamp_column,\n             date_partition_column=data_source.date_partition_column,\n+            description=data_source.description,\n+            tags=dict(data_source.tags),\n+            owner=data_source.owner,\n         )\n \n     def to_proto(self) -> DataSourceProto:\n         data_source_proto = DataSourceProto(\n+            name=self.name,\n             type=DataSourceProto.CUSTOM_SOURCE,\n             data_source_class_type=\"feast.infra.offline_stores.contrib.postgres_offline_store.postgres_source.PostgreSQLSource\",\n             field_mapping=self.field_mapping,\n             custom_options=self._postgres_options.to_proto(),\n+            description=self.description,\n+            tags=self.tags,\n+            owner=self.owner,\n         )\n \n         data_source_proto.timestamp_field = self.timestamp_field\n", "issue": "Incorrect projects-list.json generated by feast ui when using Postgres as a data source.\n## Expected Behavior \r\nCorrect generation of the projects-list.json when running feast ui. \r\n## Current Behavior\r\nThe generated projects-list.json does not contain a name in the dataSources field, causing the parser to fail.\r\n## Steps to reproduce\r\nSetup feast with PostgreSQL as a data source.\r\n### Specifications\r\n\r\n- Version:\r\n- Platform:\r\n- Subsystem:\r\n\r\n## Possible Solution\r\nAdding name=self.name to to_proto() in postgres_source.py. And in general making the postgres_source.py file more similar to e.g., file_source.py.\n", "before_files": [{"content": "import json\nfrom typing import Callable, Dict, Iterable, Optional, Tuple\n\nfrom feast.data_source import DataSource\nfrom feast.infra.utils.postgres.connection_utils import _get_conn\nfrom feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto\nfrom feast.repo_config import RepoConfig\nfrom feast.type_map import pg_type_code_to_pg_type, pg_type_to_feast_value_type\nfrom feast.value_type import ValueType\n\n\nclass PostgreSQLSource(DataSource):\n    def __init__(\n        self,\n        name: str,\n        query: str,\n        timestamp_field: Optional[str] = \"\",\n        created_timestamp_column: Optional[str] = \"\",\n        field_mapping: Optional[Dict[str, str]] = None,\n        date_partition_column: Optional[str] = \"\",\n    ):\n        self._postgres_options = PostgreSQLOptions(name=name, query=query)\n\n        super().__init__(\n            name=name,\n            timestamp_field=timestamp_field,\n            created_timestamp_column=created_timestamp_column,\n            field_mapping=field_mapping,\n            date_partition_column=date_partition_column,\n        )\n\n    def __hash__(self):\n        return super().__hash__()\n\n    def __eq__(self, other):\n        if not isinstance(other, PostgreSQLSource):\n            raise TypeError(\n                \"Comparisons should only involve PostgreSQLSource class objects.\"\n            )\n\n        return (\n            self._postgres_options._query == other._postgres_options._query\n            and self.timestamp_field == other.timestamp_field\n            and self.created_timestamp_column == other.created_timestamp_column\n            and self.field_mapping == other.field_mapping\n        )\n\n    @staticmethod\n    def from_proto(data_source: DataSourceProto):\n        assert data_source.HasField(\"custom_options\")\n\n        postgres_options = json.loads(data_source.custom_options.configuration)\n        return PostgreSQLSource(\n            name=postgres_options[\"name\"],\n            query=postgres_options[\"query\"],\n            field_mapping=dict(data_source.field_mapping),\n            timestamp_field=data_source.timestamp_field,\n            created_timestamp_column=data_source.created_timestamp_column,\n            date_partition_column=data_source.date_partition_column,\n        )\n\n    def to_proto(self) -> DataSourceProto:\n        data_source_proto = DataSourceProto(\n            type=DataSourceProto.CUSTOM_SOURCE,\n            data_source_class_type=\"feast.infra.offline_stores.contrib.postgres_offline_store.postgres_source.PostgreSQLSource\",\n            field_mapping=self.field_mapping,\n            custom_options=self._postgres_options.to_proto(),\n        )\n\n        data_source_proto.timestamp_field = self.timestamp_field\n        data_source_proto.created_timestamp_column = self.created_timestamp_column\n        data_source_proto.date_partition_column = self.date_partition_column\n\n        return data_source_proto\n\n    def validate(self, config: RepoConfig):\n        pass\n\n    @staticmethod\n    def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]:\n        return pg_type_to_feast_value_type\n\n    def get_table_column_names_and_types(\n        self, config: RepoConfig\n    ) -> Iterable[Tuple[str, str]]:\n        with _get_conn(config.offline_store) as conn, conn.cursor() as cur:\n            cur.execute(\n                f\"SELECT * FROM ({self.get_table_query_string()}) AS sub LIMIT 0\"\n            )\n            return (\n                (c.name, pg_type_code_to_pg_type(c.type_code)) for c in cur.description\n            )\n\n    def get_table_query_string(self) -> str:\n        return f\"({self._postgres_options._query})\"\n\n\nclass PostgreSQLOptions:\n    def __init__(self, name: str, query: Optional[str]):\n        self._name = name\n        self._query = query\n\n    @classmethod\n    def from_proto(cls, postgres_options_proto: DataSourceProto.CustomSourceOptions):\n        config = json.loads(postgres_options_proto.configuration.decode(\"utf8\"))\n        postgres_options = cls(name=config[\"name\"], query=config[\"query\"])\n\n        return postgres_options\n\n    def to_proto(self) -> DataSourceProto.CustomSourceOptions:\n        postgres_options_proto = DataSourceProto.CustomSourceOptions(\n            configuration=json.dumps(\n                {\"name\": self._name, \"query\": self._query}\n            ).encode()\n        )\n\n        return postgres_options_proto\n", "path": "sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres_source.py"}], "after_files": [{"content": "import json\nfrom typing import Callable, Dict, Iterable, Optional, Tuple\n\nfrom feast.data_source import DataSource\nfrom feast.infra.utils.postgres.connection_utils import _get_conn\nfrom feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto\nfrom feast.repo_config import RepoConfig\nfrom feast.type_map import pg_type_code_to_pg_type, pg_type_to_feast_value_type\nfrom feast.value_type import ValueType\n\n\nclass PostgreSQLSource(DataSource):\n    def __init__(\n        self,\n        name: str,\n        query: str,\n        timestamp_field: Optional[str] = \"\",\n        created_timestamp_column: Optional[str] = \"\",\n        field_mapping: Optional[Dict[str, str]] = None,\n        date_partition_column: Optional[str] = \"\",\n        description: Optional[str] = \"\",\n        tags: Optional[Dict[str, str]] = None,\n        owner: Optional[str] = \"\",\n    ):\n        self._postgres_options = PostgreSQLOptions(name=name, query=query)\n\n        super().__init__(\n            name=name,\n            timestamp_field=timestamp_field,\n            created_timestamp_column=created_timestamp_column,\n            field_mapping=field_mapping,\n            date_partition_column=date_partition_column,\n            description=description,\n            tags=tags,\n            owner=owner,\n        )\n\n    def __hash__(self):\n        return super().__hash__()\n\n    def __eq__(self, other):\n        if not isinstance(other, PostgreSQLSource):\n            raise TypeError(\n                \"Comparisons should only involve PostgreSQLSource class objects.\"\n            )\n\n        return (\n            self._postgres_options._query == other._postgres_options._query\n            and self.timestamp_field == other.timestamp_field\n            and self.created_timestamp_column == other.created_timestamp_column\n            and self.field_mapping == other.field_mapping\n        )\n\n    @staticmethod\n    def from_proto(data_source: DataSourceProto):\n        assert data_source.HasField(\"custom_options\")\n\n        postgres_options = json.loads(data_source.custom_options.configuration)\n        return PostgreSQLSource(\n            name=postgres_options[\"name\"],\n            query=postgres_options[\"query\"],\n            field_mapping=dict(data_source.field_mapping),\n            timestamp_field=data_source.timestamp_field,\n            created_timestamp_column=data_source.created_timestamp_column,\n            date_partition_column=data_source.date_partition_column,\n            description=data_source.description,\n            tags=dict(data_source.tags),\n            owner=data_source.owner,\n        )\n\n    def to_proto(self) -> DataSourceProto:\n        data_source_proto = DataSourceProto(\n            name=self.name,\n            type=DataSourceProto.CUSTOM_SOURCE,\n            data_source_class_type=\"feast.infra.offline_stores.contrib.postgres_offline_store.postgres_source.PostgreSQLSource\",\n            field_mapping=self.field_mapping,\n            custom_options=self._postgres_options.to_proto(),\n            description=self.description,\n            tags=self.tags,\n            owner=self.owner,\n        )\n\n        data_source_proto.timestamp_field = self.timestamp_field\n        data_source_proto.created_timestamp_column = self.created_timestamp_column\n        data_source_proto.date_partition_column = self.date_partition_column\n\n        return data_source_proto\n\n    def validate(self, config: RepoConfig):\n        pass\n\n    @staticmethod\n    def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]:\n        return pg_type_to_feast_value_type\n\n    def get_table_column_names_and_types(\n        self, config: RepoConfig\n    ) -> Iterable[Tuple[str, str]]:\n        with _get_conn(config.offline_store) as conn, conn.cursor() as cur:\n            cur.execute(\n                f\"SELECT * FROM ({self.get_table_query_string()}) AS sub LIMIT 0\"\n            )\n            return (\n                (c.name, pg_type_code_to_pg_type(c.type_code)) for c in cur.description\n            )\n\n    def get_table_query_string(self) -> str:\n        return f\"({self._postgres_options._query})\"\n\n\nclass PostgreSQLOptions:\n    def __init__(self, name: str, query: Optional[str]):\n        self._name = name\n        self._query = query\n\n    @classmethod\n    def from_proto(cls, postgres_options_proto: DataSourceProto.CustomSourceOptions):\n        config = json.loads(postgres_options_proto.configuration.decode(\"utf8\"))\n        postgres_options = cls(name=config[\"name\"], query=config[\"query\"])\n\n        return postgres_options\n\n    def to_proto(self) -> DataSourceProto.CustomSourceOptions:\n        postgres_options_proto = DataSourceProto.CustomSourceOptions(\n            configuration=json.dumps(\n                {\"name\": self._name, \"query\": self._query}\n            ).encode()\n        )\n\n        return postgres_options_proto\n", "path": "sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres_source.py"}]}