From c2a3f33f5c7561b113ac41f292e62e0933a82988 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=F0=9F=9A=80=20Jack?= <jacsteve@amazon.com>
Date: Fri, 20 Oct 2023 12:50:14 +1100
Subject: [PATCH] fix(type-safe-api): fix syntax error for python runtime
 request parameters with descriptions

Descriptions in Python request parameters would previously render invalid python syntax as quotes
were escaped as &quot;. Use triple curly braces to ensure these are rendered correctly.
Additionally, field references can only be used once per field in a pydantic model, and since fields
with descriptions include the field in the type annotation these would fail at runtime when another
field is used in the assignment (ie foo: Annotated[StrictStr, Field(..., description="...")] =
Field(alias='foo') ). We therefore remove the assignment of a Field value, which is ok since the
alias is not required as the handler wrapper already constructs a dict with the "paramName"s as keys
rather than the "baseName"s which are in the raw request.

Fixes #609
---
 .../python/templates/operationConfig.mustache |  6 +-
 .../test/resources/specs/single.yaml          |  6 ++
 .../__snapshots__/docs.test.ts.snap           | 74 ++++++++++-------
 .../__snapshots__/java.test.ts.snap           | 40 ++++++----
 .../__snapshots__/python.test.ts.snap         | 80 ++++++++++---------
 .../__snapshots__/typescript.test.ts.snap     |  6 +-
 6 files changed, 120 insertions(+), 92 deletions(-)

diff --git a/packages/type-safe-api/scripts/type-safe-api/generators/python/templates/operationConfig.mustache b/packages/type-safe-api/scripts/type-safe-api/generators/python/templates/operationConfig.mustache
index bad2e254c..2215dc967 100644
--- a/packages/type-safe-api/scripts/type-safe-api/generators/python/templates/operationConfig.mustache
+++ b/packages/type-safe-api/scripts/type-safe-api/generators/python/templates/operationConfig.mustache
@@ -1,7 +1,7 @@
 from __future__ import annotations
 import urllib.parse
 import json
-from typing import Callable, Any, Dict, List, NamedTuple, TypeVar, Generic, Union, TypedDict, Protocol, Optional, Literal
+from typing import Callable, Any, Dict, List, NamedTuple, TypeVar, Generic, Union, TypedDict, Protocol, Optional, Literal, Annotated
 from functools import wraps
 from dataclasses import dataclass, fields
 from datetime import datetime
@@ -215,7 +215,7 @@ class {{operationIdCamelCase}}RequestParameters(BaseModel):
     """
     {{#allParams}}
     {{^isBodyParam}}
-    {{paramName}}: {{vendorExtensions.x-py-typing}} = Field(alias='{{baseName}}'{{^required}}, default=None{{/required}})
+    {{paramName}}: {{{vendorExtensions.x-py-typing}}}
     {{/isBodyParam}}
     {{/allParams}}
 
@@ -232,7 +232,7 @@ class {{operationIdCamelCase}}RequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> {{operationIdCamelCase}}RequestParameters:
diff --git a/packages/type-safe-api/test/resources/specs/single.yaml b/packages/type-safe-api/test/resources/specs/single.yaml
index 4c9428ffe..e8ab7a206 100644
--- a/packages/type-safe-api/test/resources/specs/single.yaml
+++ b/packages/type-safe-api/test/resources/specs/single.yaml
@@ -9,11 +9,13 @@ paths:
       parameters:
         - in: query
           name: param1
+          description: This is parameter 1
           schema:
             type: string
           required: true
         - in: query
           name: param2
+          description: This is parameter 2
           schema:
             type: array
             items:
@@ -36,6 +38,7 @@ paths:
           required: true
         - in: header
           name: x-header-param
+          description: This is a header parameter
           schema:
             type: string
           required: true
@@ -149,11 +152,13 @@ components:
       required:
         - errorMessage
     TestRequest:
+      description: This is a test request
       type: object
       properties:
         myInput:
           type: number
     TestResponse:
+      description: This is a test response
       type: object
       properties:
         messages:
@@ -162,6 +167,7 @@ components:
             type: object
             properties:
               message:
+                description: This is a message
                 type: string
               id:
                 type: integer
diff --git a/packages/type-safe-api/test/scripts/generators/__snapshots__/docs.test.ts.snap b/packages/type-safe-api/test/scripts/generators/__snapshots__/docs.test.ts.snap
index ae8c019c7..837acc81a 100644
--- a/packages/type-safe-api/test/scripts/generators/__snapshots__/docs.test.ts.snap
+++ b/packages/type-safe-api/test/scripts/generators/__snapshots__/docs.test.ts.snap
@@ -916,7 +916,8 @@ ul.nav-tabs {
     "myInput" : {
       "type" : "number"
     }
-  }
+  },
+  "description" : "This is a test request"
 };
     defs["TestResponse"] = {
   "required" : [ "messages" ],
@@ -928,14 +929,16 @@ ul.nav-tabs {
         "$ref" : "#/components/schemas/TestResponse_messages_inner"
       }
     }
-  }
+  },
+  "description" : "This is a test response"
 };
     defs["TestResponse_messages_inner"] = {
   "required" : [ "id" ],
   "type" : "object",
   "properties" : {
     "message" : {
-      "type" : "string"
+      "type" : "string",
+      "description" : "This is a message"
     },
     "id" : {
       "type" : "integer"
@@ -2655,11 +2658,11 @@ public class DefaultApiExample {
 
         // Create an instance of the API class
         DefaultApi apiInstance = new DefaultApi();
-        String param1 = param1_example; // String | 
-        array[String] param2 = ; // array[String] | 
+        String param1 = param1_example; // String | This is parameter 1
+        array[String] param2 = ; // array[String] | This is parameter 2
         BigDecimal param3 = 8.14; // BigDecimal | 
         String pathParam = pathParam_example; // String | 
-        String xHeaderParam = xHeaderParam_example; // String | 
+        String xHeaderParam = xHeaderParam_example; // String | This is a header parameter
         TestRequest testRequest = ; // TestRequest | 
         String param4 = param4_example; // String | 
         array[String] xMultiValueHeaderParam = ; // array[String] | 
@@ -2682,11 +2685,11 @@ public class DefaultApiExample {
 public class DefaultApiExample {
     public static void main(String[] args) {
         DefaultApi apiInstance = new DefaultApi();
-        String param1 = param1_example; // String | 
-        array[String] param2 = ; // array[String] | 
+        String param1 = param1_example; // String | This is parameter 1
+        array[String] param2 = ; // array[String] | This is parameter 2
         BigDecimal param3 = 8.14; // BigDecimal | 
         String pathParam = pathParam_example; // String | 
-        String xHeaderParam = xHeaderParam_example; // String | 
+        String xHeaderParam = xHeaderParam_example; // String | This is a header parameter
         TestRequest testRequest = ; // TestRequest | 
         String param4 = param4_example; // String | 
         array[String] xMultiValueHeaderParam = ; // array[String] | 
@@ -2710,11 +2713,11 @@ public class DefaultApiExample {
 
 // Create an instance of the API class
 DefaultApi *apiInstance = [[DefaultApi alloc] init];
-String *param1 = param1_example; //  (default to null)
-array[String] *param2 = ; //  (default to null)
+String *param1 = param1_example; // This is parameter 1 (default to null)
+array[String] *param2 = ; // This is parameter 2 (default to null)
 BigDecimal *param3 = 8.14; //  (default to null)
 String *pathParam = pathParam_example; //  (default to null)
-String *xHeaderParam = xHeaderParam_example; //  (default to null)
+String *xHeaderParam = xHeaderParam_example; // This is a header parameter (default to null)
 TestRequest *testRequest = ; // 
 String *param4 = param4_example; //  (optional) (default to null)
 array[String] *xMultiValueHeaderParam = ; //  (optional) (default to null)
@@ -2743,11 +2746,11 @@ array[String] *xMultiValueHeaderParam = ; //  (optional) (default to null)
 
 // Create an instance of the API class
 var api = new ExampleApi.DefaultApi()
-var param1 = param1_example; // {String} 
-var param2 = ; // {array[String]} 
+var param1 = param1_example; // {String} This is parameter 1
+var param2 = ; // {array[String]} This is parameter 2
 var param3 = 8.14; // {BigDecimal} 
 var pathParam = pathParam_example; // {String} 
-var xHeaderParam = xHeaderParam_example; // {String} 
+var xHeaderParam = xHeaderParam_example; // {String} This is a header parameter
 var testRequest = ; // {TestRequest} 
 var opts = {
   'param4': param4_example, // {String} 
@@ -2784,11 +2787,11 @@ namespace Example
 
             // Create an instance of the API class
             var apiInstance = new DefaultApi();
-            var param1 = param1_example;  // String |  (default to null)
-            var param2 = new array[String](); // array[String] |  (default to null)
+            var param1 = param1_example;  // String | This is parameter 1 (default to null)
+            var param2 = new array[String](); // array[String] | This is parameter 2 (default to null)
             var param3 = 8.14;  // BigDecimal |  (default to null)
             var pathParam = pathParam_example;  // String |  (default to null)
-            var xHeaderParam = xHeaderParam_example;  // String |  (default to null)
+            var xHeaderParam = xHeaderParam_example;  // String | This is a header parameter (default to null)
             var testRequest = new TestRequest(); // TestRequest | 
             var param4 = param4_example;  // String |  (optional)  (default to null)
             var xMultiValueHeaderParam = new array[String](); // array[String] |  (optional)  (default to null)
@@ -2811,11 +2814,11 @@ require_once(__DIR__ . '/vendor/autoload.php');
 
 // Create an instance of the API class
 $api_instance = new OpenAPITools\\Client\\Api\\DefaultApi();
-$param1 = param1_example; // String | 
-$param2 = ; // array[String] | 
+$param1 = param1_example; // String | This is parameter 1
+$param2 = ; // array[String] | This is parameter 2
 $param3 = 8.14; // BigDecimal | 
 $pathParam = pathParam_example; // String | 
-$xHeaderParam = xHeaderParam_example; // String | 
+$xHeaderParam = xHeaderParam_example; // String | This is a header parameter
 $testRequest = ; // TestRequest | 
 $param4 = param4_example; // String | 
 $xMultiValueHeaderParam = ; // array[String] | 
@@ -2836,11 +2839,11 @@ use WWW::OPenAPIClient::DefaultApi;
 
 # Create an instance of the API class
 my $api_instance = WWW::OPenAPIClient::DefaultApi->new();
-my $param1 = param1_example; # String | 
-my $param2 = []; # array[String] | 
+my $param1 = param1_example; # String | This is parameter 1
+my $param2 = []; # array[String] | This is parameter 2
 my $param3 = 8.14; # BigDecimal | 
 my $pathParam = pathParam_example; # String | 
-my $xHeaderParam = xHeaderParam_example; # String | 
+my $xHeaderParam = xHeaderParam_example; # String | This is a header parameter
 my $testRequest = WWW::OPenAPIClient::Object::TestRequest->new(); # TestRequest | 
 my $param4 = param4_example; # String | 
 my $xMultiValueHeaderParam = []; # array[String] | 
@@ -2863,11 +2866,11 @@ from pprint import pprint
 
 # Create an instance of the API class
 api_instance = openapi_client.DefaultApi()
-param1 = param1_example # String |  (default to null)
-param2 =  # array[String] |  (default to null)
+param1 = param1_example # String | This is parameter 1 (default to null)
+param2 =  # array[String] | This is parameter 2 (default to null)
 param3 = 8.14 # BigDecimal |  (default to null)
 pathParam = pathParam_example # String |  (default to null)
-xHeaderParam = xHeaderParam_example # String |  (default to null)
+xHeaderParam = xHeaderParam_example # String | This is a header parameter (default to null)
 testRequest =  # TestRequest | 
 param4 = param4_example # String |  (optional) (default to null)
 xMultiValueHeaderParam =  # array[String] |  (optional) (default to null)
@@ -2953,6 +2956,9 @@ pub fn main() {
                     String
                 </span>
 
+                    <div class="inner description marked">
+This is a header parameter
+                    </div>
             </div>
                 <div class="inner required">
                     Required
@@ -3046,6 +3052,9 @@ $(document).ready(function() {
                     String
                 </span>
 
+                    <div class="inner description marked">
+This is parameter 1
+                    </div>
             </div>
                 <div class="inner required">
                     Required
@@ -3066,6 +3075,9 @@ $(document).ready(function() {
                     array[String]
                 </span>
 
+                    <div class="inner description marked">
+This is parameter 2
+                    </div>
             </div>
                 <div class="inner required">
                     Required
@@ -5484,11 +5496,11 @@ No authorization required
 
 |Name | Type | Description  | Notes |
 |------------- | ------------- | ------------- | -------------|
-| **param1** | **String**|  | [default to null] |
-| **param2** | [**List**](../Models/String.md)|  | [default to null] |
+| **param1** | **String**| This is parameter 1 | [default to null] |
+| **param2** | [**List**](../Models/String.md)| This is parameter 2 | [default to null] |
 | **param3** | **BigDecimal**|  | [default to null] |
 | **pathParam** | **String**|  | [default to null] |
-| **x-header-param** | **String**|  | [default to null] |
+| **x-header-param** | **String**| This is a header parameter | [default to null] |
 | **TestRequest** | [**TestRequest**](../Models/TestRequest.md)|  | |
 | **param4** | **String**|  | [optional] [default to null] |
 | **x-multi-value-header-param** | [**List**](../Models/String.md)|  | [optional] [default to null] |
@@ -5585,7 +5597,7 @@ No authorization required
 
 | Name | Type | Description | Notes |
 |------------ | ------------- | ------------- | -------------|
-| **message** | **String** |  | [optional] [default to null] |
+| **message** | **String** | This is a message | [optional] [default to null] |
 | **id** | **Integer** |  | [default to null] |
 
 [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/packages/type-safe-api/test/scripts/generators/__snapshots__/java.test.ts.snap b/packages/type-safe-api/test/scripts/generators/__snapshots__/java.test.ts.snap
index cd138506c..9b7abbe7e 100644
--- a/packages/type-safe-api/test/scripts/generators/__snapshots__/java.test.ts.snap
+++ b/packages/type-safe-api/test/scripts/generators/__snapshots__/java.test.ts.snap
@@ -7252,14 +7252,16 @@ paths:
     post:
       operationId: operationOne
       parameters:
-      - explode: true
+      - description: This is parameter 1
+        explode: true
         in: query
         name: param1
         required: true
         schema:
           type: string
         style: form
-      - explode: true
+      - description: This is parameter 2
+        explode: true
         in: query
         name: param2
         required: true
@@ -7289,7 +7291,8 @@ paths:
         schema:
           type: string
         style: simple
-      - explode: false
+      - description: This is a header parameter
+        explode: false
         in: header
         name: x-header-param
         required: true
@@ -7420,11 +7423,13 @@ components:
       - errorMessage
       type: object
     TestRequest:
+      description: This is a test request
       properties:
         myInput:
           type: number
       type: object
     TestResponse:
+      description: This is a test response
       properties:
         messages:
           items:
@@ -7445,6 +7450,7 @@ components:
     TestResponse_messages_inner:
       properties:
         message:
+          description: This is a message
           type: string
         id:
           type: integer
@@ -7809,11 +7815,11 @@ public class Example {
     defaultClient.setBasePath("http://localhost");
 
     DefaultApi apiInstance = new DefaultApi(defaultClient);
-    String param1 = "param1_example"; // String | 
-    List<String> param2 = Arrays.asList(); // List<String> | 
+    String param1 = "param1_example"; // String | This is parameter 1
+    List<String> param2 = Arrays.asList(); // List<String> | This is parameter 2
     BigDecimal param3 = new BigDecimal(78); // BigDecimal | 
     String pathParam = "pathParam_example"; // String | 
-    String xHeaderParam = "xHeaderParam_example"; // String | 
+    String xHeaderParam = "xHeaderParam_example"; // String | This is a header parameter
     TestRequest testRequest = new TestRequest(); // TestRequest | 
     String param4 = "param4_example"; // String | 
     List<String> xMultiValueHeaderParam = Arrays.asList(); // List<String> | 
@@ -7838,11 +7844,11 @@ public class Example {
 
 | Name | Type | Description  | Notes |
 |------------- | ------------- | ------------- | -------------|
-| **param1** | **String**|  | |
-| **param2** | [**List&lt;String&gt;**](String.md)|  | |
+| **param1** | **String**| This is parameter 1 | |
+| **param2** | [**List&lt;String&gt;**](String.md)| This is parameter 2 | |
 | **param3** | **BigDecimal**|  | |
 | **pathParam** | **String**|  | |
-| **xHeaderParam** | **String**|  | |
+| **xHeaderParam** | **String**| This is a header parameter | |
 | **testRequest** | [**TestRequest**](TestRequest.md)|  | |
 | **param4** | **String**|  | [optional] |
 | **xMultiValueHeaderParam** | [**List&lt;String&gt;**](String.md)|  | [optional] |
@@ -7957,6 +7963,7 @@ No authorization required
 
 # TestRequest
 
+This is a test request
 
 ## Properties
 
@@ -7971,6 +7978,7 @@ No authorization required
 
 # TestResponse
 
+This is a test response
 
 ## Properties
 
@@ -7990,7 +7998,7 @@ No authorization required
 
 | Name | Type | Description | Notes |
 |------------ | ------------- | ------------- | -------------|
-|**message** | **String** |  |  [optional] |
+|**message** | **String** | This is a message |  [optional] |
 |**id** | **Integer** |  |  |
 
 
@@ -11811,11 +11819,11 @@ public class DefaultApi {
     /**
      * 
      * 
-     * @param param1  (required)
-     * @param param2  (required)
+     * @param param1 This is parameter 1 (required)
+     * @param param2 This is parameter 2 (required)
      * @param param3  (required)
      * @param pathParam  (required)
-     * @param xHeaderParam  (required)
+     * @param xHeaderParam This is a header parameter (required)
      * @param testRequest  (required)
      * @return APIoperationOneRequest
      * @http.response.details
@@ -16640,7 +16648,7 @@ import java.util.Set;
 import test.test.runtime.JSON;
 
 /**
- * TestRequest
+ * This is a test request
  */
 @lombok.AllArgsConstructor @lombok.experimental.SuperBuilder
 @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
@@ -16847,7 +16855,7 @@ import java.util.Set;
 import test.test.runtime.JSON;
 
 /**
- * TestResponse
+ * This is a test response
  */
 @lombok.AllArgsConstructor @lombok.experimental.SuperBuilder
 @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
@@ -17097,7 +17105,7 @@ public class TestResponseMessagesInner {
   }
 
    /**
-   * Get message
+   * This is a message
    * @return message
   **/
   @javax.annotation.Nullable
diff --git a/packages/type-safe-api/test/scripts/generators/__snapshots__/python.test.ts.snap b/packages/type-safe-api/test/scripts/generators/__snapshots__/python.test.ts.snap
index eeb409f3e..2188d6d0e 100644
--- a/packages/type-safe-api/test/scripts/generators/__snapshots__/python.test.ts.snap
+++ b/packages/type-safe-api/test/scripts/generators/__snapshots__/python.test.ts.snap
@@ -947,7 +947,7 @@ class DefaultApi(object):
   "test_project/api/operation_config.py": "from __future__ import annotations
 import urllib.parse
 import json
-from typing import Callable, Any, Dict, List, NamedTuple, TypeVar, Generic, Union, TypedDict, Protocol, Optional, Literal
+from typing import Callable, Any, Dict, List, NamedTuple, TypeVar, Generic, Union, TypedDict, Protocol, Optional, Literal, Annotated
 from functools import wraps
 from dataclasses import dataclass, fields
 from datetime import datetime
@@ -1171,7 +1171,7 @@ class NeitherRequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> NeitherRequestParameters:
@@ -1284,7 +1284,7 @@ class BothRequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> BothRequestParameters:
@@ -1397,7 +1397,7 @@ class Tag1RequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> Tag1RequestParameters:
@@ -1510,7 +1510,7 @@ class Tag2RequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> Tag2RequestParameters:
@@ -4872,11 +4872,11 @@ configuration = test_project.Configuration(
 with test_project.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = test_project.DefaultApi(api_client)
-    param1 = 'param1_example' # str | 
-    param2 = ['param2_example'] # List[str] | 
+    param1 = 'param1_example' # str | This is parameter 1
+    param2 = ['param2_example'] # List[str] | This is parameter 2
     param3 = 3.4 # float | 
     path_param = 'path_param_example' # str | 
-    x_header_param = 'x_header_param_example' # str | 
+    x_header_param = 'x_header_param_example' # str | This is a header parameter
     test_request = test_project.TestRequest() # TestRequest | 
     param4 = 'param4_example' # str |  (optional)
     x_multi_value_header_param = ['x_multi_value_header_param_example'] # List[str] |  (optional)
@@ -4894,11 +4894,11 @@ with test_project.ApiClient(configuration) as api_client:
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **param1** | **str**|  | 
- **param2** | [**List[str]**](str.md)|  | 
+ **param1** | **str**| This is parameter 1 | 
+ **param2** | [**List[str]**](str.md)| This is parameter 2 | 
  **param3** | **float**|  | 
  **path_param** | **str**|  | 
- **x_header_param** | **str**|  | 
+ **x_header_param** | **str**| This is a header parameter | 
  **test_request** | [**TestRequest**](TestRequest.md)|  | 
  **param4** | **str**|  | [optional] 
  **x_multi_value_header_param** | [**List[str]**](str.md)|  | [optional] 
@@ -5045,6 +5045,7 @@ map_response_map_property_value_form_dict = map_response_map_property_value.from
 ",
   "docs/TestRequest.md": "# TestRequest
 
+This is a test request
 
 ## Properties
 Name | Type | Description | Notes
@@ -5074,6 +5075,7 @@ test_request_form_dict = test_request.from_dict(test_request_dict)
 ",
   "docs/TestResponse.md": "# TestResponse
 
+This is a test response
 
 ## Properties
 Name | Type | Description | Notes
@@ -5107,7 +5109,7 @@ test_response_form_dict = test_response.from_dict(test_response_dict)
 ## Properties
 Name | Type | Description | Notes
 ------------ | ------------- | ------------- | -------------
-**message** | **str** |  | [optional] 
+**message** | **str** | This is a message | [optional] 
 **id** | **int** |  | 
 
 ## Example
@@ -5212,7 +5214,7 @@ import warnings
 from pydantic import validate_arguments, ValidationError
 from typing_extensions import Annotated
 
-from pydantic import StrictBytes, StrictFloat, StrictInt, StrictStr, conlist
+from pydantic import Field, StrictBytes, StrictFloat, StrictInt, StrictStr, conlist
 
 from typing import Any, Optional, Union
 
@@ -5930,7 +5932,7 @@ class DefaultApi(object):
             _request_auth=_params.get('_request_auth'))
 
     @validate_arguments
-    def operation_one(self, param1 : StrictStr, param2 : conlist(StrictStr), param3 : Union[StrictFloat, StrictInt], path_param : StrictStr, x_header_param : StrictStr, test_request : TestRequest, param4 : Optional[StrictStr] = None, x_multi_value_header_param : Optional[conlist(StrictStr)] = None, **kwargs) -> TestResponse:  # noqa: E501
+    def operation_one(self, param1 : Annotated[StrictStr, Field(..., description="This is parameter 1")], param2 : Annotated[conlist(StrictStr), Field(..., description="This is parameter 2")], param3 : Union[StrictFloat, StrictInt], path_param : StrictStr, x_header_param : Annotated[StrictStr, Field(..., description="This is a header parameter")], test_request : TestRequest, param4 : Optional[StrictStr] = None, x_multi_value_header_param : Optional[conlist(StrictStr)] = None, **kwargs) -> TestResponse:  # noqa: E501
         """operation_one  # noqa: E501
 
         This method makes a synchronous HTTP request by default. To make an
@@ -5939,15 +5941,15 @@ class DefaultApi(object):
         >>> thread = api.operation_one(param1, param2, param3, path_param, x_header_param, test_request, param4, x_multi_value_header_param, async_req=True)
         >>> result = thread.get()
 
-        :param param1: (required)
+        :param param1: This is parameter 1 (required)
         :type param1: str
-        :param param2: (required)
+        :param param2: This is parameter 2 (required)
         :type param2: List[str]
         :param param3: (required)
         :type param3: float
         :param path_param: (required)
         :type path_param: str
-        :param x_header_param: (required)
+        :param x_header_param: This is a header parameter (required)
         :type x_header_param: str
         :param test_request: (required)
         :type test_request: TestRequest
@@ -5972,7 +5974,7 @@ class DefaultApi(object):
         return self.operation_one_with_http_info(param1, param2, param3, path_param, x_header_param, test_request, param4, x_multi_value_header_param, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def operation_one_with_http_info(self, param1 : StrictStr, param2 : conlist(StrictStr), param3 : Union[StrictFloat, StrictInt], path_param : StrictStr, x_header_param : StrictStr, test_request : TestRequest, param4 : Optional[StrictStr] = None, x_multi_value_header_param : Optional[conlist(StrictStr)] = None, **kwargs) -> ApiResponse:  # noqa: E501
+    def operation_one_with_http_info(self, param1 : Annotated[StrictStr, Field(..., description="This is parameter 1")], param2 : Annotated[conlist(StrictStr), Field(..., description="This is parameter 2")], param3 : Union[StrictFloat, StrictInt], path_param : StrictStr, x_header_param : Annotated[StrictStr, Field(..., description="This is a header parameter")], test_request : TestRequest, param4 : Optional[StrictStr] = None, x_multi_value_header_param : Optional[conlist(StrictStr)] = None, **kwargs) -> ApiResponse:  # noqa: E501
         """operation_one  # noqa: E501
 
         This method makes a synchronous HTTP request by default. To make an
@@ -5981,15 +5983,15 @@ class DefaultApi(object):
         >>> thread = api.operation_one_with_http_info(param1, param2, param3, path_param, x_header_param, test_request, param4, x_multi_value_header_param, async_req=True)
         >>> result = thread.get()
 
-        :param param1: (required)
+        :param param1: This is parameter 1 (required)
         :type param1: str
-        :param param2: (required)
+        :param param2: This is parameter 2 (required)
         :type param2: List[str]
         :param param3: (required)
         :type param3: float
         :param path_param: (required)
         :type path_param: str
-        :param x_header_param: (required)
+        :param x_header_param: This is a header parameter (required)
         :type x_header_param: str
         :param test_request: (required)
         :type test_request: TestRequest
@@ -6264,7 +6266,7 @@ class DefaultApi(object):
   "test_project/api/operation_config.py": "from __future__ import annotations
 import urllib.parse
 import json
-from typing import Callable, Any, Dict, List, NamedTuple, TypeVar, Generic, Union, TypedDict, Protocol, Optional, Literal
+from typing import Callable, Any, Dict, List, NamedTuple, TypeVar, Generic, Union, TypedDict, Protocol, Optional, Literal, Annotated
 from functools import wraps
 from dataclasses import dataclass, fields
 from datetime import datetime
@@ -6506,7 +6508,7 @@ class AnyRequestResponseRequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> AnyRequestResponseRequestParameters:
@@ -6620,7 +6622,7 @@ class EmptyRequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> EmptyRequestParameters:
@@ -6733,7 +6735,7 @@ class MapResponseRequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> MapResponseRequestParameters:
@@ -6846,7 +6848,7 @@ class MediaTypesRequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> MediaTypesRequestParameters:
@@ -6960,7 +6962,7 @@ class MultipleContentTypesRequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> MultipleContentTypesRequestParameters:
@@ -7060,13 +7062,13 @@ class OperationOneRequestParameters(BaseModel):
     """
     Query, path and header parameters for the OperationOne operation
     """
-    param1: StrictStr = Field(alias='param1')
-    param2: conlist(StrictStr) = Field(alias='param2')
-    param3: Union[StrictFloat, StrictInt] = Field(alias='param3')
-    path_param: StrictStr = Field(alias='pathParam')
-    x_header_param: StrictStr = Field(alias='x-header-param')
-    param4: Optional[StrictStr] = Field(alias='param4', default=None)
-    x_multi_value_header_param: Optional[conlist(StrictStr)] = Field(alias='x-multi-value-header-param', default=None)
+    param1: Annotated[StrictStr, Field(..., description="This is parameter 1")]
+    param2: Annotated[conlist(StrictStr), Field(..., description="This is parameter 2")]
+    param3: Union[StrictFloat, StrictInt]
+    path_param: StrictStr
+    x_header_param: Annotated[StrictStr, Field(..., description="This is a header parameter")]
+    param4: Optional[StrictStr]
+    x_multi_value_header_param: Optional[conlist(StrictStr)]
 
     class Config:
         """Pydantic configuration"""
@@ -7081,7 +7083,7 @@ class OperationOneRequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> OperationOneRequestParameters:
@@ -7207,7 +7209,7 @@ class WithoutOperationIdDeleteRequestParameters(BaseModel):
         return cls.from_dict(json.loads(json_str))
 
     def to_dict(self):
-        return self.dict(by_alias=True, exclude={}, exclude_none=True)
+        return self.dict(exclude={}, exclude_none=True)
 
     @classmethod
     def from_dict(cls, obj: dict) -> WithoutOperationIdDeleteRequestParameters:
@@ -9170,7 +9172,7 @@ from pydantic import BaseModel, Field, StrictFloat, StrictInt
 
 class TestRequest(BaseModel):
     """
-    TestRequest
+    This is a test request
     """
     my_input: Optional[Union[StrictFloat, StrictInt]] = Field(None, alias="myInput")
     __properties = ["myInput"]
@@ -9242,7 +9244,7 @@ from test_project.models.test_response_messages_inner import TestResponseMessage
 
 class TestResponse(BaseModel):
     """
-    TestResponse
+    This is a test response
     """
     messages: conlist(TestResponseMessagesInner) = Field(...)
     __properties = ["messages"]
@@ -9322,7 +9324,7 @@ class TestResponseMessagesInner(BaseModel):
     """
     TestResponseMessagesInner
     """
-    message: Optional[StrictStr] = None
+    message: Optional[StrictStr] = Field(None, description="This is a message")
     id: StrictInt = Field(...)
     __properties = ["message", "id"]
 
diff --git a/packages/type-safe-api/test/scripts/generators/__snapshots__/typescript.test.ts.snap b/packages/type-safe-api/test/scripts/generators/__snapshots__/typescript.test.ts.snap
index f0bacf6b4..33968ff2c 100644
--- a/packages/type-safe-api/test/scripts/generators/__snapshots__/typescript.test.ts.snap
+++ b/packages/type-safe-api/test/scripts/generators/__snapshots__/typescript.test.ts.snap
@@ -3818,7 +3818,7 @@ export function MapResponseMapPropertyValueToJSON(value?: MapResponseMapProperty
 
 import { exists, mapValues } from '../runtime';
 /**
- * 
+ * This is a test request
  * @export
  * @interface TestRequest
  */
@@ -3892,7 +3892,7 @@ import {
 } from './TestResponseMessagesInner';
 
 /**
- * 
+ * This is a test response
  * @export
  * @interface TestResponse
  */
@@ -3966,7 +3966,7 @@ import { exists, mapValues } from '../runtime';
  */
 export interface TestResponseMessagesInner {
     /**
-     * 
+     * This is a message
      * @type {string}
      * @memberof TestResponseMessagesInner
      */