Skip to content

Commit

Permalink
Fix or skip aiohttp and flask tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien Sagnard committed Dec 7, 2018
1 parent d6ca78b commit 2dd48a5
Show file tree
Hide file tree
Showing 43 changed files with 830 additions and 490 deletions.
1 change: 0 additions & 1 deletion bin/python-aiohttp-petstore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ fi
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -t modules/openapi-generator/src/main/resources/python-aiohttp -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g python-aiohttp -o samples/server/petstore/python-aiohttp -Dservice $@"

rm -rf samples/server/petstore/python-aiohttp/*
java $JAVA_OPTS -jar $executable $ags
1 change: 0 additions & 1 deletion bin/python-flask-petstore-python2.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,4 @@ export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/
#ags="generate -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g python-flask -o samples/server/petstore/flaskConnexion-python2 -DsupportPython2=true $@"
ags="generate -t modules/openapi-generator/src/main/resources/flaskConnexion -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g python-flask -o samples/server/petstore/flaskConnexion-python2 -c bin/supportPython2.json -D service $@"

rm -rf samples/server/petstore/flaskConnexion-python2/*
java $JAVA_OPTS -jar $executable $ags
1 change: 0 additions & 1 deletion bin/python-flask-petstore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ fi
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -t modules/openapi-generator/src/main/resources/flaskConnexion -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g python-flask -o samples/server/petstore/flaskConnexion -Dservice $@"

rm -rf samples/server/petstore/flaskConnexion/*
java $JAVA_OPTS -jar $executable $ags
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,18 @@ public class PythonAbstractConnexionServerCodegen extends DefaultCodegen impleme
public static final String CONTROLLER_PACKAGE = "controllerPackage";
public static final String DEFAULT_CONTROLLER = "defaultController";
public static final String SUPPORT_PYTHON2 = "supportPython2";
static final String MEDIA_TYPE = "mediaType";

protected int serverPort = 8080;
protected String packageName;
protected String packageVersion;
protected String controllerPackage;
protected String defaultController;
protected Map<Character, String> regexModifiers;
protected boolean fixParameterName;
protected boolean fixBodyName;

public PythonAbstractConnexionServerCodegen(String templateDirectory, boolean fixParameterNameValue, boolean fixBodyNameValue) {
public PythonAbstractConnexionServerCodegen(String templateDirectory, boolean fixBodyNameValue) {
super();
fixParameterName = fixParameterNameValue;
fixBodyName = fixBodyNameValue;
modelPackage = "models";
testPackage = "test";
Expand Down Expand Up @@ -130,9 +129,6 @@ public PythonAbstractConnexionServerCodegen(String templateDirectory, boolean fi
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("test-requirements.mustache", "", "test-requirements.txt"));
supportingFiles.add(new SupportingFile("requirements.mustache", "", "requirements.txt"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("Dockerfile.mustache", "", "Dockerfile"));
supportingFiles.add(new SupportingFile("dockerignore.mustache", "", ".dockerignore"));

regexModifiers = new HashMap<Character, String>();
regexModifiers.put('i', "IGNORECASE");
Expand Down Expand Up @@ -334,11 +330,8 @@ public void preprocessOpenAPI(OpenAPI openAPI) {
}
if (!fixedPath.equals(pathname)) {
LOGGER.warn("Path '" + pathname + "' is not consistant with Python variable names. It will be replaced by '" + fixedPath + "'");
// Is it okay to replace automatically ?
if (fixParameterName) {
paths.remove(pathname);
paths.put(fixedPath, path);
}
paths.remove(pathname);
paths.put(fixedPath, path);
}
}
Map<HttpMethod, Operation> operationMap = path.readOperationsMap();
Expand Down Expand Up @@ -366,10 +359,7 @@ public void preprocessOpenAPI(OpenAPI openAPI) {
String pythonParameterName = this.toParamName(swaggerParameterName);
if (!swaggerParameterName.equals(pythonParameterName)) {
LOGGER.warn("Parameter name '" + swaggerParameterName + "' is not consistant with Python variable names. It will be replaced by '" + pythonParameterName + "'");
// Is it okay to replace automatically ?
if (fixParameterName) {
parameter.setName(pythonParameterName);
}
parameter.setName(pythonParameterName);
}
if (swaggerParameterName.isEmpty()) {
LOGGER.error("Missing parameter name in " + pathname + "." + parameter.getIn());
Expand All @@ -395,13 +385,11 @@ public void preprocessOpenAPI(OpenAPI openAPI) {
}
}
// Sort path names after variable name fix
if (fixParameterName) {
List<String> fixedPathnames = new ArrayList(paths.keySet());
Collections.sort(fixedPathnames);
for (String pathname: fixedPathnames) {
PathItem pathItem = paths.remove(pathname);
paths.put(pathname, pathItem);
}
List<String> fixedPathnames = new ArrayList(paths.keySet());
Collections.sort(fixedPathnames);
for (String pathname: fixedPathnames) {
PathItem pathItem = paths.remove(pathname);
paths.put(pathname, pathItem);
}
}
addSecurityExtensions(openAPI);
Expand Down Expand Up @@ -683,7 +671,7 @@ public void setParameterExampleValue(CodegenParameter p) {
example = "'" + escapeText(example) + "'";
} else if (!languageSpecificPrimitives.contains(type)) {
// type is a model class, e.g. User
example = type + "()";
example = "{}";
} else {
LOGGER.warn("Type " + type + " not handled properly in setParameterExampleValue");
}
Expand All @@ -692,7 +680,12 @@ public void setParameterExampleValue(CodegenParameter p) {
example = p.items.defaultValue;
}
if (example == null) {
example = "None";
if (Boolean.TRUE.equals(p.isListContainer)) {
example = "[]";
}
else {
example = "None";
}
} else if (Boolean.TRUE.equals(p.isListContainer)) {
if (Boolean.TRUE.equals(p.isBodyParam)) {
example = "[" + example + "]";
Expand Down Expand Up @@ -786,6 +779,66 @@ public void postProcessParameter(CodegenParameter parameter) {
postProcessPattern(parameter.pattern, parameter.vendorExtensions);
}

@Override
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");

for (CodegenOperation operation : operationList) {
Map<String, String> skipTests = new HashMap<>();
// Set flag to deactivate tests due to connexion issue.
if (operation.consumes != null ) {
if (operation.consumes.size() == 1) {
Map<String, String> consume = operation.consumes.get(0);
if (! "application/json".equals(consume.get(MEDIA_TYPE))) {
skipTests.put("reason", consume.get(MEDIA_TYPE) + " not supported by Connexion");
if ("multipart/form-data".equals(consume.get(MEDIA_TYPE))) {
operation.isMultipart = Boolean.TRUE;
}
}
operation.vendorExtensions.put("x-prefered-consume", consume);
}
else if (operation.consumes.size() > 1) {
Map<String, String> consume = operation.consumes.get(0);
skipTests.put("reason", "Connexion does not support multiple consummes. See https://github.com/zalando/connexion/pull/760");
operation.vendorExtensions.put("x-prefered-consume", consume);
if ("multipart/form-data".equals(consume.get(MEDIA_TYPE))) {
operation.isMultipart = Boolean.TRUE;
}
}
}
else {
// A body without consumes means '*/*' has been used instead of application/json
if (operation.bodyParam != null) {
Map<String, String> consume = new HashMap<>();
consume.put(MEDIA_TYPE, "application/json");
operation.vendorExtensions.put("x-prefered-consume", consume);
skipTests.put("reason", "*/* not supported by Connexion. Use application/json instead. See https://github.com/zalando/connexion/pull/760");
}
}
// Choose to consume 'application/json' if available, else choose the last one.
if (operation.produces != null ) {
for (Map<String, String> produce: operation.produces) {
operation.vendorExtensions.put("x-prefered-produce", produce);
if (produce.get(MEDIA_TYPE).equals("application/json")) {
break;
}
}
}
if (! skipTests.isEmpty()) {
operation.vendorExtensions.put("x-skip-test", skipTests);
}
if (operation.requestBodyExamples != null) {
for (Map<String, String> example: operation.requestBodyExamples) {
if (example.get("contentType") != null && example.get("contentType").equals("application/json")) {
operation.bodyParam.example = example.get("example");
}
}
}
}
return objs;
}

/*
* The openapi pattern spec follows the Perl convention and style of modifiers. Python
* does not support this in as natural a way so it needs to convert it. See
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class PythonAiohttpConnexionServerCodegen extends PythonAbstractConnexion
private static final Logger LOGGER = LoggerFactory.getLogger(PythonAiohttpConnexionServerCodegen.class);

public PythonAiohttpConnexionServerCodegen() {
super("python-aiohttp", true, true);
super("python-aiohttp", true);
testPackage = "tests";
embeddedTemplateDir = templateDir = "python-aiohttp";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class PythonFlaskConnexionServerCodegen extends PythonAbstractConnexionSe
private static final Logger LOGGER = LoggerFactory.getLogger(PythonFlaskConnexionServerCodegen.class);

public PythonFlaskConnexionServerCodegen() {
super("flaskConnexion", false, false);
super("flaskConnexion", false);
}

/**
Expand All @@ -45,6 +45,9 @@ public String getName() {

@Override
protected void addSupportingFiles() {
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("Dockerfile.mustache", "", "Dockerfile"));
supportingFiles.add(new SupportingFile("dockerignore.mustache", "", ".dockerignore"));
supportingFiles.add(new SupportingFile("setup.mustache", "", "setup.py"));
supportingFiles.add(new SupportingFile("tox.mustache", "", "tox.ini"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# coding: utf-8

from __future__ import absolute_import
import unittest

from flask import json
from six import BytesIO
Expand All @@ -13,7 +14,10 @@ from {{packageName}}.test import BaseTestCase
class {{#operations}}Test{{classname}}(BaseTestCase):
"""{{classname}} integration test stubs"""

{{#operation}}
{{#operation}}
{{#vendorExtensions.x-skip-test}}
@unittest.skip("{{reason}}")
{{/vendorExtensions.x-skip-test}}
def test_{{operationId}}(self):
"""Test case for {{{operationId}}}

Expand All @@ -25,18 +29,21 @@ class {{#operations}}Test{{classname}}(BaseTestCase):
{{#queryParams}}
{{#-first}}query_string = [{{/-first}}{{^-first}} {{/-first}}('{{paramName}}', {{{example}}}){{#hasMore}},{{/hasMore}}{{#-last}}]{{/-last}}
{{/queryParams}}
{{#headerParams}}
{{#-first}}headers = [{{/-first}}{{^-first}} {{/-first}}('{{paramName}}', {{{example}}}){{#hasMore}},{{/hasMore}}{{#-last}}]{{/-last}}
{{/headerParams}}
headers = { {{#vendorExtensions.x-prefered-produce}}
'Accept': '{{mediaType}}',{{/vendorExtensions.x-prefered-produce}}{{#vendorExtensions.x-prefered-consume}}
'Content-Type': '{{mediaType}}',{{/vendorExtensions.x-prefered-consume}}{{#headerParams}}
'{{paramName}}': {{{example}}},{{/headerParams}}{{#authMethods}}
{{#isOAuth}}'Authorization': 'Bearer special-key',{{/isOAuth}}{{#isApiKey}}'{{name}}': 'special-key',{{/isApiKey}}{{/authMethods}}
}
{{#formParams}}
{{#-first}}data = dict({{/-first}}{{^-first}} {{/-first}}{{paramName}}={{{example}}}{{#hasMore}},{{/hasMore}}{{#-last}}){{/-last}}
{{/formParams}}
response = self.client.open(
'{{#contextPath}}{{{.}}}{{/contextPath}}{{{path}}}'{{#pathParams}}{{#-first}}.format({{/-first}}{{paramName}}={{{example}}}{{#hasMore}}, {{/hasMore}}{{^hasMore}}){{/hasMore}}{{/pathParams}},
method='{{httpMethod}}'{{#bodyParam}},
method='{{httpMethod}}',
headers=headers{{#bodyParam}},
data=json.dumps({{paramName}}){{^consumes}},
content_type='application/json'{{/consumes}}{{/bodyParam}}{{#headerParams}}{{#-first}},
headers=headers{{/-first}}{{/headerParams}}{{#formParams}}{{#-first}},
content_type='application/json'{{/consumes}}{{/bodyParam}}{{#formParams}}{{#-first}},
data=data{{/-first}}{{/formParams}}{{#consumes}}{{#-first}},
content_type='{{{mediaType}}}'{{/-first}}{{/consumes}}{{#queryParams}}{{#-first}},
query_string=query_string{{/-first}}{{/queryParams}})
Expand All @@ -47,5 +54,4 @@ class {{#operations}}Test{{classname}}(BaseTestCase):
{{/operations}}

if __name__ == '__main__':
import unittest
unittest.main()
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
connexion == 2.0.0
connexion == 2.0.2
swagger-ui-bundle == 0.0.2
python_dateutil == 2.6.0
{{#supportPython2}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = {{#supportPython2}}py27, {{/supportPython2}}py35
envlist = {{#supportPython2}}py27, {{/supportPython2}}py3

[testenv]
deps=-r{toxinidir}/requirements.txt
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,17 @@ Your OpenAPI definition lives here:
http://localhost:{{serverPort}}{{contextPath}}/openapi.json
```

To launch the integration tests, use tox:
To launch the integration tests, use pytest:
```
sudo pip install -r test-requirements.txt
pytest
```

## Running with Docker

To run the server on a Docker container, please execute the following from the root directory:

```bash
# building the image
docker build -t {{packageName}} .

# starting up a container
docker run -p {{serverPort}}:{{serverPort}} {{packageName}}
```

## Prevent file overriding

After first generation, add edited files to _.openapi-generator-ignore_ to prevent generator to overwrite them. Typically:
```
server/controllers/*
test/*
Dockerfile
*.txt
```
Original file line number Diff line number Diff line change
@@ -1,33 +1,58 @@
# coding: utf-8

import pytest
import json
from aiohttp import web
{{#operations}}
{{#operation}}
{{#isMultipart}}
from aiohttp import FormData
{{/isMultipart}}
{{/operation}}
{{/operations}}

{{#imports}}{{import}}
{{/imports}}

{{#operations}}
{{#operation}}

{{#vendorExtensions.x-skip-test}}
@pytest.mark.skip("{{reason}}")
{{/vendorExtensions.x-skip-test}}
async def test_{{operationId}}(client):
"""Test case for {{{operationId}}}

{{{summary}}}
"""
{{#bodyParam}}
{{paramName}} = {{{example}}}.to_dict()
{{paramName}} = {{{example}}}
{{/bodyParam}}
{{#queryParams}}
{{#-first}}params = [{{/-first}}{{^-first}} {{/-first}}('{{paramName}}', {{{example}}}){{#hasMore}},{{/hasMore}}{{#-last}}]{{/-last}}
{{/queryParams}}
headers = {
'Accept': 'application/json',{{#bodyParam}}
'Content-Type': 'application/json',{{/bodyParam}}{{#headerParams}}
headers = { {{#vendorExtensions.x-prefered-produce}}
'Accept': '{{mediaType}}',{{/vendorExtensions.x-prefered-produce}}{{#vendorExtensions.x-prefered-consume}}
'Content-Type': '{{mediaType}}',{{/vendorExtensions.x-prefered-consume}}{{#headerParams}}
'{{paramName}}': {{{example}}},{{/headerParams}}{{#authMethods}}
{{#isOAuth}}'Authorization': 'Bearer special-key',{{/isOAuth}}{{#isApiKey}}'{{name}}': 'special-key',{{/isApiKey}}{{/authMethods}}
}
{{#formParams}}
{{#-first}}data = dict({{/-first}}{{^-first}} {{/-first}}{{paramName}}={{{example}}}{{#hasMore}},{{/hasMore}}{{#-last}}){{/-last}}
{{#isMultipart}}
{{#-first}}
data = FormData()
{{/-first}}
data.add_field('{{paramName}}', {{{example}}})
{{/isMultipart}}
{{^isMultipart}}
{{#-first}}
data = {
{{/-first}}
'{{paramName}}': {{{example}}}{{#hasMore}},{{/hasMore}}
{{^hasMore}}
}
{{/hasMore}}
{{/isMultipart}}
{{/formParams}}
response = await client.request(
method='{{httpMethod}}',
Expand Down
Loading

0 comments on commit 2dd48a5

Please sign in to comment.