diff --git a/codegen-output/aws-json-1-0/README.md b/codegen-output/aws-json-1-0/README.md index 306705d96..19ea5f3c1 100644 --- a/codegen-output/aws-json-1-0/README.md +++ b/codegen-output/aws-json-1-0/README.md @@ -2,4 +2,4 @@ ## Sample Json 1.0 Protocol Service Client -awsjson10 client +Python client for Sample Json 1.0 Protocol Service diff --git a/codegen-output/aws-json-1-0/pyproject.toml b/codegen-output/aws-json-1-0/pyproject.toml index 8b07cfc29..a9b4f5b94 100644 --- a/codegen-output/aws-json-1-0/pyproject.toml +++ b/codegen-output/aws-json-1-0/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "awsjson10" version = "0.0.1" -description = "awsjson10 client" +description = "Python client for Sample Json 1.0 Protocol Service" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "awsjson10"] diff --git a/codegen-output/aws-json-1-1/README.md b/codegen-output/aws-json-1-1/README.md index a811f30ed..984d1fbde 100644 --- a/codegen-output/aws-json-1-1/README.md +++ b/codegen-output/aws-json-1-1/README.md @@ -2,4 +2,4 @@ ## Sample Json 1.1 Protocol Service Client -awsjson11 client +Python client for Sample Json 1.1 Protocol Service diff --git a/codegen-output/aws-json-1-1/pyproject.toml b/codegen-output/aws-json-1-1/pyproject.toml index 921eedbcd..c6f588ad9 100644 --- a/codegen-output/aws-json-1-1/pyproject.toml +++ b/codegen-output/aws-json-1-1/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "awsjson11" version = "0.0.1" -description = "awsjson11 client" +description = "Python client for Sample Json 1.1 Protocol Service" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "awsjson11"] diff --git a/codegen-output/aws-query/README.md b/codegen-output/aws-query/README.md index 9e5d7edaa..fdd59c80f 100644 --- a/codegen-output/aws-query/README.md +++ b/codegen-output/aws-query/README.md @@ -2,7 +2,7 @@ ## Sample Query Protocol Service Client -awsquery client +Python client for Sample Query Protocol Service ### Documentation diff --git a/codegen-output/aws-query/pyproject.toml b/codegen-output/aws-query/pyproject.toml index 289f33685..eade7c2a8 100644 --- a/codegen-output/aws-query/pyproject.toml +++ b/codegen-output/aws-query/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "awsquery" version = "0.0.1" -description = "awsquery client" +description = "Python client for Sample Query Protocol Service" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "awsquery"] diff --git a/codegen-output/ec2-query/README.md b/codegen-output/ec2-query/README.md index 05c376cf8..c24b4b691 100644 --- a/codegen-output/ec2-query/README.md +++ b/codegen-output/ec2-query/README.md @@ -2,7 +2,7 @@ ## Sample Ec2 Protocol Service Client -ec2query client +Python client for Sample Ec2 Protocol Service ### Documentation diff --git a/codegen-output/ec2-query/pyproject.toml b/codegen-output/ec2-query/pyproject.toml index 1fb477a90..4b6ce3a64 100644 --- a/codegen-output/ec2-query/pyproject.toml +++ b/codegen-output/ec2-query/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "ec2query" version = "0.0.1" -description = "ec2query client" +description = "Python client for Sample Ec2 Protocol Service" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "ec2query"] diff --git a/codegen-output/my-handwritten-model/README.md b/codegen-output/my-handwritten-model/README.md index cc10b198b..a7227557a 100644 --- a/codegen-output/my-handwritten-model/README.md +++ b/codegen-output/my-handwritten-model/README.md @@ -2,4 +2,4 @@ ## My Handwritten Model Client -my_handwritten_model client +Python client for My Handwritten Model diff --git a/codegen-output/my-handwritten-model/pyproject.toml b/codegen-output/my-handwritten-model/pyproject.toml index f1c5fd4fe..e58cf27f1 100644 --- a/codegen-output/my-handwritten-model/pyproject.toml +++ b/codegen-output/my-handwritten-model/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "my_handwritten_model" version = "0.0.1" -description = "my_handwritten_model client" +description = "Python client for My Handwritten Model" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "my_handwritten_model"] diff --git a/codegen-output/non-query-compatible-rpcv2-cbor/README.md b/codegen-output/non-query-compatible-rpcv2-cbor/README.md index 93029c3f8..7b955d6a8 100644 --- a/codegen-output/non-query-compatible-rpcv2-cbor/README.md +++ b/codegen-output/non-query-compatible-rpcv2-cbor/README.md @@ -2,4 +2,4 @@ ## Non Query Compatible RpcV2 Protocol Service Client -nonquerycompatiblerpcv2cbor client +Python client for Non Query Compatible RpcV2 Protocol Service diff --git a/codegen-output/non-query-compatible-rpcv2-cbor/pyproject.toml b/codegen-output/non-query-compatible-rpcv2-cbor/pyproject.toml index 1b286f1cd..5937a8056 100644 --- a/codegen-output/non-query-compatible-rpcv2-cbor/pyproject.toml +++ b/codegen-output/non-query-compatible-rpcv2-cbor/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "nonquerycompatiblerpcv2cbor" version = "0.0.1" -description = "nonquerycompatiblerpcv2cbor client" +description = "Python client for Non Query Compatible RpcV2 Protocol Service" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "nonquerycompatiblerpcv2cbor"] diff --git a/codegen-output/query-compatible-aws-json-1-0/README.md b/codegen-output/query-compatible-aws-json-1-0/README.md index 540af86e5..2f8ba8249 100644 --- a/codegen-output/query-compatible-aws-json-1-0/README.md +++ b/codegen-output/query-compatible-aws-json-1-0/README.md @@ -2,4 +2,4 @@ ## Query Compatible Json 1.0 Protocol Service Client -querycompatibleawsjson10 client +Python client for Query Compatible Json 1.0 Protocol Service diff --git a/codegen-output/query-compatible-aws-json-1-0/pyproject.toml b/codegen-output/query-compatible-aws-json-1-0/pyproject.toml index 1d942bfdc..0fdccd779 100644 --- a/codegen-output/query-compatible-aws-json-1-0/pyproject.toml +++ b/codegen-output/query-compatible-aws-json-1-0/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "querycompatibleawsjson10" version = "0.0.1" -description = "querycompatibleawsjson10 client" +description = "Python client for Query Compatible Json 1.0 Protocol Service" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "querycompatibleawsjson10"] diff --git a/codegen-output/query-compatible-rpcv2-cbor/README.md b/codegen-output/query-compatible-rpcv2-cbor/README.md index e35424ce9..5928f1851 100644 --- a/codegen-output/query-compatible-rpcv2-cbor/README.md +++ b/codegen-output/query-compatible-rpcv2-cbor/README.md @@ -2,4 +2,4 @@ ## Query Compatible RpcV2 Protocol Service Client -querycompatiblerpcv2cbor client +Python client for Query Compatible RpcV2 Protocol Service diff --git a/codegen-output/query-compatible-rpcv2-cbor/pyproject.toml b/codegen-output/query-compatible-rpcv2-cbor/pyproject.toml index b26f4075c..8be942985 100644 --- a/codegen-output/query-compatible-rpcv2-cbor/pyproject.toml +++ b/codegen-output/query-compatible-rpcv2-cbor/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "querycompatiblerpcv2cbor" version = "0.0.1" -description = "querycompatiblerpcv2cbor client" +description = "Python client for Query Compatible RpcV2 Protocol Service" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "querycompatiblerpcv2cbor"] diff --git a/codegen-output/rest-json-1/README.md b/codegen-output/rest-json-1/README.md index 6587b4974..239dd0567 100644 --- a/codegen-output/rest-json-1/README.md +++ b/codegen-output/rest-json-1/README.md @@ -2,4 +2,4 @@ ## Sample Rest Json Protocol Service Client -restjson client +Python client for Sample Rest Json Protocol Service diff --git a/codegen-output/rest-json-1/pyproject.toml b/codegen-output/rest-json-1/pyproject.toml index a3c6b76b4..28eae9ce9 100644 --- a/codegen-output/rest-json-1/pyproject.toml +++ b/codegen-output/rest-json-1/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "restjson" version = "0.0.1" -description = "restjson client" +description = "Python client for Sample Rest Json Protocol Service" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "restjson"] diff --git a/codegen-output/rest-xml-with-namespace/README.md b/codegen-output/rest-xml-with-namespace/README.md index 1f9b69a3d..9c005dcfc 100644 --- a/codegen-output/rest-xml-with-namespace/README.md +++ b/codegen-output/rest-xml-with-namespace/README.md @@ -2,7 +2,7 @@ ## Sample Rest Xml Protocol Service With Namespace Client -restxmlwithnamespace client +Python client for Sample Rest Xml Protocol Service With Namespace ### Documentation diff --git a/codegen-output/rest-xml-with-namespace/pyproject.toml b/codegen-output/rest-xml-with-namespace/pyproject.toml index ef8901cdc..2a0359aa8 100644 --- a/codegen-output/rest-xml-with-namespace/pyproject.toml +++ b/codegen-output/rest-xml-with-namespace/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "restxmlwithnamespace" version = "0.0.1" -description = "restxmlwithnamespace client" +description = "Python client for Sample Rest Xml Protocol Service With Namespace" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "restxmlwithnamespace"] diff --git a/codegen-output/rest-xml/README.md b/codegen-output/rest-xml/README.md index e1cb86613..365c8f067 100644 --- a/codegen-output/rest-xml/README.md +++ b/codegen-output/rest-xml/README.md @@ -2,7 +2,7 @@ ## Sample Rest Xml Protocol Service Client -restxml client +Python client for Sample Rest Xml Protocol Service ### Documentation diff --git a/codegen-output/rest-xml/pyproject.toml b/codegen-output/rest-xml/pyproject.toml index e0dc82aac..6d34622cd 100644 --- a/codegen-output/rest-xml/pyproject.toml +++ b/codegen-output/rest-xml/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "restxml" version = "0.0.1" -description = "restxml client" +description = "Python client for Sample Rest Xml Protocol Service" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "restxml"] diff --git a/codegen-output/rpcv2-cbor/README.md b/codegen-output/rpcv2-cbor/README.md index 64b17629a..7beeef19f 100644 --- a/codegen-output/rpcv2-cbor/README.md +++ b/codegen-output/rpcv2-cbor/README.md @@ -2,4 +2,4 @@ ## RpcV2 Protocol Service Client -rpcv2cbor client +Python client for RpcV2 Protocol Service diff --git a/codegen-output/rpcv2-cbor/pyproject.toml b/codegen-output/rpcv2-cbor/pyproject.toml index 91fd95a8d..1c45fc0bd 100644 --- a/codegen-output/rpcv2-cbor/pyproject.toml +++ b/codegen-output/rpcv2-cbor/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "rpcv2cbor" version = "0.0.1" -description = "rpcv2cbor client" +description = "Python client for RpcV2 Protocol Service" readme = "README.md" requires-python = ">=3.12" keywords = ["smithy", "rpcv2cbor"] diff --git a/codegen/core/src/main/java/software/amazon/smithy/python/codegen/PythonSettings.java b/codegen/core/src/main/java/software/amazon/smithy/python/codegen/PythonSettings.java index 5c9cdbbb0..0671e3185 100644 --- a/codegen/core/src/main/java/software/amazon/smithy/python/codegen/PythonSettings.java +++ b/codegen/core/src/main/java/software/amazon/smithy/python/codegen/PythonSettings.java @@ -5,7 +5,6 @@ package software.amazon.smithy.python.codegen; import java.util.Arrays; -import java.util.Locale; import java.util.Objects; import software.amazon.smithy.codegen.core.CodegenException; import software.amazon.smithy.model.Model; @@ -56,9 +55,8 @@ private PythonSettings(Builder builder) { builder.service, builder.moduleName, builder.moduleVersion, - StringUtils.isBlank(builder.moduleDescription) - ? builder.moduleName + " " + builder.artifactType.name().toLowerCase(Locale.ENGLISH) - : builder.moduleDescription, + // Unset descriptions stay empty; SetupGenerator resolves them from the service. + StringUtils.isBlank(builder.moduleDescription) ? "" : builder.moduleDescription, builder.artifactType); } @@ -87,10 +85,9 @@ public ServiceShape service(Model model) { public static PythonSettings fromNode(ObjectNode config) { config.warnIfAdditionalProperties(Arrays.asList(SERVICE, MODULE_NAME, MODULE_DESCRIPTION, MODULE_VERSION)); - String moduleName = config.expectStringMember(MODULE_NAME).getValue(); Builder builder = builder() .service(config.expectStringMember(SERVICE).expectShapeId()) - .moduleName(moduleName) + .moduleName(config.expectStringMember(MODULE_NAME).getValue()) .moduleVersion(config.expectStringMember(MODULE_VERSION).getValue()); config.getStringMember(MODULE_DESCRIPTION).map(StringNode::getValue).ifPresent(builder::moduleDescription); return builder.build(); diff --git a/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/SetupGenerator.java b/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/SetupGenerator.java index 58d49d35e..dda9482e2 100644 --- a/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/SetupGenerator.java +++ b/codegen/core/src/main/java/software/amazon/smithy/python/codegen/generators/SetupGenerator.java @@ -41,8 +41,24 @@ public static void generateSetup( GenerationContext context ) { var dependencies = gatherDependencies(context.writerDelegator().getDependencies().stream()); - writePyproject(settings, context.writerDelegator(), dependencies); - writeReadme(settings, context); + var description = resolveDescription(settings, context); + writePyproject(settings, description, context.writerDelegator(), dependencies); + writeReadme(settings, description, context); + } + + /** + * Use the configured description if set, otherwise describe the client or types + * package by the service's {@code smithy.api#title} trait or else the service shape's name. + */ + private static String resolveDescription(PythonSettings settings, GenerationContext context) { + if (!StringUtils.isBlank(settings.moduleDescription())) { + return settings.moduleDescription(); + } + var service = context.model().expectShape(settings.service()); + var artifact = settings.artifactType() == PythonSettings.ArtifactType.TYPES ? "types" : "client"; + return "Python " + artifact + " for " + service.getTrait(TitleTrait.class) + .map(StringTrait::getValue) + .orElse(service.getId().getName()); } /** @@ -106,6 +122,7 @@ private static Map> gatherDependencies( */ private static void writePyproject( PythonSettings settings, + String description, WriterDelegator writers, Map> dependencies ) { @@ -139,7 +156,7 @@ private static void writePyproject( "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3.15" ] - """, settings.moduleName(), settings.moduleVersion(), settings.moduleDescription()); + """, settings.moduleName(), settings.moduleVersion(), description); Optional.ofNullable(dependencies.get(PythonDependency.Type.DEPENDENCY.getType())).ifPresent(deps -> { writer.openBlock("dependencies = [", "]\n", () -> writeDependencyList(writer, deps.values())); @@ -283,6 +300,7 @@ private static List getOptionalDependencies(SymbolDependency dependency) private static void writeReadme( PythonSettings settings, + String description, GenerationContext context ) { var service = context.model().expectShape(settings.service()); @@ -292,17 +310,13 @@ private static void writeReadme( .map(StringTrait::getValue) .orElse(StringUtils.capitalize(settings.moduleName())); - var description = StringUtils.isBlank(settings.moduleDescription()) - ? "Generated service client for " + title - : StringUtils.wrap(settings.moduleDescription(), 80); - context.writerDelegator().useFileWriter("README.md", writer -> { writer.pushState(new ReadmeSection()); writer.write(""" ## $L Client $L - """, title, description); + """, title, StringUtils.wrap(description, 80)); service.getTrait(DocumentationTrait.class).map(StringTrait::getValue).ifPresent(documentation -> { writer.write(""" diff --git a/codegen/core/src/test/java/software/amazon/smithy/python/codegen/generators/SetupGeneratorTest.java b/codegen/core/src/test/java/software/amazon/smithy/python/codegen/generators/SetupGeneratorTest.java index 91c778902..097191436 100644 --- a/codegen/core/src/test/java/software/amazon/smithy/python/codegen/generators/SetupGeneratorTest.java +++ b/codegen/core/src/test/java/software/amazon/smithy/python/codegen/generators/SetupGeneratorTest.java @@ -4,19 +4,27 @@ */ package software.amazon.smithy.python.codegen.generators; +import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; import java.util.Map; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import software.amazon.smithy.build.MockManifest; import software.amazon.smithy.codegen.core.SymbolDependency; import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.model.traits.DocumentationTrait; +import software.amazon.smithy.model.traits.TitleTrait; import software.amazon.smithy.python.codegen.GenerationContext; import software.amazon.smithy.python.codegen.PythonSettings; +import software.amazon.smithy.python.codegen.PythonSettings.ArtifactType; import software.amazon.smithy.python.codegen.PythonSymbolProvider; import software.amazon.smithy.python.codegen.SmithyPythonDependency; import software.amazon.smithy.python.codegen.writer.PythonDelegator; @@ -70,4 +78,92 @@ public void readmeKeepsRawTripleQuotesInCodeSpans() { assertTrue(readme.contains("Use `\"\"\"` here."), readme); } + + static Stream packageDescriptionCases() { + var titled = service("smithy.example#Weather", "Example Weather Service"); + var untitled = service("smithy.example#Weather", null); + var client = ArtifactType.CLIENT; + var types = ArtifactType.TYPES; + var titledDefault = "Python client for Example Weather Service"; + var titledTypesDefault = "Python types for Example Weather Service"; + return Stream.of( + Arguments.of("explicit", titled, "Custom description", client, "Custom description"), + Arguments.of("explicit old default", titled, "test_client client", client, "test_client client"), + Arguments.of("blank", titled, " ", client, titledDefault), + Arguments.of("titled", titled, null, client, titledDefault), + Arguments.of("untitled", untitled, null, client, "Python client for Weather"), + Arguments.of("types default", titled, null, types, titledTypesDefault), + Arguments.of("types untitled", untitled, null, types, "Python types for Weather"), + Arguments.of("types blank", titled, " ", types, titledTypesDefault), + Arguments.of("types explicit", titled, "Custom types", types, "Custom types"), + Arguments.of("types explicit old default", titled, "test_client types", types, "test_client types")); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("packageDescriptionCases") + public void resolvesPackageDescription( + String name, + ServiceShape service, + String moduleDescription, + ArtifactType artifactType, + String expected + ) { + assertDescription(service, moduleDescription, artifactType, expected); + } + + private static ServiceShape service(String id, String title) { + var builder = ServiceShape.builder().id(id).version("2024-01-01"); + if (title != null) { + builder.addTrait(new TitleTrait(title)); + } + return builder.build(); + } + + private static void assertDescription( + ServiceShape service, + String moduleDescription, + ArtifactType artifactType, + String expected + ) { + var model = Model.builder().addShape(service).build(); + PythonSettings settings; + if (artifactType == ArtifactType.CLIENT) { + // Clients are configured through the plugin's settings parsing. + var config = ObjectNode.builder() + .withMember("service", service.getId().toString()) + .withMember("module", "test_client") + .withMember("moduleVersion", "0.0.1"); + if (moduleDescription != null) { + config.withMember("moduleDescription", moduleDescription); + } + settings = PythonSettings.fromNode(config.build()); + } else { + // The types plugin converts its own settings through the builder. + settings = PythonSettings.builder() + .service(service.getId()) + .moduleName("test_client") + .moduleVersion("0.0.1") + .moduleDescription(moduleDescription) + .artifactType(artifactType) + .build(); + } + var manifest = new MockManifest(); + var delegator = new PythonDelegator(manifest, new PythonSymbolProvider(model, settings), settings); + var context = GenerationContext.builder() + .model(model) + .settings(settings) + .fileManifest(manifest) + .writerDelegator(delegator) + .build(); + + SetupGenerator.generateSetup(settings, context); + delegator.flushWriters(); + String pyproject = manifest.expectFileString("pyproject.toml"); + String readme = manifest.expectFileString("README.md"); + + // Both generated files carry the same resolved description. + assertAll( + () -> assertTrue(pyproject.contains("description = \"" + expected + "\"\n"), pyproject), + () -> assertTrue(readme.contains("\n" + expected + "\n"), readme)); + } } diff --git a/codegen/plugins/types/src/it/java/software/amazon/smithy/python/codegen/types/PythonTypeCodegenTest.java b/codegen/plugins/types/src/it/java/software/amazon/smithy/python/codegen/types/PythonTypeCodegenTest.java index ddd37d6ea..52ef94907 100644 --- a/codegen/plugins/types/src/it/java/software/amazon/smithy/python/codegen/types/PythonTypeCodegenTest.java +++ b/codegen/plugins/types/src/it/java/software/amazon/smithy/python/codegen/types/PythonTypeCodegenTest.java @@ -4,6 +4,11 @@ */ package software.amazon.smithy.python.codegen.types; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -39,7 +44,7 @@ public void testCodegen(@TempDir Path tempDir) { } @Test - public void testCodegenWithoutService(@TempDir Path tempDir) { + public void testCodegenWithoutService(@TempDir Path tempDir) throws IOException { PythonTypeCodegenPlugin plugin = new PythonTypeCodegenPlugin(); Model model = Model.assembler(PythonTypeCodegenTest.class.getClassLoader()) .discoverModels(PythonTypeCodegenTest.class.getClassLoader()) @@ -55,5 +60,14 @@ public void testCodegenWithoutService(@TempDir Path tempDir) { .model(model) .build(); plugin.execute(context); + + // Without a selected service, describe the package by its module name rather + // than the internal synthetic service. + var expected = "Python types for types_test"; + String pyproject = Files.readString(tempDir.resolve("pyproject.toml")); + String readme = Files.readString(tempDir.resolve("README.md")); + assertAll( + () -> assertTrue(pyproject.contains("description = \"" + expected + "\"\n"), pyproject), + () -> assertTrue(readme.contains("\n" + expected + "\n"), readme)); } } diff --git a/codegen/plugins/types/src/main/java/software/amazon/smithy/python/codegen/types/PythonTypeCodegenSettings.java b/codegen/plugins/types/src/main/java/software/amazon/smithy/python/codegen/types/PythonTypeCodegenSettings.java index ff70f76a6..4d95cf743 100644 --- a/codegen/plugins/types/src/main/java/software/amazon/smithy/python/codegen/types/PythonTypeCodegenSettings.java +++ b/codegen/plugins/types/src/main/java/software/amazon/smithy/python/codegen/types/PythonTypeCodegenSettings.java @@ -14,6 +14,7 @@ import software.amazon.smithy.python.codegen.PythonSettings; import software.amazon.smithy.utils.SmithyBuilder; import software.amazon.smithy.utils.SmithyUnstableApi; +import software.amazon.smithy.utils.StringUtils; import software.amazon.smithy.utils.ToSmithyBuilder; /** @@ -64,11 +65,17 @@ public Builder toBuilder() { } public PythonSettings toPythonSettings(ShapeId service) { + // Without a selected service, describe the package by its module name rather + // than the internal synthetic service. + var description = moduleDescription; + if (this.service.isEmpty() && StringUtils.isBlank(description)) { + description = "Python types for " + moduleName; + } return PythonSettings.builder() .service(service) .moduleName(moduleName) .moduleVersion(moduleVersion) - .moduleDescription(moduleDescription) + .moduleDescription(description) .artifactType(PythonSettings.ArtifactType.TYPES) .build(); }