diff --git a/CHANGELOG.md b/CHANGELOG.md index d02c06c805..958fa5fce4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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) - Fixes mapping of `int16` format to the `integer` type rather than `double` when the type is `integer` or `number` [#5611](https://github.com/microsoft/kiota/issues/5611) +- Fixes typing inconsistencies in generated code and libraries in Python [kiota-python#333](https://github.com/microsoft/kiota-python/issues/333) ## [1.19.1] - 2024-10-11 @@ -1484,5 +1485,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Initial GitHub release - - diff --git a/it/python/requirements-dev.txt b/it/python/requirements-dev.txt index f2f0f4d1af..6fb3dcedde 100644 --- a/it/python/requirements-dev.txt +++ b/it/python/requirements-dev.txt @@ -98,19 +98,19 @@ httpx[http2]==0.27.2 hyperframe==6.0.1 ; python_full_version >= '3.6.1' -microsoft-kiota-abstractions==1.3.3 +microsoft-kiota-abstractions==1.4.6 -microsoft-kiota-authentication-azure==1.1.0 +microsoft-kiota-authentication-azure==1.4.6 -microsoft-kiota-http==1.3.4 +microsoft-kiota-http==1.4.6 -microsoft-kiota-serialization-json==1.3.3 +microsoft-kiota-serialization-json==1.4.6 -microsoft-kiota-serialization-text==1.0.0 +microsoft-kiota-serialization-text==1.4.6 -microsoft-kiota-serialization-form==0.1.1 +microsoft-kiota-serialization-form==1.4.6 -microsoft-kiota-serialization-multipart==0.1.0 +microsoft-kiota-serialization-multipart==1.4.6 msal==1.31.0 diff --git a/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs index 46b4877ce8..f9d19b388c 100644 --- a/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs @@ -22,6 +22,7 @@ public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter wri if (codeElement.Parent is not CodeClass parentClass) throw new InvalidOperationException("the parent of a method should be a class"); var returnType = conventions.GetTypeString(codeElement.ReturnType, codeElement, true, writer); + var returnTypeIsEnum = codeElement.ReturnType is CodeType { TypeDefinition: CodeEnum }; var isVoid = NoneKeyword.Equals(returnType, StringComparison.OrdinalIgnoreCase); if (parentClass.IsOfKind(CodeClassKind.Model) && (codeElement.IsOfKind(CodeMethodKind.Setter) || codeElement.IsOfKind(CodeMethodKind.Getter) || codeElement.IsOfKind(CodeMethodKind.Constructor))) { @@ -79,7 +80,7 @@ public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter wri writer.CloseBlock(string.Empty); break; case CodeMethodKind.RequestExecutor: - WriteRequestExecutorBody(codeElement, requestParams, parentClass, isVoid, returnType, writer); + WriteRequestExecutorBody(codeElement, requestParams, parentClass, isVoid, returnType, writer, returnTypeIsEnum); writer.CloseBlock(string.Empty); break; case CodeMethodKind.Getter: @@ -212,9 +213,10 @@ private void WriteFactoryMethodBody(CodeMethod codeElement, CodeClass parentClas if (parentClass.DiscriminatorInformation.ShouldWriteParseNodeCheck && !parentClass.DiscriminatorInformation.ShouldWriteDiscriminatorForIntersectionType) { writer.StartBlock("try:"); - writer.WriteLine($"{DiscriminatorMappingVarName} = {parseNodeParameter.Name}.get_child_node(\"{parentClass.DiscriminatorInformation.DiscriminatorPropertyName}\").get_str_value()"); + writer.WriteLine($"child_node = {parseNodeParameter.Name}.get_child_node(\"{parentClass.DiscriminatorInformation.DiscriminatorPropertyName}\")"); + writer.WriteLine($"{DiscriminatorMappingVarName} = child_node.get_str_value() if child_node else {NoneKeyword}"); writer.DecreaseIndent(); - writer.StartBlock($"except AttributeError:"); + writer.StartBlock("except AttributeError:"); writer.WriteLine($"{DiscriminatorMappingVarName} = {NoneKeyword}"); writer.DecreaseIndent(); } @@ -527,11 +529,12 @@ private void WriteDeserializerBodyForIntersectionModel(CodeClass parentClass, La .OrderBy(static x => x) .ToArray(); var propertiesNamesAsConditions = propertiesNames - .Select(static x => $"{x}") - .Aggregate(static (x, y) => $"self.{x} or self.{y}"); + .Select(static x => $"self.{x}") + .Aggregate(static (x, y) => $"{x} or {y}"); writer.StartBlock($"if {propertiesNamesAsConditions}:"); var propertiesNamesAsArgument = propertiesNames - .Aggregate(static (x, y) => $"self.{x}, self.{y}"); + .Select(static x => $"self.{x}") + .Aggregate(static (x, y) => $"{x}, {y}"); writer.WriteLine($"return ParseNodeHelper.merge_deserializers_for_intersection_wrapper({propertiesNamesAsArgument})"); writer.DecreaseIndent(); } @@ -556,7 +559,8 @@ private void WriteDeserializerBodyForInheritedModel(bool inherits, CodeMethod co } writer.WriteLine("return fields"); } - private void WriteRequestExecutorBody(CodeMethod codeElement, RequestParams requestParams, CodeClass parentClass, bool isVoid, string returnType, LanguageWriter writer) + private void WriteRequestExecutorBody(CodeMethod codeElement, RequestParams requestParams, CodeClass parentClass, + bool isVoid, string returnType, LanguageWriter writer, bool isEnum) { if (codeElement.HttpMethod == null) throw new InvalidOperationException("http method cannot be null"); @@ -578,8 +582,8 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, RequestParams requ writer.WriteLine(")"); var isStream = conventions.StreamTypeName.Equals(returnType, StringComparison.OrdinalIgnoreCase); var returnTypeWithoutCollectionSymbol = GetReturnTypeWithoutCollectionSymbol(codeElement, returnType); - var genericTypeForSendMethod = GetSendRequestMethodName(isVoid, isStream, codeElement.ReturnType.IsCollection, returnTypeWithoutCollectionSymbol); - var newFactoryParameter = GetTypeFactory(isVoid, isStream, returnTypeWithoutCollectionSymbol); + var genericTypeForSendMethod = GetSendRequestMethodName(isVoid, isStream, codeElement.ReturnType.IsCollection, returnTypeWithoutCollectionSymbol, isEnum); + var newFactoryParameter = GetTypeFactory(isVoid, isStream, returnTypeWithoutCollectionSymbol, isEnum); var errorMappingVarName = NoneKeyword; if (codeElement.ErrorMappings.Any()) { @@ -695,7 +699,8 @@ private void WriteSerializerBodyForIntersectionModel(CodeClass parentClass, Lang var propertiesNames = complexProperties .Select(static x => x.Name) .OrderBy(static x => x, StringComparer.OrdinalIgnoreCase) - .Aggregate(static (x, y) => $"self.{x}, self.{y}"); + .Select(static x => $"self.{x}") + .Aggregate(static (x, y) => $"{x}, {y}"); writer.WriteLine($"writer.{GetSerializationMethodName(complexProperties[0].Type)}({NoneKeyword}, {propertiesNames})"); if (includeElse) { @@ -803,22 +808,23 @@ private string GetSerializationMethodName(CodeTypeBase propType) _ => "write_object_value", }; } - private string GetTypeFactory(bool isVoid, bool isStream, string returnType) + private string GetTypeFactory(bool isVoid, bool isStream, string returnType, bool isEnum) { if (isVoid) return string.Empty; - if (isStream || conventions.IsPrimitiveType(returnType)) return $" \"{returnType}\","; + if (isStream || conventions.IsPrimitiveType(returnType) || isEnum) return $" \"{returnType}\","; return $" {returnType},"; } - private string GetSendRequestMethodName(bool isVoid, bool isStream, bool isCollection, string returnType) + private string GetSendRequestMethodName(bool isVoid, bool isStream, bool isCollection, string returnType, + bool isEnum) { if (isVoid) return "send_no_response_content_async"; if (isCollection) { - if (conventions.IsPrimitiveType(returnType)) return "send_collection_of_primitive_async"; - return $"send_collection_async"; + if (conventions.IsPrimitiveType(returnType) || isEnum) return "send_collection_of_primitive_async"; + return "send_collection_async"; } - if (isStream || conventions.IsPrimitiveType(returnType)) return "send_primitive_async"; + if (isStream || conventions.IsPrimitiveType(returnType) || isEnum) return "send_primitive_async"; return "send_async"; } private void UpdateRequestInformationFromRequestBody(CodeMethod codeElement, RequestParams requestParams, CodeProperty requestAdapterProperty, LanguageWriter writer) diff --git a/src/Kiota.Builder/Writers/Python/CodePropertyWriter.cs b/src/Kiota.Builder/Writers/Python/CodePropertyWriter.cs index 7439f123bf..d2e9e5a0d1 100644 --- a/src/Kiota.Builder/Writers/Python/CodePropertyWriter.cs +++ b/src/Kiota.Builder/Writers/Python/CodePropertyWriter.cs @@ -45,7 +45,7 @@ public override void WriteCodeElement(CodeProperty codeElement, LanguageWriter w break; case CodePropertyKind.ErrorMessageOverride when parentClass.IsErrorDefinition: writer.WriteLine("@property"); - writer.StartBlock($"def {codeElement.Name}(self) -> {codeElement.Type.Name}:"); + writer.StartBlock($"def {codeElement.Name}(self) -> Optional[{codeElement.Type.Name}]:"); conventions.WriteLongDescription(codeElement, writer); if (parentClass.GetPrimaryMessageCodePath(static x => x.Name.ToFirstCharacterLowerCase(), static x => x.Name.ToSnakeCase()) is string primaryMessageCodePath && diff --git a/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs index f9142d48c2..b1ac6b73c2 100644 --- a/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs @@ -1159,7 +1159,8 @@ public void WritesModelFactoryBodyForInheritedModels() writer.Write(method); var result = tw.ToString(); Assert.Contains("try:", result); - Assert.Contains("mapping_value = parse_node.get_child_node(\"@odata.type\").get_str_value()", result); + Assert.Contains("child_node = parse_node.get_child_node(\"@odata.type\")", result); + Assert.Contains("mapping_value = child_node.get_str_value() if child_node else None", result); Assert.Contains("except AttributeError:", result); Assert.Contains("mapping_value = None", result); Assert.Contains("if mapping_value and mapping_value.casefold() == \"ns.childclass\".casefold()", result); @@ -1194,7 +1195,8 @@ public void WritesModelFactoryBodyForUnionModels() writer.Write(factoryMethod); var result = tw.ToString(); Assert.Contains("try:", result); - Assert.Contains("mapping_value = parse_node.get_child_node(\"@odata.type\").get_str_value()", result); + Assert.Contains("child_node = parse_node.get_child_node(\"@odata.type\")", result); + Assert.Contains("mapping_value = child_node.get_str_value() if child_node else None", result); Assert.Contains("except AttributeError:", result); Assert.Contains("mapping_value = None", result); Assert.Contains("result = UnionTypeWrapper()", result);