prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  FeatureService should support "description" as first class named-value argument as Entity does
  ## Expected Behavior 
  ...
  ```
  # Define your feature service and the features it will serve
  driver_fs = FeatureService(name="driver_ranking_fv_svc",
                             features=[driver_hourly_stats_view],
                             description="Used for training an ElasticNetCV model"})
  ```
  ```
  feast feature-services describe driver_ranking_fv_svc
  spec:
    name: driver_ranking_fv_svc
    features:
    - featureViewName: driver_hourly_stats
      featureColumns:
      - name: conv_rate
        valueType: FLOAT
      - name: acc_rate
        valueType: FLOAT
      - name: avg_daily_trips
        valueType: INT64
  description: Used for training an ElasticNetCV model
  meta: {}
  ```
  Extend the argument list in the [FeatureService ](https://github.com/feast-dev/feast/blob/7dff49a194a25a62927c1ee7022caf0651f68f38/sdk/python/feast/feature_service.py#L24)to support `description=None` as default
  ## Current Behavior
  
  ```
  # Define your feature service and the features it will serve
  driver_fs = FeatureService(name="driver_ranking_fv_svc",
                             features=[driver_hourly_stats_view],
                             tags={"description": "Used for training an ElasticNetCV model"})
  ```
  Then query the FS from the cli
  
  ```
  feast feature-services describe driver_ranking_fv_svc
  spec:
    name: driver_ranking_fv_svc
    features:
    - featureViewName: driver_hourly_stats
      featureColumns:
      - name: conv_rate
        valueType: FLOAT
      - name: acc_rate
        valueType: FLOAT
      - name: avg_daily_trips
        valueType: INT64
    tags:
      description: Used for training an ElasticNetCV model
  meta: {}
  ```
  ## Steps to reproduce
  
  Follow the steps above in the current behavior
  
  ### Specifications
  
  - Version: v0.12v
  
  
  --- 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/feature_service.py`
  Content:
  ```
  1 from datetime import datetime
  2 from typing import Dict, List, Optional, Union
  3 
  4 from google.protobuf.json_format import MessageToJson
  5 
  6 from feast.feature_table import FeatureTable
  7 from feast.feature_view import FeatureView
  8 from feast.feature_view_projection import FeatureViewProjection
  9 from feast.protos.feast.core.FeatureService_pb2 import (
  10     FeatureService as FeatureServiceProto,
  11 )
  12 from feast.protos.feast.core.FeatureService_pb2 import (
  13     FeatureServiceMeta,
  14     FeatureServiceSpec,
  15 )
  16 
  17 
  18 class FeatureService:
  19     """
  20     A feature service is a logical grouping of features for retrieval (training or serving).
  21     The features grouped by a feature service may come from any number of feature views.
  22 
  23     Args:
  24         name: Unique name of the feature service.
  25         features: A list of Features that are grouped as part of this FeatureService.
  26             The list may contain Feature Views, Feature Tables, or a subset of either.
  27         tags (optional): A dictionary of key-value pairs used for organizing Feature
  28             Services.
  29     """
  30 
  31     name: str
  32     features: List[FeatureViewProjection]
  33     tags: Dict[str, str]
  34     created_timestamp: Optional[datetime] = None
  35     last_updated_timestamp: Optional[datetime] = None
  36 
  37     def __init__(
  38         self,
  39         name: str,
  40         features: List[Union[FeatureTable, FeatureView, FeatureViewProjection]],
  41         tags: Optional[Dict[str, str]] = None,
  42     ):
  43         """
  44         Creates a FeatureService object.
  45 
  46         Raises:
  47             ValueError: If one of the specified features is not a valid type.
  48         """
  49         self.name = name
  50         self.features = []
  51         for feature in features:
  52             if isinstance(feature, FeatureTable) or isinstance(feature, FeatureView):
  53                 self.features.append(FeatureViewProjection.from_definition(feature))
  54             elif isinstance(feature, FeatureViewProjection):
  55                 self.features.append(feature)
  56             else:
  57                 raise ValueError(f"Unexpected type: {type(feature)}")
  58         self.tags = tags or {}
  59         self.created_timestamp = None
  60         self.last_updated_timestamp = None
  61 
  62     def __repr__(self):
  63         items = (f"{k} = {v}" for k, v in self.__dict__.items())
  64         return f"<{self.__class__.__name__}({', '.join(items)})>"
  65 
  66     def __str__(self):
  67         return str(MessageToJson(self.to_proto()))
  68 
  69     def __hash__(self):
  70         return hash(self.name)
  71 
  72     def __eq__(self, other):
  73         if not isinstance(other, FeatureService):
  74             raise TypeError(
  75                 "Comparisons should only involve FeatureService class objects."
  76             )
  77         if self.tags != other.tags or self.name != other.name:
  78             return False
  79 
  80         if sorted(self.features) != sorted(other.features):
  81             return False
  82 
  83         return True
  84 
  85     @staticmethod
  86     def from_proto(feature_service_proto: FeatureServiceProto):
  87         """
  88         Converts a FeatureServiceProto to a FeatureService object.
  89 
  90         Args:
  91             feature_service_proto: A protobuf representation of a FeatureService.
  92         """
  93         fs = FeatureService(
  94             name=feature_service_proto.spec.name,
  95             features=[
  96                 FeatureViewProjection.from_proto(fp)
  97                 for fp in feature_service_proto.spec.features
  98             ],
  99             tags=dict(feature_service_proto.spec.tags),
  100         )
  101 
  102         if feature_service_proto.meta.HasField("created_timestamp"):
  103             fs.created_timestamp = (
  104                 feature_service_proto.meta.created_timestamp.ToDatetime()
  105             )
  106         if feature_service_proto.meta.HasField("last_updated_timestamp"):
  107             fs.last_updated_timestamp = (
  108                 feature_service_proto.meta.last_updated_timestamp.ToDatetime()
  109             )
  110 
  111         return fs
  112 
  113     def to_proto(self) -> FeatureServiceProto:
  114         """
  115         Converts a FeatureService to its protobuf representation.
  116 
  117         Returns:
  118             A FeatureServiceProto protobuf.
  119         """
  120         meta = FeatureServiceMeta()
  121         if self.created_timestamp:
  122             meta.created_timestamp.FromDatetime(self.created_timestamp)
  123 
  124         spec = FeatureServiceSpec()
  125         spec.name = self.name
  126         for definition in self.features:
  127             if isinstance(definition, FeatureTable) or isinstance(
  128                 definition, FeatureView
  129             ):
  130                 feature_ref = FeatureViewProjection(
  131                     definition.name, definition.features
  132                 )
  133             else:
  134                 feature_ref = definition
  135 
  136             spec.features.append(feature_ref.to_proto())
  137 
  138         if self.tags:
  139             spec.tags.update(self.tags)
  140 
  141         feature_service_proto = FeatureServiceProto(spec=spec, meta=meta)
  142         return feature_service_proto
  143 
  144     def validate(self):
  145         pass
  146
  ```
  --- 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/feature_service.py b/sdk/python/feast/feature_service.py
  --- a/sdk/python/feast/feature_service.py
  +++ b/sdk/python/feast/feature_service.py
  @@ -31,6 +31,7 @@
       name: str
       features: List[FeatureViewProjection]
       tags: Dict[str, str]
  +    description: Optional[str] = None
       created_timestamp: Optional[datetime] = None
       last_updated_timestamp: Optional[datetime] = None
   
  @@ -39,6 +40,7 @@
           name: str,
           features: List[Union[FeatureTable, FeatureView, FeatureViewProjection]],
           tags: Optional[Dict[str, str]] = None,
  +        description: Optional[str] = None,
       ):
           """
           Creates a FeatureService object.
  @@ -56,6 +58,7 @@
               else:
                   raise ValueError(f"Unexpected type: {type(feature)}")
           self.tags = tags or {}
  +        self.description = description
           self.created_timestamp = None
           self.last_updated_timestamp = None
   
  @@ -97,6 +100,11 @@
                   for fp in feature_service_proto.spec.features
               ],
               tags=dict(feature_service_proto.spec.tags),
  +            description=(
  +                feature_service_proto.spec.description
  +                if feature_service_proto.spec.description != ""
  +                else None
  +            ),
           )
   
           if feature_service_proto.meta.HasField("created_timestamp"):
  @@ -137,6 +145,8 @@
   
           if self.tags:
               spec.tags.update(self.tags)
  +        if self.description:
  +            spec.description = self.description
   
           feature_service_proto = FeatureServiceProto(spec=spec, meta=meta)
           return feature_service_proto
  
verification_info: {"golden_diff": "diff --git a/sdk/python/feast/feature_service.py b/sdk/python/feast/feature_service.py\n--- a/sdk/python/feast/feature_service.py\n+++ b/sdk/python/feast/feature_service.py\n@@ -31,6 +31,7 @@\n     name: str\n     features: List[FeatureViewProjection]\n     tags: Dict[str, str]\n+    description: Optional[str] = None\n     created_timestamp: Optional[datetime] = None\n     last_updated_timestamp: Optional[datetime] = None\n \n@@ -39,6 +40,7 @@\n         name: str,\n         features: List[Union[FeatureTable, FeatureView, FeatureViewProjection]],\n         tags: Optional[Dict[str, str]] = None,\n+        description: Optional[str] = None,\n     ):\n         \"\"\"\n         Creates a FeatureService object.\n@@ -56,6 +58,7 @@\n             else:\n                 raise ValueError(f\"Unexpected type: {type(feature)}\")\n         self.tags = tags or {}\n+        self.description = description\n         self.created_timestamp = None\n         self.last_updated_timestamp = None\n \n@@ -97,6 +100,11 @@\n                 for fp in feature_service_proto.spec.features\n             ],\n             tags=dict(feature_service_proto.spec.tags),\n+            description=(\n+                feature_service_proto.spec.description\n+                if feature_service_proto.spec.description != \"\"\n+                else None\n+            ),\n         )\n \n         if feature_service_proto.meta.HasField(\"created_timestamp\"):\n@@ -137,6 +145,8 @@\n \n         if self.tags:\n             spec.tags.update(self.tags)\n+        if self.description:\n+            spec.description = self.description\n \n         feature_service_proto = FeatureServiceProto(spec=spec, meta=meta)\n         return feature_service_proto\n", "issue": "FeatureService should support \"description\" as first class named-value argument as Entity does\n## Expected Behavior \r\n...\r\n```\r\n# Define your feature service and the features it will serve\r\ndriver_fs = FeatureService(name=\"driver_ranking_fv_svc\",\r\n                           features=[driver_hourly_stats_view],\r\n                           description=\"Used for training an ElasticNetCV model\"})\r\n```\r\n```\r\nfeast feature-services describe driver_ranking_fv_svc\r\nspec:\r\n  name: driver_ranking_fv_svc\r\n  features:\r\n  - featureViewName: driver_hourly_stats\r\n    featureColumns:\r\n    - name: conv_rate\r\n      valueType: FLOAT\r\n    - name: acc_rate\r\n      valueType: FLOAT\r\n    - name: avg_daily_trips\r\n      valueType: INT64\r\ndescription: Used for training an ElasticNetCV model\r\nmeta: {}\r\n```\r\nExtend the argument list in the [FeatureService ](https://github.com/feast-dev/feast/blob/7dff49a194a25a62927c1ee7022caf0651f68f38/sdk/python/feast/feature_service.py#L24)to support `description=None` as default\r\n## Current Behavior\r\n\r\n```\r\n# Define your feature service and the features it will serve\r\ndriver_fs = FeatureService(name=\"driver_ranking_fv_svc\",\r\n                           features=[driver_hourly_stats_view],\r\n                           tags={\"description\": \"Used for training an ElasticNetCV model\"})\r\n```\r\nThen query the FS from the cli\r\n\r\n```\r\nfeast feature-services describe driver_ranking_fv_svc\r\nspec:\r\n  name: driver_ranking_fv_svc\r\n  features:\r\n  - featureViewName: driver_hourly_stats\r\n    featureColumns:\r\n    - name: conv_rate\r\n      valueType: FLOAT\r\n    - name: acc_rate\r\n      valueType: FLOAT\r\n    - name: avg_daily_trips\r\n      valueType: INT64\r\n  tags:\r\n    description: Used for training an ElasticNetCV model\r\nmeta: {}\r\n```\r\n## Steps to reproduce\r\n\r\nFollow the steps above in the current behavior\r\n\r\n### Specifications\r\n\r\n- Version: v0.12v\r\n\n", "before_files": [{"content": "from datetime import datetime\nfrom typing import Dict, List, Optional, Union\n\nfrom google.protobuf.json_format import MessageToJson\n\nfrom feast.feature_table import FeatureTable\nfrom feast.feature_view import FeatureView\nfrom feast.feature_view_projection import FeatureViewProjection\nfrom feast.protos.feast.core.FeatureService_pb2 import (\n    FeatureService as FeatureServiceProto,\n)\nfrom feast.protos.feast.core.FeatureService_pb2 import (\n    FeatureServiceMeta,\n    FeatureServiceSpec,\n)\n\n\nclass FeatureService:\n    \"\"\"\n    A feature service is a logical grouping of features for retrieval (training or serving).\n    The features grouped by a feature service may come from any number of feature views.\n\n    Args:\n        name: Unique name of the feature service.\n        features: A list of Features that are grouped as part of this FeatureService.\n            The list may contain Feature Views, Feature Tables, or a subset of either.\n        tags (optional): A dictionary of key-value pairs used for organizing Feature\n            Services.\n    \"\"\"\n\n    name: str\n    features: List[FeatureViewProjection]\n    tags: Dict[str, str]\n    created_timestamp: Optional[datetime] = None\n    last_updated_timestamp: Optional[datetime] = None\n\n    def __init__(\n        self,\n        name: str,\n        features: List[Union[FeatureTable, FeatureView, FeatureViewProjection]],\n        tags: Optional[Dict[str, str]] = None,\n    ):\n        \"\"\"\n        Creates a FeatureService object.\n\n        Raises:\n            ValueError: If one of the specified features is not a valid type.\n        \"\"\"\n        self.name = name\n        self.features = []\n        for feature in features:\n            if isinstance(feature, FeatureTable) or isinstance(feature, FeatureView):\n                self.features.append(FeatureViewProjection.from_definition(feature))\n            elif isinstance(feature, FeatureViewProjection):\n                self.features.append(feature)\n            else:\n                raise ValueError(f\"Unexpected type: {type(feature)}\")\n        self.tags = tags or {}\n        self.created_timestamp = None\n        self.last_updated_timestamp = None\n\n    def __repr__(self):\n        items = (f\"{k} = {v}\" for k, v in self.__dict__.items())\n        return f\"<{self.__class__.__name__}({', '.join(items)})>\"\n\n    def __str__(self):\n        return str(MessageToJson(self.to_proto()))\n\n    def __hash__(self):\n        return hash(self.name)\n\n    def __eq__(self, other):\n        if not isinstance(other, FeatureService):\n            raise TypeError(\n                \"Comparisons should only involve FeatureService class objects.\"\n            )\n        if self.tags != other.tags or self.name != other.name:\n            return False\n\n        if sorted(self.features) != sorted(other.features):\n            return False\n\n        return True\n\n    @staticmethod\n    def from_proto(feature_service_proto: FeatureServiceProto):\n        \"\"\"\n        Converts a FeatureServiceProto to a FeatureService object.\n\n        Args:\n            feature_service_proto: A protobuf representation of a FeatureService.\n        \"\"\"\n        fs = FeatureService(\n            name=feature_service_proto.spec.name,\n            features=[\n                FeatureViewProjection.from_proto(fp)\n                for fp in feature_service_proto.spec.features\n            ],\n            tags=dict(feature_service_proto.spec.tags),\n        )\n\n        if feature_service_proto.meta.HasField(\"created_timestamp\"):\n            fs.created_timestamp = (\n                feature_service_proto.meta.created_timestamp.ToDatetime()\n            )\n        if feature_service_proto.meta.HasField(\"last_updated_timestamp\"):\n            fs.last_updated_timestamp = (\n                feature_service_proto.meta.last_updated_timestamp.ToDatetime()\n            )\n\n        return fs\n\n    def to_proto(self) -> FeatureServiceProto:\n        \"\"\"\n        Converts a FeatureService to its protobuf representation.\n\n        Returns:\n            A FeatureServiceProto protobuf.\n        \"\"\"\n        meta = FeatureServiceMeta()\n        if self.created_timestamp:\n            meta.created_timestamp.FromDatetime(self.created_timestamp)\n\n        spec = FeatureServiceSpec()\n        spec.name = self.name\n        for definition in self.features:\n            if isinstance(definition, FeatureTable) or isinstance(\n                definition, FeatureView\n            ):\n                feature_ref = FeatureViewProjection(\n                    definition.name, definition.features\n                )\n            else:\n                feature_ref = definition\n\n            spec.features.append(feature_ref.to_proto())\n\n        if self.tags:\n            spec.tags.update(self.tags)\n\n        feature_service_proto = FeatureServiceProto(spec=spec, meta=meta)\n        return feature_service_proto\n\n    def validate(self):\n        pass\n", "path": "sdk/python/feast/feature_service.py"}], "after_files": [{"content": "from datetime import datetime\nfrom typing import Dict, List, Optional, Union\n\nfrom google.protobuf.json_format import MessageToJson\n\nfrom feast.feature_table import FeatureTable\nfrom feast.feature_view import FeatureView\nfrom feast.feature_view_projection import FeatureViewProjection\nfrom feast.protos.feast.core.FeatureService_pb2 import (\n    FeatureService as FeatureServiceProto,\n)\nfrom feast.protos.feast.core.FeatureService_pb2 import (\n    FeatureServiceMeta,\n    FeatureServiceSpec,\n)\n\n\nclass FeatureService:\n    \"\"\"\n    A feature service is a logical grouping of features for retrieval (training or serving).\n    The features grouped by a feature service may come from any number of feature views.\n\n    Args:\n        name: Unique name of the feature service.\n        features: A list of Features that are grouped as part of this FeatureService.\n            The list may contain Feature Views, Feature Tables, or a subset of either.\n        tags (optional): A dictionary of key-value pairs used for organizing Feature\n            Services.\n    \"\"\"\n\n    name: str\n    features: List[FeatureViewProjection]\n    tags: Dict[str, str]\n    description: Optional[str] = None\n    created_timestamp: Optional[datetime] = None\n    last_updated_timestamp: Optional[datetime] = None\n\n    def __init__(\n        self,\n        name: str,\n        features: List[Union[FeatureTable, FeatureView, FeatureViewProjection]],\n        tags: Optional[Dict[str, str]] = None,\n        description: Optional[str] = None,\n    ):\n        \"\"\"\n        Creates a FeatureService object.\n\n        Raises:\n            ValueError: If one of the specified features is not a valid type.\n        \"\"\"\n        self.name = name\n        self.features = []\n        for feature in features:\n            if isinstance(feature, FeatureTable) or isinstance(feature, FeatureView):\n                self.features.append(FeatureViewProjection.from_definition(feature))\n            elif isinstance(feature, FeatureViewProjection):\n                self.features.append(feature)\n            else:\n                raise ValueError(f\"Unexpected type: {type(feature)}\")\n        self.tags = tags or {}\n        self.description = description\n        self.created_timestamp = None\n        self.last_updated_timestamp = None\n\n    def __repr__(self):\n        items = (f\"{k} = {v}\" for k, v in self.__dict__.items())\n        return f\"<{self.__class__.__name__}({', '.join(items)})>\"\n\n    def __str__(self):\n        return str(MessageToJson(self.to_proto()))\n\n    def __hash__(self):\n        return hash(self.name)\n\n    def __eq__(self, other):\n        if not isinstance(other, FeatureService):\n            raise TypeError(\n                \"Comparisons should only involve FeatureService class objects.\"\n            )\n        if self.tags != other.tags or self.name != other.name:\n            return False\n\n        if sorted(self.features) != sorted(other.features):\n            return False\n\n        return True\n\n    @staticmethod\n    def from_proto(feature_service_proto: FeatureServiceProto):\n        \"\"\"\n        Converts a FeatureServiceProto to a FeatureService object.\n\n        Args:\n            feature_service_proto: A protobuf representation of a FeatureService.\n        \"\"\"\n        fs = FeatureService(\n            name=feature_service_proto.spec.name,\n            features=[\n                FeatureViewProjection.from_proto(fp)\n                for fp in feature_service_proto.spec.features\n            ],\n            tags=dict(feature_service_proto.spec.tags),\n            description=(\n                feature_service_proto.spec.description\n                if feature_service_proto.spec.description != \"\"\n                else None\n            ),\n        )\n\n        if feature_service_proto.meta.HasField(\"created_timestamp\"):\n            fs.created_timestamp = (\n                feature_service_proto.meta.created_timestamp.ToDatetime()\n            )\n        if feature_service_proto.meta.HasField(\"last_updated_timestamp\"):\n            fs.last_updated_timestamp = (\n                feature_service_proto.meta.last_updated_timestamp.ToDatetime()\n            )\n\n        return fs\n\n    def to_proto(self) -> FeatureServiceProto:\n        \"\"\"\n        Converts a FeatureService to its protobuf representation.\n\n        Returns:\n            A FeatureServiceProto protobuf.\n        \"\"\"\n        meta = FeatureServiceMeta()\n        if self.created_timestamp:\n            meta.created_timestamp.FromDatetime(self.created_timestamp)\n\n        spec = FeatureServiceSpec()\n        spec.name = self.name\n        for definition in self.features:\n            if isinstance(definition, FeatureTable) or isinstance(\n                definition, FeatureView\n            ):\n                feature_ref = FeatureViewProjection(\n                    definition.name, definition.features\n                )\n            else:\n                feature_ref = definition\n\n            spec.features.append(feature_ref.to_proto())\n\n        if self.tags:\n            spec.tags.update(self.tags)\n        if self.description:\n            spec.description = self.description\n\n        feature_service_proto = FeatureServiceProto(spec=spec, meta=meta)\n        return feature_service_proto\n\n    def validate(self):\n        pass\n", "path": "sdk/python/feast/feature_service.py"}]}