From bcb993fd5c98f524f588b64e48a4c1e466cea416 Mon Sep 17 00:00:00 2001 From: jonathan343 Date: Fri, 24 Jul 2026 00:49:06 -0400 Subject: [PATCH 1/2] fix: handle explicit null member defaults for enums and intEnums --- .../src/it/resources/META-INF/smithy/main.smithy | 12 ++++++++++++ .../codegen/generators/StructureGenerator.java | 10 +++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/codegen/core/src/it/resources/META-INF/smithy/main.smithy b/codegen/core/src/it/resources/META-INF/smithy/main.smithy index 3d7ab539c..27d0c4770 100644 --- a/codegen/core/src/it/resources/META-INF/smithy/main.smithy +++ b/codegen/core/src/it/resources/META-INF/smithy/main.smithy @@ -381,6 +381,8 @@ structure Defaults { @required requiredDefaultBlob: Blob = "c3BhbQ==" + defaultNullBlob: Blob = null + // timestamp @required requiredTimestamp: Timestamp @@ -400,6 +402,8 @@ structure Defaults { @required requiredDefaultTimestamp: Timestamp = 4.2 + defaultNullTimestamp: Timestamp = null + @required requiredList: StringList @@ -420,6 +424,14 @@ structure Defaults { @required requiredDefaultMap: StringMap = {} + defaultEnum: StringYesNo = "YES" + + defaultNullEnum: StringYesNo = null + + defaultIntEnum: IntYesNo = 1 + + defaultNullIntEnum: IntYesNo = null + @required requiredDocument: Document diff --git a/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/StructureGenerator.java b/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/StructureGenerator.java index ee29f296e..7a5ecfdf7 100644 --- a/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/StructureGenerator.java +++ b/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/StructureGenerator.java @@ -288,6 +288,14 @@ private String getDefaultValue(PythonWriter writer, MemberShape member) { // see: https://smithy.io/2.0/spec/type-refinement-traits.html#smithy-api-default-trait var defaultNode = member.expectTrait(DefaultTrait.class).toNode(); var target = model.expectShape(member.getTarget()); + // A member may override its target's default with an explicit null to mark + // itself nullable, in which case it resolves to None. This guard covers every + // non-document type in one place so each branch below can assume a typed value. + // Documents are excluded: a null document default is a non-None Document(None), + // built by the document branch below. + if (!target.isDocumentShape() && defaultNode.isNullNode()) { + return "None"; + } if (target.isTimestampShape()) { ZonedDateTime value = CodegenUtils.parseTimestampNode(model, member, defaultNode); return CodegenUtils.getDatetimeConstructor(writer, value); @@ -318,8 +326,8 @@ private String getDefaultValue(PythonWriter writer, MemberShape member) { }); } + // A null default is handled by the guard above, so it can't reach here. return switch (defaultNode.getType()) { - case NULL -> "None"; case BOOLEAN -> defaultNode.expectBooleanNode().getValue() ? "True" : "False"; // These will be given to a default_factory in field. They're inherently empty, so no need to // worry about any potential values. From 1195d5b7a12a9b02f621ffdc893cad8d99deec0c Mon Sep 17 00:00:00 2001 From: jonathan343 Date: Fri, 24 Jul 2026 01:03:24 -0400 Subject: [PATCH 2/2] simplify code comment --- .../python/codegen/generators/StructureGenerator.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/StructureGenerator.java b/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/StructureGenerator.java index 7a5ecfdf7..3b1cffae1 100644 --- a/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/StructureGenerator.java +++ b/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/StructureGenerator.java @@ -288,11 +288,8 @@ private String getDefaultValue(PythonWriter writer, MemberShape member) { // see: https://smithy.io/2.0/spec/type-refinement-traits.html#smithy-api-default-trait var defaultNode = member.expectTrait(DefaultTrait.class).toNode(); var target = model.expectShape(member.getTarget()); - // A member may override its target's default with an explicit null to mark - // itself nullable, in which case it resolves to None. This guard covers every - // non-document type in one place so each branch below can assume a typed value. - // Documents are excluded: a null document default is a non-None Document(None), - // built by the document branch below. + // A null default marks the member nullable and resolves to None. Documents are + // excluded since their null default is a non-None Document(None) (see the branch below). if (!target.isDocumentShape() && defaultNode.isNullNode()) { return "None"; }