Repository: microsoft/kiota (csharp)

Issue:
Incorrect primitive_type in generated code causes "Encountered an unknown type during deserialization str"
### What are you generating using Kiota, clients or plugins?

API Client/SDK

### In what context or format are you using Kiota?

Linux executable

### Client library/SDK language

Python

### Describe the bug

When I use the versions below of Kiota the following error occurs:

`Exception: Encountered an unknown type during deserialization str`

I think that the bug is due to send_collection_of_primitive_async passing argument `primitive_type` as `str` instead of `<class type[str]>` and located here: https://github.com/microsoft/kiota/blob/main/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs#L808

  "microsoft-kiota-abstractions==1.3.3",
  "microsoft-kiota-http==1.3.3",
  "microsoft-kiota-serialization-json==1.3.2",
  "microsoft-kiota-serialization-text==1.0.0",
  "microsoft-kiota-serialization-form==0.1.1",
  "microsoft-kiota-serialization-multipart==0.1.0",

### Expected behavior

The get method should return a list of strings (names).

### How to reproduce

Have Kiota generate a python code for an endpoint that returns a JSON collection of string (python equivalent: List[str]).


### Open API description file

```json
        "/names": {
            "get": {
                "summary": "Get names",
                "operationId": "getNames",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "uniqueItems": true,
                                    "type": "array",
                                    "items": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },

```

### Kiota Version

1.18.0+5c6b5d0ef23865ba2f9d9f0b9fe4b944cf26b1ec

### Latest Kiota version known to work for scenario above?(Not required)

_No response_

### Known Workarounds

Manually edited the generated code and replace `"str"` with `str`.

### Configuration

- OS: Ubuntu

Can't see that it is specific to this configuration.

### Debug output

### Other information

The generated `get method` for the endpoint seems to be incorrect (`"str"` instead of `str`):

`return await self.request_adapter.send_collection_of_primitive_async(request_info, "str", None)`

Which will cause the  `if generic_type in primitive_types:` in JsonParseNode.get_collection_of_primitive_values  to be False

since  "str"  is _NOT_ in primitive_types due it being an actual string (and not str, i.e. a <class type>).

Example:

```
>>> types = {bool, str, int, float, bytes}
>>> type(types)
<class 'set'>
>>> str in types
True 
>>> 'str' in types
False
```

```
    def get_collection_of_primitive_values(self, primitive_type: Any) -> Optional[List[T]]:
        """Gets the collection of primitive values of the node
        Returns:
            List[T]: The collection of primitive values
        """

        primitive_types = {bool, str, int, float, UUID, datetime, timedelta, date, time, bytes}

        def func(item):
            generic_type = primitive_type if primitive_type else type(item)
            current_parse_node = self._create_new_node(item)
            if generic_type in primitive_types:
                method = getattr(current_parse_node, f'get_{generic_type.__name__.lower()}_value')
                return method()
            raise Exception(f"Encountered an unknown type during deserialization {generic_type}")

        if isinstance(self._json_node, str):
            return list(map(func, json.loads(self._json_node)))
        return list(map(func, list(self._json_node)))

```

Pull request description:
Fixes https://github.com/microsoft/kiota/issues/5417


From
```python
async def get(self,request_configuration: Optional[RequestConfiguration[QueryParameters]] = None) -> Optional[List[str]]:
        """
        Get names
        param request_configuration: Configuration for the request such as headers, query parameters, and middleware options.
        Returns: Optional[List[str]]
        """
        request_info = self.to_get_request_information(
            request_configuration
        )
        if not self.request_adapter:
            raise Exception("Http core is null") 
        return await self.request_adapter.send_collection_of_primitive_async(request_info, "str", None)

```

To
```python
async def get(self,request_configuration: Optional[RequestConfiguration[QueryParameters]] = None) -> Optional[List[str]]:
        """
        Get names
        param request_configuration: Configuration for the request such as headers, query parameters, and middleware options.
        Returns: Optional[List[str]]
        """
        request_info = self.to_get_request_information(
            request_configuration
        )
        if not self.request_adapter:
            raise Exception("Http core is null") 
        return await self.request_adapter.send_collection_of_primitive_async(request_info, str, None)
```

Note - the param type was fixed in an earlier PR for a related issue in September

Patch:
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 6e77c8004f..f4bcd561b3 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -196,7 +196,10 @@
       "request": "launch",
       "preLaunchTask": "build",
       "program": "${workspaceFolder}/src/kiota/bin/Debug/net8.0/kiota.dll",
-      "args": ["search", "microsoft"],
+      "args": [
+        "search",
+        "microsoft"
+      ],
       "cwd": "${workspaceFolder}/src/kiota",
       "console": "internalConsole",
       "stopAtEntry": false
@@ -207,7 +210,10 @@
       "request": "launch",
       "preLaunchTask": "build",
       "program": "${workspaceFolder}/src/kiota/bin/Debug/net8.0/kiota.dll",
-      "args": ["search", "test"],
+      "args": [
+        "search",
+        "test"
+      ],
       "cwd": "${workspaceFolder}/src/kiota",
       "console": "internalConsole",
       "stopAtEntry": false
@@ -249,7 +255,11 @@
       "request": "launch",
       "preLaunchTask": "build",
       "program": "${workspaceFolder}/src/kiota/bin/Debug/net8.0/kiota.dll",
-      "args": ["info", "-l", "CSharp"],
+      "args": [
+        "info",
+        "-l",
+        "CSharp"
+      ],
       "cwd": "${workspaceFolder}/src/kiota",
       "console": "internalConsole",
       "stopAtEntry": false
@@ -260,7 +270,11 @@
       "request": "launch",
       "preLaunchTask": "build",
       "program": "${workspaceFolder}/src/kiota/bin/Debug/net8.0/kiota.dll",
-      "args": ["update", "-o", "${workspaceFolder}/samples"],
+      "args": [
+        "update",
+        "-o",
+        "${workspaceFolder}/samples"
+      ],
       "cwd": "${workspaceFolder}/src/kiota",
       "console": "internalConsole",
       "stopAtEntry": false
@@ -271,7 +285,10 @@
       "request": "launch",
       "preLaunchTask": "build",
       "program": "${workspaceFolder}/src/kiota/bin/Debug/net8.0/kiota.dll",
-      "args": ["workspace", "migrate"],
+      "args": [
+        "workspace",
+        "migrate"
+      ],
       "cwd": "${workspaceFolder}/samples/msgraph-mail/dotnet",
       "console": "internalConsole",
       "stopAtEntry": false,
@@ -285,7 +302,10 @@
       "request": "launch",
       "preLaunchTask": "build",
       "program": "${workspaceFolder}/src/kiota/bin/Debug/net8.0/kiota.dll",
-      "args": ["client", "generate"],
+      "args": [
+        "client",
+        "generate"
+      ],
       "cwd": "${workspaceFolder}/samples/msgraph-mail/dotnet",
       "console": "internalConsole",
       "stopAtEntry": false,
@@ -349,7 +369,11 @@
       "request": "launch",
       "preLaunchTask": "build",
       "program": "${workspaceFolder}/src/kiota/bin/Debug/net8.0/kiota.dll",
-      "args": ["login", "github", "device"],
+      "args": [
+        "login",
+        "github",
+        "device"
+      ],
       "cwd": "${workspaceFolder}/src/kiota",
       "console": "internalConsole",
       "stopAtEntry": false
@@ -361,4 +385,4 @@
       "processId": "${command:pickProcess}"
     }
   ]
-}
+}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7327f1b128..171110e1f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Added
 
 ### Changed
+- Fixed python generation client serailization failure str being quoted as "str"
+- Fixed Issue with primitive values being stringified in python python. [#5417](https://github.com/microsoft/kiota/issues/5417)
 
 - Fixed an issue where multipart request content would be ignored if other unstructured content was present in the description. [#5638](https://github.com/microsoft/kiota/issues/5638)
 - Fixed an issue where when generating Go code the deserializer for unions was using `CodeClass` as a filter and not `CodeInterface`. [#4844](https://github.com/microsoft/kiota/issues/4844)
@@ -32,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Fixed cyclic dependencies in generated Go code. [#2834](https://github.com/microsoft/kiota/issues/2834)
 - Fixed a bug where default output folder is created on plugin edit and generate commands. [#5510](https://github.com/microsoft/kiota/issues/5429)
 - Changed GeneratedCode attribute applied when generating CSharp to only include the major version of Kiota. [#5489](https://github.com/microsoft/kiota/issues/5489)
+
 - Fixed generating CSharp client displays clean hint regardless of whether --clean-output is already passed [#5576](https://github.com/microsoft/kiota/issues/5576)
 
 ## [1.19.0] - 2024-10-03
diff --git a/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs
index 4cf7b7fc80..3b391cdb8f 100644
--- a/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs
+++ b/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs
@@ -583,7 +583,7 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, RequestParams requ
         var isStream = conventions.StreamTypeName.Equals(returnType, StringComparison.OrdinalIgnoreCase);
         var returnTypeWithoutCollectionSymbol = GetReturnTypeWithoutCollectionSymbol(codeElement, returnType);
         var genericTypeForSendMethod = GetSendRequestMethodName(isVoid, isStream, codeElement.ReturnType.IsCollection, returnTypeWithoutCollectionSymbol, isEnum);
-        var newFactoryParameter = GetTypeFactory(isVoid, isStream, returnTypeWithoutCollectionSymbol, isEnum);
+        var newFactoryParameter = GetTypeFactory(isVoid, isStream, isEnum, returnTypeWithoutCollectionSymbol);
         var errorMappingVarName = NoneKeyword;
         if (codeElement.ErrorMappings.Any())
         {
@@ -809,10 +809,11 @@ private string GetSerializationMethodName(CodeTypeBase propType)
             _ => "write_object_value",
         };
     }
-    private string GetTypeFactory(bool isVoid, bool isStream, string returnType, bool isEnum)
+    internal string GetTypeFactory(bool isVoid, bool isStream, bool isEnum, string returnType)
     {
         if (isVoid) return string.Empty;
-        if (isStream || conventions.IsPrimitiveType(returnType) || isEnum) return $" \"{returnType}\",";
+        if (isStream || isEnum) return $" \"{returnType}\",";
+        if (conventions.IsPrimitiveType(returnType)) return $" {returnType},";
         return $" {returnType},";
     }
     private string GetSendRequestMethodName(bool isVoid, bool isStream, bool isCollection, string returnType,


Test patch:
diff --git a/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs
index b1ac6b73c2..ae6d75a3bc 100644
--- a/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs
@@ -1,11 +1,11 @@
 ﻿using System;
 using System.IO;
 using System.Linq;
-
 using Kiota.Builder.CodeDOM;
 using Kiota.Builder.Extensions;
 using Kiota.Builder.Writers;
 using Kiota.Builder.Writers.Python;
+using Moq;
 using Xunit;
 
 namespace Kiota.Builder.Tests.Writers.Python;
@@ -25,12 +25,15 @@ public sealed class CodeMethodWriterTests : IDisposable
     private const string MethodDescription = "some description";
     private const string ParamDescription = "some parameter description";
     private const string ParamName = "param_name";
+
+
     public CodeMethodWriterTests()
     {
         writer = LanguageWriter.GetLanguageWriter(GenerationLanguage.Python, DefaultPath, DefaultName);
         tw = new StringWriter();
         writer.SetTextWriter(tw);
         root = CodeNamespace.InitRootNamespace();
+
     }
     private void setup(bool withInheritance = false)
     {
@@ -791,6 +794,7 @@ public void WritesInheritedDeSerializerBody()
         Assert.Contains("return fields", result);
         Assert.DoesNotContain("defined_in_parent", result, StringComparison.OrdinalIgnoreCase);
     }
+
     [Fact]
     public void WritesUnionDeSerializerBody()
     {
@@ -815,6 +819,27 @@ public void WritesUnionDeSerializerBody()
         Assert.Contains("return self.complex_type1_value.get_field_deserializers()", result);
         Assert.Contains("return {}", result);
     }
+    [Theory]
+    [InlineData(true, false, false, "string", "")]
+    [InlineData(false, true, false, "Stream", " \"Stream\",")]
+    [InlineData(false, false, true, "SomeEnum", " \"SomeEnum\",")]
+    [InlineData(false, false, false, "int", " int,")]
+    [InlineData(false, false, false, "CustomType", " CustomType,")]
+    public void GetTypeFactory_ReturnsCorrectString(bool isVoid, bool isStream, bool isEnum, string returnType, string expected)
+    {
+        var mockConventionService = new Mock<PythonConventionService>();
+
+        var codeMethodWriter = new CodeMethodWriter(
+            mockConventionService.Object,
+            "TestNamespace",
+            false // usesBackingStore
+        );
+
+        var result = codeMethodWriter.GetTypeFactory(isVoid, isStream, isEnum, returnType);
+
+
+        Assert.Equal(expected, result);
+    }
     [Fact]
     public void WritesIntersectionDeSerializerBody()
     {