Skip to content

Commit 89d7af1

Browse files
Add support for both string and object license formats in pyproject.toml for Python and Python-Pydantic generators. (OpenAPITools#21619)
1 parent 3e577d5 commit 89d7af1

5 files changed

Lines changed: 153 additions & 1 deletion

File tree

modules/openapi-generator/src/main/resources/python-pydantic-v1/pyproject.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "{{{packageName}}}"
33
version = "{{{packageVersion}}}"
44
description = "{{{appName}}}"
55
authors = ["{{infoName}}{{^infoName}}OpenAPI Generator Community{{/infoName}} <{{infoEmail}}{{^infoEmail}}team@openapitools.org{{/infoEmail}}>"]
6-
license = "{{{licenseInfo}}}{{^licenseInfo}}Unlicense{{/licenseInfo}}"
6+
license = { text = "{{{licenseInfo}}}{{^licenseInfo}}Unlicense{{/licenseInfo}}" }
77
readme = "README.md"
88
repository = "https://{{{gitHost}}}/{{{gitUserId}}}/{{{gitRepoId}}}"
99
keywords = ["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"]

modules/openapi-generator/src/main/resources/python/pyproject.mustache

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ authors = [
1616
]
1717
{{/poetry1}}
1818
{{#licenseInfo}}
19+
{{#poetry1}}
1920
license = "{{{licenseInfo}}}"
21+
{{/poetry1}}
22+
{{^poetry1}}
23+
license = { text = "{{{licenseInfo}}}" }
24+
{{/poetry1}}
2025
{{/licenseInfo}}
2126
readme = "README.md"
2227
{{#poetry1}}

modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonClientCodegenTest.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.swagger.v3.parser.core.models.ParseOptions;
2626
import io.swagger.v3.parser.util.SchemaTypeUtil;
2727
import org.openapitools.codegen.*;
28+
import org.openapitools.codegen.config.CodegenConfigurator;
2829
import org.openapitools.codegen.languages.PythonClientCodegen;
2930
import org.openapitools.codegen.languages.features.CXFServerFeatures;
3031
import org.testng.Assert;
@@ -611,4 +612,77 @@ public void testInitFileImportsExports() throws IOException {
611612
assertFileContains(initFilePath, "from openapi_client.models.tag import Tag as Tag");
612613
assertFileContains(initFilePath, "from openapi_client.models.user import User as User");
613614
}
615+
616+
@Test(description = "Verify default license format uses object notation when poetry1 is false")
617+
public void testLicenseFormatInPyprojectToml() throws IOException {
618+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
619+
output.deleteOnExit();
620+
621+
final CodegenConfigurator configurator = new CodegenConfigurator()
622+
.setGeneratorName("python")
623+
.setInputSpec("src/test/resources/bugs/issue_21619.yaml")
624+
.setOutputDir(output.getAbsolutePath())
625+
.addAdditionalProperty("licenseInfo", "MIT");
626+
627+
DefaultGenerator generator = new DefaultGenerator();
628+
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
629+
files.forEach(File::deleteOnExit);
630+
631+
TestUtils.assertFileExists(Paths.get(output.getAbsolutePath(), "pyproject.toml"));
632+
// When poetry1=false (default), license should use object notation: { text = "MIT" }
633+
TestUtils.assertFileContains(Paths.get(output.getAbsolutePath(), "pyproject.toml"),
634+
"license = { text = \"MIT\" }");
635+
}
636+
637+
@Test(description = "Verify poetry1 mode uses string notation for license")
638+
public void testPoetry1LicenseFormat() throws IOException {
639+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
640+
output.deleteOnExit();
641+
642+
final CodegenConfigurator configurator = new CodegenConfigurator()
643+
.setGeneratorName("python")
644+
.setInputSpec("src/test/resources/bugs/issue_21619.yaml")
645+
.setOutputDir(output.getAbsolutePath())
646+
.addAdditionalProperty("licenseInfo", "Apache-2.0")
647+
.addAdditionalProperty("poetry1", true); // Enable legacy poetry1 mode
648+
649+
DefaultGenerator generator = new DefaultGenerator();
650+
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
651+
files.forEach(File::deleteOnExit);
652+
653+
Path pyprojectPath = Paths.get(output.getAbsolutePath(), "pyproject.toml");
654+
TestUtils.assertFileExists(pyprojectPath);
655+
656+
// In poetry1 mode, license should use simple string format: "Apache-2.0"
657+
TestUtils.assertFileContains(pyprojectPath, "license = \"Apache-2.0\"");
658+
659+
// Verify it does NOT use the new object format
660+
TestUtils.assertFileNotContains(pyprojectPath, "license = { text = \"Apache-2.0\" }");
661+
}
662+
663+
@Test(description = "Verify non-poetry1 mode uses object notation for license")
664+
public void testNonPoetry1LicenseFormat() throws IOException {
665+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
666+
output.deleteOnExit();
667+
668+
final CodegenConfigurator configurator = new CodegenConfigurator()
669+
.setGeneratorName("python")
670+
.setInputSpec("src/test/resources/bugs/issue_21619.yaml")
671+
.setOutputDir(output.getAbsolutePath())
672+
.addAdditionalProperty("licenseInfo", "BSD-3-Clause")
673+
.addAdditionalProperty("poetry1", false); // Explicitly disable poetry1 mode
674+
675+
DefaultGenerator generator = new DefaultGenerator();
676+
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
677+
files.forEach(File::deleteOnExit);
678+
679+
Path pyprojectPath = Paths.get(output.getAbsolutePath(), "pyproject.toml");
680+
TestUtils.assertFileExists(pyprojectPath);
681+
682+
// In non-poetry1 mode, license should use object format: { text = "BSD-3-Clause" }
683+
TestUtils.assertFileContains(pyprojectPath, "license = { text = \"BSD-3-Clause\" }");
684+
685+
// Verify it does NOT use the legacy string format
686+
TestUtils.assertFileNotContains(pyprojectPath, "license = \"BSD-3-Clause\"");
687+
}
614688
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonPydanticV1ClientCodegenTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.swagger.v3.parser.core.models.ParseOptions;
2626
import io.swagger.v3.parser.util.SchemaTypeUtil;
2727
import org.openapitools.codegen.*;
28+
import org.openapitools.codegen.config.CodegenConfigurator;
2829
import org.openapitools.codegen.languages.PythonPydanticV1ClientCodegen;
2930
import org.openapitools.codegen.languages.features.CXFServerFeatures;
3031
import org.testng.Assert;
@@ -534,4 +535,45 @@ public void testInitFileImportsExports() throws Exception {
534535
assertFileContains(initFilePath, "from openapi_client.models.tag import Tag as Tag");
535536
assertFileContains(initFilePath, "from openapi_client.models.user import User as User");
536537
}
538+
539+
@Test(description = "Verify pydantic-v1 always uses object notation for license")
540+
public void testLicenseFormatInPyprojectToml() throws IOException {
541+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
542+
output.deleteOnExit();
543+
544+
final CodegenConfigurator configurator = new CodegenConfigurator()
545+
.setGeneratorName("python-pydantic-v1")
546+
.setInputSpec("src/test/resources/bugs/issue_21619.yaml")
547+
.setOutputDir(output.getAbsolutePath())
548+
.addAdditionalProperty("licenseInfo", "MIT");
549+
550+
DefaultGenerator generator = new DefaultGenerator();
551+
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
552+
files.forEach(File::deleteOnExit);
553+
554+
TestUtils.assertFileExists(Paths.get(output.getAbsolutePath(), "pyproject.toml"));
555+
// python-pydantic-v1 always uses object notation regardless of poetry1
556+
TestUtils.assertFileContains(Paths.get(output.getAbsolutePath(), "pyproject.toml"),
557+
"license = { text = \"MIT\" }");
558+
}
559+
560+
@Test(description = "Verify pydantic-v1 uses default license when licenseInfo not provided")
561+
public void testDefaultLicenseInPyprojectToml() throws IOException {
562+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
563+
output.deleteOnExit();
564+
565+
final CodegenConfigurator configurator = new CodegenConfigurator()
566+
.setGeneratorName("python-pydantic-v1")
567+
.setInputSpec("src/test/resources/bugs/issue_21619.yaml")
568+
.setOutputDir(output.getAbsolutePath());
569+
570+
DefaultGenerator generator = new DefaultGenerator();
571+
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
572+
files.forEach(File::deleteOnExit);
573+
574+
TestUtils.assertFileExists(Paths.get(output.getAbsolutePath(), "pyproject.toml"));
575+
// Should use default "Unlicense"
576+
TestUtils.assertFileContains(Paths.get(output.getAbsolutePath(), "pyproject.toml"),
577+
"license = { text = \"Unlicense\" }");
578+
}
537579
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
openapi: 3.0.0
2+
info:
3+
title: License Format Test API
4+
version: 1.0.0
5+
description: Simple API for testing pyproject.toml license format changes
6+
paths:
7+
/test:
8+
get:
9+
operationId: getTest
10+
summary: Simple test endpoint
11+
responses:
12+
'200':
13+
description: Success
14+
content:
15+
application/json:
16+
schema:
17+
type: object
18+
properties:
19+
message:
20+
type: string
21+
example: "Hello World"
22+
components:
23+
schemas:
24+
TestModel:
25+
type: object
26+
properties:
27+
id:
28+
type: integer
29+
format: int64
30+
name:
31+
type: string

0 commit comments

Comments
 (0)