Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/generators/python-aiohttp.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|supportPython2|support python2. This option has been deprecated and will be removed in the 5.x release.| |false|
|useNose|use the nose test framework| |false|
|usePythonSrcRootInImports|include pythonSrcRoot in import namespaces.| |false|

## IMPORT MAPPING

Expand Down
1 change: 1 addition & 0 deletions docs/generators/python-blueplanet.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|supportPython2|support python2. This option has been deprecated and will be removed in the 5.x release.| |false|
|useNose|use the nose test framework| |false|
|usePythonSrcRootInImports|include pythonSrcRoot in import namespaces.| |false|

## IMPORT MAPPING

Expand Down
1 change: 1 addition & 0 deletions docs/generators/python-flask.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|supportPython2|support python2. This option has been deprecated and will be removed in the 5.x release.| |false|
|useNose|use the nose test framework| |false|
|usePythonSrcRootInImports|include pythonSrcRoot in import namespaces.| |false|

## IMPORT MAPPING

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,7 @@ public String patternCorrection(String pattern) {

public void setPackageName(String packageName) {
this.packageName = packageName;
additionalProperties.put(CodegenConstants.PACKAGE_NAME, this.packageName);
}

public void setProjectName(String projectName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public abstract class AbstractPythonConnexionServerCodegen extends AbstractPytho
// nose is a python testing framework, we use pytest if USE_NOSE is unset
public static final String USE_NOSE = "useNose";
public static final String PYTHON_SRC_ROOT = "pythonSrcRoot";
public static final String USE_PYTHON_SRC_ROOT_IN_IMPORTS = "usePythonSrcRootInImports";
static final String MEDIA_TYPE = "mediaType";

protected int serverPort = 8080;
Expand All @@ -62,6 +63,7 @@ public abstract class AbstractPythonConnexionServerCodegen extends AbstractPytho
protected boolean featureCORS = Boolean.FALSE;
protected boolean useNose = Boolean.FALSE;
protected String pythonSrcRoot;
protected boolean usePythonSrcRootInImports = Boolean.FALSE;

public AbstractPythonConnexionServerCodegen(String templateDirectory, boolean fixBodyNameValue) {
super();
Expand All @@ -79,7 +81,7 @@ public AbstractPythonConnexionServerCodegen(String templateDirectory, boolean fi
typeMapping.put("map", "Dict");

// set the output folder here
outputFolder = "generated-code/connexion";
outputFolder = "generated-code" + File.separatorChar + "connexion";

apiTemplateFiles.put("controller.mustache", ".py");
modelTemplateFiles.put("model.mustache", ".py");
Expand Down Expand Up @@ -132,6 +134,8 @@ public AbstractPythonConnexionServerCodegen(String templateDirectory, boolean fi
defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(PYTHON_SRC_ROOT, "put python sources in this subdirectory of output folder (defaults to \"\" for). Use this for src/ layout.").
defaultValue(""));
cliOptions.add(new CliOption(USE_PYTHON_SRC_ROOT_IN_IMPORTS, "include pythonSrcRoot in import namespaces.").
defaultValue("false"));
}

protected void addSupportingFiles() {
Expand All @@ -147,7 +151,6 @@ public void processOpts() {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
} else {
setPackageName("openapi_server");
additionalProperties.put(CodegenConstants.PACKAGE_NAME, this.packageName);
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
Expand Down Expand Up @@ -177,9 +180,19 @@ public void processOpts() {
if (additionalProperties.containsKey(USE_NOSE)) {
setUseNose((String) additionalProperties.get(USE_NOSE));
}
if (additionalProperties.containsKey(USE_PYTHON_SRC_ROOT_IN_IMPORTS)) {
setUsePythonSrcRootInImports((String) additionalProperties.get(USE_PYTHON_SRC_ROOT_IN_IMPORTS));
}
if (additionalProperties.containsKey(PYTHON_SRC_ROOT)) {
setPythonSrcRoot((String) additionalProperties.get(PYTHON_SRC_ROOT));
additionalProperties.put(PYTHON_SRC_ROOT, pythonSrcRoot);
String pythonSrcRoot = (String) additionalProperties.get(PYTHON_SRC_ROOT);
if (usePythonSrcRootInImports) {
// if we prepend the package name if the pythonSrcRoot we get the desired effect.
// but we also need to set pythonSrcRoot itself to "" to ensure all the paths are
// what we expect.
setPackageName(pythonSrcRoot + "." + packageName);
pythonSrcRoot = "";
}
setPythonSrcRoot(pythonSrcRoot);
} else {
setPythonSrcRoot("");
}
Expand Down Expand Up @@ -218,6 +231,11 @@ public void setPythonSrcRoot(String val) {
} else {
this.pythonSrcRoot = pySrcRoot + File.separator;
}
additionalProperties.put(PYTHON_SRC_ROOT, StringUtils.defaultIfBlank(this.pythonSrcRoot, null));
}

public void setUsePythonSrcRootInImports(String val) {
this.usePythonSrcRootInImports = Boolean.parseBoolean(val);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package org.openapitools.codegen.python;

import static org.openapitools.codegen.languages.AbstractPythonConnexionServerCodegen.PYTHON_SRC_ROOT;
import static org.openapitools.codegen.languages.AbstractPythonConnexionServerCodegen.USE_PYTHON_SRC_ROOT_IN_IMPORTS;

import java.io.File;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;

import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.languages.AbstractPythonConnexionServerCodegen;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class AbstractPythonConnexionServerCodegenTest {

/**
* Passing "description" as first param to succinctly identify the significance of test parameters.
*/
@Test(dataProvider = "data")
public void test(String description, Map<String, Object> additionalProperties, String modelName,
ExpectedValues expectedValues) {
AbstractPythonConnexionServerCodegen codegen = new MockAbstractPythonConnexionServerCodegen("", false);
codegen.additionalProperties().putAll(additionalProperties);
codegen.processOpts();
String pythonSrcRoot = Objects.toString(codegen.additionalProperties().get(PYTHON_SRC_ROOT), null);
Assert.assertEquals(pythonSrcRoot, expectedValues.pythonSrcRoot);
Assert.assertEquals(codegen.apiPackage(), expectedValues.expectedApiPackage);
Assert.assertEquals(codegen.modelFileFolder(), expectedValues.expectedModelFileFolder);
Assert.assertEquals(codegen.apiFileFolder(), expectedValues.expectedApiFileFolder);
Assert.assertEquals(codegen.toModelImport(modelName), expectedValues.expectedImport);
}

@DataProvider
public Object[][] data() {
return new Object[][]{
new Object[]{
"Default setup",
Collections.emptyMap(),
"TestModel",
new ExpectedValues("from openapi_server.models.test_model import TestModel",
"openapi_server.controllers",
platformAgnosticPath("generated-code", "connexion", "openapi_server", "models"),
platformAgnosticPath("generated-code", "connexion", "openapi_server", "controllers"),
null)
},
new Object[]{
"Default setup with Python src root",
ImmutableMap.of(PYTHON_SRC_ROOT, "test_root"),
"TestModel",
new ExpectedValues("from openapi_server.models.test_model import TestModel",
"openapi_server.controllers",
platformAgnosticPath("generated-code", "connexion", "test_root", "openapi_server", "models"),
platformAgnosticPath("generated-code", "connexion", "test_root", "openapi_server", "controllers"),
"test_root")
},
new Object[]{
"Python src in import",
ImmutableMap.of(PYTHON_SRC_ROOT, "test_root", USE_PYTHON_SRC_ROOT_IN_IMPORTS, "true"),
"TestModel",
new ExpectedValues("from test_root.openapi_server.models.test_model import TestModel",
"test_root.openapi_server.controllers",
platformAgnosticPath("generated-code", "connexion", "test_root", "openapi_server", "models"),
platformAgnosticPath("generated-code", "connexion", "test_root", "openapi_server", "controllers"),
null)
},
new Object[]{
"Python src in import with specified package",
ImmutableMap.of(PYTHON_SRC_ROOT, "test_root",
USE_PYTHON_SRC_ROOT_IN_IMPORTS, "true",
CodegenConstants.PACKAGE_NAME, "test_package"),
"TestModel",
new ExpectedValues("from test_root.test_package.models.test_model import TestModel",
"test_root.test_package.controllers",
platformAgnosticPath("generated-code", "connexion", "test_root", "test_package", "models"),
platformAgnosticPath("generated-code", "connexion", "test_root", "test_package", "controllers"),
null)
}
};
}

private static String platformAgnosticPath(String... nodes) {
return StringUtils.join(nodes, File.separatorChar);
}

private static class MockAbstractPythonConnexionServerCodegen extends AbstractPythonConnexionServerCodegen {
public MockAbstractPythonConnexionServerCodegen(String templateDirectory, boolean fixBodyNameValue) {
super(templateDirectory, fixBodyNameValue);
}
}

private static class ExpectedValues {
public final String expectedImport;
public final String expectedApiPackage;
public final String expectedModelFileFolder;
public final String expectedApiFileFolder;
public final String pythonSrcRoot;

public ExpectedValues(String expectedImport, String expectedApiPackage, String expectedModelFileFolder,
String expectedApiFileFolder, String pythonSrcRoot) {
this.expectedImport = expectedImport;
this.expectedApiPackage = expectedApiPackage;
this.expectedModelFileFolder = expectedModelFileFolder;
this.expectedApiFileFolder = expectedApiFileFolder;
this.pythonSrcRoot = pythonSrcRoot != null ? pythonSrcRoot + File.separatorChar : null;
}
}

}