Python flask pythonic params (#2374)

* Using connexion `pythonic_params` support while keeping OpenAPI spec file correct with reference to the original spec file.

* - Add `camelCase` query parameter which shows the incorrectnes of the conversion of the OpenAPI spec file in Python server implementation(s).

* Also use `pythonic_params=True` for the `python-aiohttp` implementation.

* - Updated Python related samples.

* The unit tests must provide the correct query parameters.

* - Updated Python related samples.
This commit is contained in:
Tom Ghyselinck
2019-03-24 03:36:26 +01:00
committed by William Cheng
parent 033ab8a6f5
commit f7943257c5
27 changed files with 190 additions and 69 deletions

View File

@@ -336,6 +336,7 @@ public class PythonAbstractConnexionServerCodegen extends DefaultCodegen impleme
if (!fixedPath.equals(pathname)) { if (!fixedPath.equals(pathname)) {
LOGGER.warn("Path '" + pathname + "' is not consistant with Python variable names. It will be replaced by '" + fixedPath + "'"); LOGGER.warn("Path '" + pathname + "' is not consistant with Python variable names. It will be replaced by '" + fixedPath + "'");
paths.remove(pathname); paths.remove(pathname);
path.addExtension("x-python-connexion-openapi-name", pathname);
paths.put(fixedPath, path); paths.put(fixedPath, path);
} }
} }
@@ -364,6 +365,7 @@ public class PythonAbstractConnexionServerCodegen extends DefaultCodegen impleme
String pythonParameterName = this.toParamName(swaggerParameterName); String pythonParameterName = this.toParamName(swaggerParameterName);
if (!swaggerParameterName.equals(pythonParameterName)) { if (!swaggerParameterName.equals(pythonParameterName)) {
LOGGER.warn("Parameter name '" + swaggerParameterName + "' is not consistant with Python variable names. It will be replaced by '" + pythonParameterName + "'"); LOGGER.warn("Parameter name '" + swaggerParameterName + "' is not consistant with Python variable names. It will be replaced by '" + pythonParameterName + "'");
parameter.addExtension("x-python-connexion-openapi-name", swaggerParameterName);
parameter.setName(pythonParameterName); parameter.setName(pythonParameterName);
} }
if (swaggerParameterName.isEmpty()) { if (swaggerParameterName.isEmpty()) {
@@ -474,6 +476,70 @@ public class PythonAbstractConnexionServerCodegen extends DefaultCodegen impleme
@Override @Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) { public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
// XXX - Revert the original parameter (and path) names to make sure we have
// a consistent REST interface across other server/client languages:
//
// XXX - Reverts `x-python-connexion-openapi-name` back to the original (query/path) parameter name.
// We do not want to have our REST API itself being converted to pythonic params.
// This would be incompatible with other server implementations.
OpenAPI openAPI = (OpenAPI) objs.get("openAPI");
//OpenAPI openAPI = (OpenAPI) objs.remove("openAPI");
Map<String, PathItem> paths = openAPI.getPaths();
if (paths != null) {
List<String> pathnames = new ArrayList(paths.keySet());
for (String pythonPathname : pathnames) {
PathItem path = paths.get(pythonPathname);
// Fix path parameters back to original casing
Map<String, Object> pathExtensions = path.getExtensions();
if (pathExtensions != null) {
// Get and remove the (temporary) vendor extension
String openapiPathname = (String) pathExtensions.remove("x-python-connexion-openapi-name");
if (openapiPathname != null && openapiPathname != pythonPathname) {
LOGGER.info("Path '" + pythonPathname + "' is not consistant with the original OpenAPI definition. It will be replaced back by '" + openapiPathname + "'");
paths.remove(pythonPathname);
paths.put(openapiPathname, path);
}
}
Map<HttpMethod, Operation> operationMap = path.readOperationsMap();
if (operationMap != null) {
for (HttpMethod method : operationMap.keySet()) {
Operation operation = operationMap.get(method);
if (operation.getParameters() != null) {
for (Parameter parameter: operation.getParameters()) {
Map<String, Object> parameterExtensions = parameter.getExtensions();
if (parameterExtensions != null) {
// Get and remove the (temporary) vendor extension
String swaggerParameterName = (String) parameterExtensions.remove("x-python-connexion-openapi-name");
if (swaggerParameterName != null) {
String pythonParameterName = parameter.getName();
if (swaggerParameterName != pythonParameterName) {
LOGGER.info("Reverting name of parameter '" + pythonParameterName + "' of operation '" + operation.getOperationId() + "' back to '" + swaggerParameterName + "'");
parameter.setName(swaggerParameterName);
} else {
LOGGER.debug("Name of parameter '" + pythonParameterName + "' of operation '" + operation.getOperationId() + "' was unchanged.");
}
} else {
LOGGER.debug("x-python-connexion-openapi-name was not set on parameter '" + parameter.getName() + "' of operation '" + operation.getOperationId() + "'");
}
}
}
}
}
}
}
// Sort path names after variable name fix
List<String> recoveredPathnames = new ArrayList(paths.keySet());
Collections.sort(recoveredPathnames);
for (String pathname: recoveredPathnames) {
PathItem pathItem = paths.remove(pathname);
paths.put(pathname, pathItem);
}
}
//objs.put("openAPI", openAPI);
generateYAMLSpecFile(objs); generateYAMLSpecFile(objs);
for (Map<String, Object> operations : getOperations(objs)) { for (Map<String, Object> operations : getOperations(objs)) {

View File

@@ -8,5 +8,8 @@ def main():
} }
specification_dir = os.path.join(os.path.dirname(__file__), 'openapi') specification_dir = os.path.join(os.path.dirname(__file__), 'openapi')
app = connexion.AioHttpApp(__name__, specification_dir=specification_dir, options=options) app = connexion.AioHttpApp(__name__, specification_dir=specification_dir, options=options)
app.add_api('openapi.yaml', arguments={'title': '{{appName}}'}, pass_context_arg_name='request') app.add_api('openapi.yaml',
arguments={'title': '{{appName}}'},
pythonic_params=True,
pass_context_arg_name='request')
app.run(port={{serverPort}}) app.run(port={{serverPort}})

View File

@@ -11,7 +11,11 @@ def client(loop, aiohttp_client):
options = { options = {
"swagger_ui": True "swagger_ui": True
} }
specification_dir = os.path.join(os.path.dirname(__file__), '..', '{{packageName}}', 'openapi') specification_dir = os.path.join(os.path.dirname(__file__), '..',
app = connexion.AioHttpApp(__name__, specification_dir=specification_dir, options=options) '{{packageName}}',
app.add_api('openapi.yaml', pass_context_arg_name='request') 'openapi')
app = connexion.AioHttpApp(__name__, specification_dir=specification_dir,
options=options)
app.add_api('openapi.yaml', pythonic_params=True,
pass_context_arg_name='request')
return loop.run_until_complete(aiohttp_client(app.app)) return loop.run_until_complete(aiohttp_client(app.app))

View File

@@ -29,7 +29,7 @@ async def test_{{operationId}}(client):
{{paramName}} = {{{example}}} {{paramName}} = {{{example}}}
{{/bodyParam}} {{/bodyParam}}
{{#queryParams}} {{#queryParams}}
{{#-first}}params = [{{/-first}}{{^-first}} {{/-first}}('{{paramName}}', {{{example}}}){{#hasMore}},{{/hasMore}}{{#-last}}]{{/-last}} {{#-first}}params = [{{/-first}}{{^-first}} {{/-first}}('{{^vendorExtensions.x-python-connexion-openapi-name}}{{paramName}}{{/vendorExtensions.x-python-connexion-openapi-name}}{{#vendorExtensions.x-python-connexion-openapi-name}}{{vendorExtensions.x-python-connexion-openapi-name}}{{/vendorExtensions.x-python-connexion-openapi-name}}', {{{example}}}){{#hasMore}},{{/hasMore}}{{#-last}}]{{/-last}}
{{/queryParams}} {{/queryParams}}
headers = { {{#vendorExtensions.x-prefered-produce}} headers = { {{#vendorExtensions.x-prefered-produce}}
'Accept': '{{mediaType}}',{{/vendorExtensions.x-prefered-produce}}{{#vendorExtensions.x-prefered-consume}} 'Accept': '{{mediaType}}',{{/vendorExtensions.x-prefered-produce}}{{#vendorExtensions.x-prefered-consume}}

View File

@@ -12,5 +12,5 @@ class BaseTestCase(TestCase):
logging.getLogger('connexion.operation').setLevel('ERROR') logging.getLogger('connexion.operation').setLevel('ERROR')
app = connexion.App(__name__, specification_dir='../openapi/') app = connexion.App(__name__, specification_dir='../openapi/')
app.app.json_encoder = JSONEncoder app.app.json_encoder = JSONEncoder
app.add_api('openapi.yaml') app.add_api('openapi.yaml', pythonic_params=True)
return app.app return app.app

View File

@@ -13,7 +13,9 @@ from {{packageName}} import encoder
def main(): def main():
app = connexion.App(__name__, specification_dir='./openapi/') app = connexion.App(__name__, specification_dir='./openapi/')
app.app.json_encoder = encoder.JSONEncoder app.app.json_encoder = encoder.JSONEncoder
app.add_api('openapi.yaml', arguments={'title': '{{appName}}'}) app.add_api('openapi.yaml',
arguments={'title': '{{appName}}'},
pythonic_params=True)
app.run(port={{serverPort}}) app.run(port={{serverPort}})

View File

@@ -27,7 +27,7 @@ class {{#operations}}Test{{classname}}(BaseTestCase):
{{paramName}} = {{{example}}} {{paramName}} = {{{example}}}
{{/bodyParam}} {{/bodyParam}}
{{#queryParams}} {{#queryParams}}
{{#-first}}query_string = [{{/-first}}{{^-first}} {{/-first}}('{{paramName}}', {{{example}}}){{#hasMore}},{{/hasMore}}{{#-last}}]{{/-last}} {{#-first}}query_string = [{{/-first}}{{^-first}} {{/-first}}('{{^vendorExtensions.x-python-connexion-openapi-name}}{{paramName}}{{/vendorExtensions.x-python-connexion-openapi-name}}{{#vendorExtensions.x-python-connexion-openapi-name}}{{vendorExtensions.x-python-connexion-openapi-name}}{{/vendorExtensions.x-python-connexion-openapi-name}}', {{{example}}}){{#hasMore}},{{/hasMore}}{{#-last}}]{{/-last}}
{{/queryParams}} {{/queryParams}}
headers = { {{#vendorExtensions.x-prefered-produce}} headers = { {{#vendorExtensions.x-prefered-produce}}
'Accept': '{{mediaType}}',{{/vendorExtensions.x-prefered-produce}}{{#vendorExtensions.x-prefered-consume}} 'Accept': '{{mediaType}}',{{/vendorExtensions.x-prefered-produce}}{{#vendorExtensions.x-prefered-consume}}

View File

@@ -116,6 +116,13 @@ paths:
type: array type: array
items: items:
type: string type: string
- name: maxCount
in: query
description: Maximum number of items to return
required: false
schema:
type: integer
format: int32
responses: responses:
'200': '200':
description: successful operation description: successful operation

View File

@@ -8,7 +8,9 @@ from openapi_server import encoder
def main(): def main():
app = connexion.App(__name__, specification_dir='./openapi/') app = connexion.App(__name__, specification_dir='./openapi/')
app.app.json_encoder = encoder.JSONEncoder app.app.json_encoder = encoder.JSONEncoder
app.add_api('openapi.yaml', arguments={'title': 'OpenAPI Petstore'}) app.add_api('openapi.yaml',
arguments={'title': 'OpenAPI Petstore'},
pythonic_params=True)
app.run(port=8080) app.run(port=8080)

View File

@@ -49,13 +49,15 @@ def find_pets_by_status(status): # noqa: E501
return 'do some magic!' return 'do some magic!'
def find_pets_by_tags(tags): # noqa: E501 def find_pets_by_tags(tags, max_count=None): # noqa: E501
"""Finds Pets by tags """Finds Pets by tags
Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. # noqa: E501 Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. # noqa: E501
:param tags: Tags to filter by :param tags: Tags to filter by
:type tags: List[str] :type tags: List[str]
:param max_count: Maximum number of items to return
:type max_count: int
:rtype: List[Pet] :rtype: List[Pet]
""" """

View File

@@ -114,6 +114,15 @@ paths:
type: string type: string
type: array type: array
style: form style: form
- description: Maximum number of items to return
explode: true
in: query
name: maxCount
required: false
schema:
format: int32
type: integer
style: form
responses: responses:
200: 200:
content: content:
@@ -138,7 +147,7 @@ paths:
tags: tags:
- pet - pet
x-openapi-router-controller: openapi_server.controllers.pet_controller x-openapi-router-controller: openapi_server.controllers.pet_controller
/pet/{pet_id}: /pet/{petId}:
delete: delete:
operationId: delete_pet operationId: delete_pet
parameters: parameters:
@@ -152,7 +161,7 @@ paths:
- description: Pet id to delete - description: Pet id to delete
explode: false explode: false
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -176,7 +185,7 @@ paths:
- description: ID of pet to return - description: ID of pet to return
explode: false explode: false
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -208,7 +217,7 @@ paths:
- description: ID of pet that needs to be updated - description: ID of pet that needs to be updated
explode: false explode: false
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -238,14 +247,14 @@ paths:
tags: tags:
- pet - pet
x-openapi-router-controller: openapi_server.controllers.pet_controller x-openapi-router-controller: openapi_server.controllers.pet_controller
/pet/{pet_id}/uploadImage: /pet/{petId}/uploadImage:
post: post:
operationId: upload_file operationId: upload_file
parameters: parameters:
- description: ID of pet to update - description: ID of pet to update
explode: false explode: false
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -326,7 +335,7 @@ paths:
tags: tags:
- store - store
x-openapi-router-controller: openapi_server.controllers.store_controller x-openapi-router-controller: openapi_server.controllers.store_controller
/store/order/{order_id}: /store/order/{orderId}:
delete: delete:
description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
operationId: delete_order operationId: delete_order
@@ -334,7 +343,7 @@ paths:
- description: ID of the order that needs to be deleted - description: ID of the order that needs to be deleted
explode: false explode: false
in: path in: path
name: order_id name: orderId
required: true required: true
schema: schema:
type: string type: string
@@ -355,7 +364,7 @@ paths:
- description: ID of pet that needs to be fetched - description: ID of pet that needs to be fetched
explode: false explode: false
in: path in: path
name: order_id name: orderId
required: true required: true
schema: schema:
format: int64 format: int64

View File

@@ -12,5 +12,5 @@ class BaseTestCase(TestCase):
logging.getLogger('connexion.operation').setLevel('ERROR') logging.getLogger('connexion.operation').setLevel('ERROR')
app = connexion.App(__name__, specification_dir='../openapi/') app = connexion.App(__name__, specification_dir='../openapi/')
app.app.json_encoder = JSONEncoder app.app.json_encoder = JSONEncoder
app.add_api('openapi.yaml') app.add_api('openapi.yaml', pythonic_params=True)
return app.app return app.app

View File

@@ -89,7 +89,8 @@ class TestPetController(BaseTestCase):
Finds Pets by tags Finds Pets by tags
""" """
query_string = [('tags', 'tags_example')] query_string = [('tags', 'tags_example'),
('maxCount', 56)]
headers = { headers = {
'Accept': 'application/json', 'Accept': 'application/json',
'Authorization': 'Bearer special-key', 'Authorization': 'Bearer special-key',

View File

@@ -8,7 +8,9 @@ from openapi_server import encoder
def main(): def main():
app = connexion.App(__name__, specification_dir='./openapi/') app = connexion.App(__name__, specification_dir='./openapi/')
app.app.json_encoder = encoder.JSONEncoder app.app.json_encoder = encoder.JSONEncoder
app.add_api('openapi.yaml', arguments={'title': 'OpenAPI Petstore'}) app.add_api('openapi.yaml',
arguments={'title': 'OpenAPI Petstore'},
pythonic_params=True)
app.run(port=8080) app.run(port=8080)

View File

@@ -49,13 +49,15 @@ def find_pets_by_status(status): # noqa: E501
return 'do some magic!' return 'do some magic!'
def find_pets_by_tags(tags): # noqa: E501 def find_pets_by_tags(tags, max_count=None): # noqa: E501
"""Finds Pets by tags """Finds Pets by tags
Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. # noqa: E501 Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. # noqa: E501
:param tags: Tags to filter by :param tags: Tags to filter by
:type tags: List[str] :type tags: List[str]
:param max_count: Maximum number of items to return
:type max_count: int
:rtype: List[Pet] :rtype: List[Pet]
""" """

View File

@@ -114,6 +114,15 @@ paths:
type: string type: string
type: array type: array
style: form style: form
- description: Maximum number of items to return
explode: true
in: query
name: maxCount
required: false
schema:
format: int32
type: integer
style: form
responses: responses:
200: 200:
content: content:
@@ -138,7 +147,7 @@ paths:
tags: tags:
- pet - pet
x-openapi-router-controller: openapi_server.controllers.pet_controller x-openapi-router-controller: openapi_server.controllers.pet_controller
/pet/{pet_id}: /pet/{petId}:
delete: delete:
operationId: delete_pet operationId: delete_pet
parameters: parameters:
@@ -152,7 +161,7 @@ paths:
- description: Pet id to delete - description: Pet id to delete
explode: false explode: false
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -176,7 +185,7 @@ paths:
- description: ID of pet to return - description: ID of pet to return
explode: false explode: false
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -208,7 +217,7 @@ paths:
- description: ID of pet that needs to be updated - description: ID of pet that needs to be updated
explode: false explode: false
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -238,14 +247,14 @@ paths:
tags: tags:
- pet - pet
x-openapi-router-controller: openapi_server.controllers.pet_controller x-openapi-router-controller: openapi_server.controllers.pet_controller
/pet/{pet_id}/uploadImage: /pet/{petId}/uploadImage:
post: post:
operationId: upload_file operationId: upload_file
parameters: parameters:
- description: ID of pet to update - description: ID of pet to update
explode: false explode: false
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -326,7 +335,7 @@ paths:
tags: tags:
- store - store
x-openapi-router-controller: openapi_server.controllers.store_controller x-openapi-router-controller: openapi_server.controllers.store_controller
/store/order/{order_id}: /store/order/{orderId}:
delete: delete:
description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
operationId: delete_order operationId: delete_order
@@ -334,7 +343,7 @@ paths:
- description: ID of the order that needs to be deleted - description: ID of the order that needs to be deleted
explode: false explode: false
in: path in: path
name: order_id name: orderId
required: true required: true
schema: schema:
type: string type: string
@@ -355,7 +364,7 @@ paths:
- description: ID of pet that needs to be fetched - description: ID of pet that needs to be fetched
explode: false explode: false
in: path in: path
name: order_id name: orderId
required: true required: true
schema: schema:
format: int64 format: int64

View File

@@ -12,5 +12,5 @@ class BaseTestCase(TestCase):
logging.getLogger('connexion.operation').setLevel('ERROR') logging.getLogger('connexion.operation').setLevel('ERROR')
app = connexion.App(__name__, specification_dir='../openapi/') app = connexion.App(__name__, specification_dir='../openapi/')
app.app.json_encoder = JSONEncoder app.app.json_encoder = JSONEncoder
app.add_api('openapi.yaml') app.add_api('openapi.yaml', pythonic_params=True)
return app.app return app.app

View File

@@ -89,7 +89,8 @@ class TestPetController(BaseTestCase):
Finds Pets by tags Finds Pets by tags
""" """
query_string = [('tags', 'tags_example')] query_string = [('tags', 'tags_example'),
('maxCount', 56)]
headers = { headers = {
'Accept': 'application/json', 'Accept': 'application/json',
'Authorization': 'Bearer special-key', 'Authorization': 'Bearer special-key',

View File

@@ -8,5 +8,8 @@ def main():
} }
specification_dir = os.path.join(os.path.dirname(__file__), 'openapi') specification_dir = os.path.join(os.path.dirname(__file__), 'openapi')
app = connexion.AioHttpApp(__name__, specification_dir=specification_dir, options=options) app = connexion.AioHttpApp(__name__, specification_dir=specification_dir, options=options)
app.add_api('openapi.yaml', arguments={'title': 'OpenAPI Petstore'}, pass_context_arg_name='request') app.add_api('openapi.yaml',
arguments={'title': 'OpenAPI Petstore'},
pythonic_params=True,
pass_context_arg_name='request')
app.run(port=8080) app.run(port=8080)

View File

@@ -161,7 +161,7 @@ paths:
tags: tags:
- pet - pet
x-openapi-router-controller: openapi_server.controllers.pet_controller x-openapi-router-controller: openapi_server.controllers.pet_controller
/pet/{pet_id}: /pet/{petId}:
delete: delete:
operationId: delete_pet operationId: delete_pet
parameters: parameters:
@@ -171,7 +171,7 @@ paths:
type: string type: string
- description: Pet id to delete - description: Pet id to delete
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -194,7 +194,7 @@ paths:
parameters: parameters:
- description: ID of pet to return - description: ID of pet to return
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -226,7 +226,7 @@ paths:
parameters: parameters:
- description: ID of pet that needs to be updated - description: ID of pet that needs to be updated
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -256,13 +256,13 @@ paths:
- pet - pet
x-openapi-router-controller: openapi_server.controllers.pet_controller x-openapi-router-controller: openapi_server.controllers.pet_controller
x-codegen-request-body-name: body x-codegen-request-body-name: body
/pet/{pet_id}/uploadImage: /pet/{petId}/uploadImage:
post: post:
operationId: upload_file operationId: upload_file
parameters: parameters:
- description: ID of pet to update - description: ID of pet to update
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -345,14 +345,14 @@ paths:
- store - store
x-codegen-request-body-name: body x-codegen-request-body-name: body
x-openapi-router-controller: openapi_server.controllers.store_controller x-openapi-router-controller: openapi_server.controllers.store_controller
/store/order/{order_id}: /store/order/{orderId}:
delete: delete:
description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
operationId: delete_order operationId: delete_order
parameters: parameters:
- description: ID of the order that needs to be deleted - description: ID of the order that needs to be deleted
in: path in: path
name: order_id name: orderId
required: true required: true
schema: schema:
type: string type: string
@@ -373,7 +373,7 @@ paths:
parameters: parameters:
- description: ID of pet that needs to be fetched - description: ID of pet that needs to be fetched
in: path in: path
name: order_id name: orderId
required: true required: true
schema: schema:
format: int64 format: int64

View File

@@ -11,7 +11,11 @@ def client(loop, aiohttp_client):
options = { options = {
"swagger_ui": True "swagger_ui": True
} }
specification_dir = os.path.join(os.path.dirname(__file__), '..', 'openapi_server', 'openapi') specification_dir = os.path.join(os.path.dirname(__file__), '..',
app = connexion.AioHttpApp(__name__, specification_dir=specification_dir, options=options) 'openapi_server',
app.add_api('openapi.yaml', pass_context_arg_name='request') 'openapi')
app = connexion.AioHttpApp(__name__, specification_dir=specification_dir,
options=options)
app.add_api('openapi.yaml', pythonic_params=True,
pass_context_arg_name='request')
return loop.run_until_complete(aiohttp_client(app.app)) return loop.run_until_complete(aiohttp_client(app.app))

View File

@@ -8,7 +8,9 @@ from openapi_server import encoder
def main(): def main():
app = connexion.App(__name__, specification_dir='./openapi/') app = connexion.App(__name__, specification_dir='./openapi/')
app.app.json_encoder = encoder.JSONEncoder app.app.json_encoder = encoder.JSONEncoder
app.add_api('openapi.yaml', arguments={'title': 'OpenAPI Petstore'}) app.add_api('openapi.yaml',
arguments={'title': 'OpenAPI Petstore'},
pythonic_params=True)
app.run(port=8080) app.run(port=8080)

View File

@@ -159,7 +159,7 @@ paths:
tags: tags:
- pet - pet
x-openapi-router-controller: openapi_server.controllers.pet_controller x-openapi-router-controller: openapi_server.controllers.pet_controller
/pet/{pet_id}: /pet/{petId}:
delete: delete:
operationId: delete_pet operationId: delete_pet
parameters: parameters:
@@ -169,7 +169,7 @@ paths:
type: string type: string
- description: Pet id to delete - description: Pet id to delete
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -192,7 +192,7 @@ paths:
parameters: parameters:
- description: ID of pet to return - description: ID of pet to return
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -224,7 +224,7 @@ paths:
parameters: parameters:
- description: ID of pet that needs to be updated - description: ID of pet that needs to be updated
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -252,13 +252,13 @@ paths:
tags: tags:
- pet - pet
x-openapi-router-controller: openapi_server.controllers.pet_controller x-openapi-router-controller: openapi_server.controllers.pet_controller
/pet/{pet_id}/uploadImage: /pet/{petId}/uploadImage:
post: post:
operationId: upload_file operationId: upload_file
parameters: parameters:
- description: ID of pet to update - description: ID of pet to update
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -338,14 +338,14 @@ paths:
- store - store
x-codegen-request-body-name: body x-codegen-request-body-name: body
x-openapi-router-controller: openapi_server.controllers.store_controller x-openapi-router-controller: openapi_server.controllers.store_controller
/store/order/{order_id}: /store/order/{orderId}:
delete: delete:
description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
operationId: delete_order operationId: delete_order
parameters: parameters:
- description: ID of the order that needs to be deleted - description: ID of the order that needs to be deleted
in: path in: path
name: order_id name: orderId
required: true required: true
schema: schema:
type: string type: string
@@ -366,7 +366,7 @@ paths:
parameters: parameters:
- description: ID of pet that needs to be fetched - description: ID of pet that needs to be fetched
in: path in: path
name: order_id name: orderId
required: true required: true
schema: schema:
format: int64 format: int64

View File

@@ -12,5 +12,5 @@ class BaseTestCase(TestCase):
logging.getLogger('connexion.operation').setLevel('ERROR') logging.getLogger('connexion.operation').setLevel('ERROR')
app = connexion.App(__name__, specification_dir='../openapi/') app = connexion.App(__name__, specification_dir='../openapi/')
app.app.json_encoder = JSONEncoder app.app.json_encoder = JSONEncoder
app.add_api('openapi.yaml') app.add_api('openapi.yaml', pythonic_params=True)
return app.app return app.app

View File

@@ -8,7 +8,9 @@ from openapi_server import encoder
def main(): def main():
app = connexion.App(__name__, specification_dir='./openapi/') app = connexion.App(__name__, specification_dir='./openapi/')
app.app.json_encoder = encoder.JSONEncoder app.app.json_encoder = encoder.JSONEncoder
app.add_api('openapi.yaml', arguments={'title': 'OpenAPI Petstore'}) app.add_api('openapi.yaml',
arguments={'title': 'OpenAPI Petstore'},
pythonic_params=True)
app.run(port=8080) app.run(port=8080)

View File

@@ -159,7 +159,7 @@ paths:
tags: tags:
- pet - pet
x-openapi-router-controller: openapi_server.controllers.pet_controller x-openapi-router-controller: openapi_server.controllers.pet_controller
/pet/{pet_id}: /pet/{petId}:
delete: delete:
operationId: delete_pet operationId: delete_pet
parameters: parameters:
@@ -169,7 +169,7 @@ paths:
type: string type: string
- description: Pet id to delete - description: Pet id to delete
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -192,7 +192,7 @@ paths:
parameters: parameters:
- description: ID of pet to return - description: ID of pet to return
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -224,7 +224,7 @@ paths:
parameters: parameters:
- description: ID of pet that needs to be updated - description: ID of pet that needs to be updated
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -252,13 +252,13 @@ paths:
tags: tags:
- pet - pet
x-openapi-router-controller: openapi_server.controllers.pet_controller x-openapi-router-controller: openapi_server.controllers.pet_controller
/pet/{pet_id}/uploadImage: /pet/{petId}/uploadImage:
post: post:
operationId: upload_file operationId: upload_file
parameters: parameters:
- description: ID of pet to update - description: ID of pet to update
in: path in: path
name: pet_id name: petId
required: true required: true
schema: schema:
format: int64 format: int64
@@ -338,14 +338,14 @@ paths:
- store - store
x-codegen-request-body-name: body x-codegen-request-body-name: body
x-openapi-router-controller: openapi_server.controllers.store_controller x-openapi-router-controller: openapi_server.controllers.store_controller
/store/order/{order_id}: /store/order/{orderId}:
delete: delete:
description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
operationId: delete_order operationId: delete_order
parameters: parameters:
- description: ID of the order that needs to be deleted - description: ID of the order that needs to be deleted
in: path in: path
name: order_id name: orderId
required: true required: true
schema: schema:
type: string type: string
@@ -366,7 +366,7 @@ paths:
parameters: parameters:
- description: ID of pet that needs to be fetched - description: ID of pet that needs to be fetched
in: path in: path
name: order_id name: orderId
required: true required: true
schema: schema:
format: int64 format: int64

View File

@@ -12,5 +12,5 @@ class BaseTestCase(TestCase):
logging.getLogger('connexion.operation').setLevel('ERROR') logging.getLogger('connexion.operation').setLevel('ERROR')
app = connexion.App(__name__, specification_dir='../openapi/') app = connexion.App(__name__, specification_dir='../openapi/')
app.app.json_encoder = JSONEncoder app.app.json_encoder = JSONEncoder
app.add_api('openapi.yaml') app.add_api('openapi.yaml', pythonic_params=True)
return app.app return app.app