[python-flask] Apply template tweaks to improve lint results (#6826)

The linting results for the generated samples are as follows
where the first number is the BEFORE and the second is AFTER.

flaskConnexion          1843 vs. 20
flaskConnexion-python2  1841 vs. 19

For the complete details please see the following gist.
https://gist.github.com/kenjones-cisco/edc9d71ef7fd2bf23714ecbb693d52b3
This commit is contained in:
Kenny Jones
2017-10-27 10:18:14 -04:00
committed by wing328
parent f472b623f0
commit 28d14e34c4
46 changed files with 1276 additions and 1239 deletions

View File

@@ -1,6 +1,7 @@
# coding: utf-8
# flake8: noqa
from __future__ import absolute_import
# import models into model package
{{#models}}{{#model}}from .{{classFilename}} import {{classname}}{{/model}}
{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}}{{/model}}
{{/models}}

View File

@@ -1,8 +1,10 @@
from flask_testing import TestCase
from ..encoder import JSONEncoder
import connexion
import logging
import connexion
from flask_testing import TestCase
from {{packageName}}.encoder import JSONEncoder
class BaseTestCase(TestCase):

View File

@@ -6,13 +6,14 @@
{{/supportPython2}}
import connexion
from .encoder import JSONEncoder
from {{packageName}} import encoder
def main():
app = connexion.App(__name__, specification_dir='./swagger/')
app.app.json_encoder = JSONEncoder
app.add_api('swagger.yaml', arguments={'title': '{{appDescription}}'})
app.app.json_encoder = encoder.JSONEncoder
app.add_api('swagger.yaml', arguments={'title': '{{appName}}'})
app.run(port={{serverPort}})

View File

@@ -1,38 +1,39 @@
from pprint import pformat
import pprint
import six
{{^supportPython2}}
from typing import TypeVar, Type
import typing
{{/supportPython2}}
from six import iteritems
from ..util import deserialize_model
from {{packageName}} import util
{{^supportPython2}}
T = TypeVar('T')
T = typing.TypeVar('T')
{{/supportPython2}}
class Model(object):
# swaggerTypes: The key is attribute name and the value is attribute type.
# swaggerTypes: The key is attribute name and the
# value is attribute type.
swagger_types = {}
# attributeMap: The key is attribute name and the value is json key in definition.
# attributeMap: The key is attribute name and the
# value is json key in definition.
attribute_map = {}
@classmethod
def from_dict(cls{{^supportPython2}}: Type[T]{{/supportPython2}}, dikt){{^supportPython2}} -> T{{/supportPython2}}:
"""
Returns the dict as a model
"""
return deserialize_model(dikt, cls)
def from_dict(cls{{^supportPython2}}: typing.Type[T]{{/supportPython2}}, dikt){{^supportPython2}} -> T{{/supportPython2}}:
"""Returns the dict as a model"""
return util.deserialize_model(dikt, cls)
def to_dict(self):
"""
Returns the model properties as a dict
"""Returns the model properties as a dict
:rtype: dict
"""
result = {}
for attr, _ in iteritems(self.swagger_types):
for attr, _ in six.iteritems(self.swagger_types):
value = getattr(self, attr)
if isinstance(value, list):
result[attr] = list(map(
@@ -53,27 +54,20 @@ class Model(object):
return result
def to_str(self):
"""
Returns the string representation of the model
"""Returns the string representation of the model
:rtype: str
"""
return pformat(self.to_dict())
return pprint.pformat(self.to_dict())
def __repr__(self):
"""
For `print` and `pprint`
"""
"""For `print` and `pprint`"""
return self.to_str()
def __eq__(self, other):
"""
Returns true if both objects are equal
"""
"""Returns true if both objects are equal"""
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""
Returns true if both objects are not equal
"""
return not self == other
"""Returns true if both objects are not equal"""
return not self == other

View File

@@ -1,18 +1,18 @@
import connexion
{{#imports}}{{import}}
import six
{{#imports}}{{import}} # noqa: E501
{{/imports}}
from datetime import date, datetime
from typing import List, Dict
from six import iteritems
from ..util import deserialize_date, deserialize_datetime
from {{packageName}} import util
{{#operations}}
{{#operation}}
def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}):
"""
{{#summary}}{{.}}{{/summary}}{{^summary}}{{operationId}}{{/summary}}
{{#notes}}{{.}}{{/notes}}
def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}): # noqa: E501
"""{{#summary}}{{.}}{{/summary}}{{^summary}}{{operationId}}{{/summary}}
{{#notes}}{{.}}{{/notes}} # noqa: E501
{{#allParams}}
:param {{paramName}}: {{description}}
{{^isContainer}}
@@ -55,15 +55,15 @@ def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{
{{#allParams}}
{{^isContainer}}
{{#isDate}}
{{paramName}} = deserialize_date({{paramName}})
{{paramName}} = util.deserialize_date({{paramName}})
{{/isDate}}
{{#isDateTime}}
{{paramName}} = deserialize_datetime({{paramName}})
{{paramName}} = util.deserialize_datetime({{paramName}})
{{/isDateTime}}
{{^isPrimitiveType}}
{{^isFile}}
if connexion.request.is_json:
{{paramName}} = {{baseType}}.from_dict(connexion.request.get_json())
{{paramName}} = {{baseType}}.from_dict(connexion.request.get_json()) # noqa: E501
{{/isFile}}
{{/isPrimitiveType}}
{{/isContainer}}
@@ -71,15 +71,15 @@ def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{
{{#items}}
{{#isDate}}
if connexion.request.is_json:
{{paramName}} = [deserialize_date(s) for s in connexion.request.get_json()]
{{paramName}} = [util.deserialize_date(s) for s in connexion.request.get_json()] # noqa: E501
{{/isDate}}
{{#isDateTime}}
if connexion.request.is_json:
{{paramName}} = [deserialize_datetime(s) for s in connexion.request.get_json()]
{{paramName}} = [util.deserialize_datetime(s) for s in connexion.request.get_json()] # noqa: E501
{{/isDateTime}}
{{#complexType}}
if connexion.request.is_json:
{{paramName}} = [{{complexType}}.from_dict(d) for d in connexion.request.get_json()]
{{paramName}} = [{{complexType}}.from_dict(d) for d in connexion.request.get_json()] # noqa: E501
{{/complexType}}
{{/items}}
{{/isListContainer}}
@@ -87,15 +87,15 @@ def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{
{{#items}}
{{#isDate}}
if connexion.request.is_json:
{{paramName}} = {k: deserialize_date(v) for k, v in iteritems(connexion.request.get_json())}
{{paramName}} = {k: util.deserialize_date(v) for k, v in six.iteritems(connexion.request.get_json())} # noqa: E501
{{/isDate}}
{{#isDateTime}}
if connexion.request.is_json:
{{paramName}} = {k: deserialize_datetime(v) for k, v in iteritems(connexion.request.get_json())}
{{paramName}} = {k: util.deserialize_datetime(v) for k, v in six.iteritems(connexion.request.get_json())} # noqa: E501
{{/isDateTime}}
{{#complexType}}
if connexion.request.is_json:
{{paramName}} = {k: {{baseType}}.from_dict(v) for k, v in iteritems(connexion.request.get_json())}
{{paramName}} = {k: {{baseType}}.from_dict(v) for k, v in six.iteritems(connexion.request.get_json())} # noqa: E501
{{/complexType}}
{{/items}}
{{/isMapContainer}}

View File

@@ -2,20 +2,20 @@
from __future__ import absolute_import
{{#imports}}{{import}}
{{/imports}}
from . import BaseTestCase
from six import BytesIO
from flask import json
from six import BytesIO
{{#imports}}{{import}} # noqa: E501
{{/imports}}
from {{packageName}}.test import BaseTestCase
class {{#operations}}Test{{classname}}(BaseTestCase):
""" {{classname}} integration test stubs """
"""{{classname}} integration test stubs"""
{{#operation}}
def test_{{operationId}}(self):
"""
Test case for {{{operationId}}}
"""Test case for {{{operationId}}}
{{{summary}}}
"""
@@ -31,15 +31,17 @@ class {{#operations}}Test{{classname}}(BaseTestCase):
{{#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}},
data=json.dumps({{paramName}}){{^consumes}},
content_type='application/json'{{/consumes}}{{/bodyParam}}{{#headerParams}}{{#-first}},
headers=headers{{/-first}}{{/headerParams}}{{#formParams}}{{#-first}},
data=data{{/-first}}{{/formParams}}{{#consumes}}{{#-first}},
content_type='{{{mediaType}}}'{{/-first}}{{/consumes}}{{#queryParams}}{{#-first}},
query_string=query_string{{/-first}}{{/queryParams}})
self.assert200(response, "Response body is : " + response.data.decode('utf-8'))
response = self.client.open(
'{{#contextPath}}{{{.}}}{{/contextPath}}{{{path}}}'{{#pathParams}}{{#-first}}.format({{/-first}}{{paramName}}={{{example}}}{{#hasMore}}, {{/hasMore}}{{^hasMore}}){{/hasMore}}{{/pathParams}},
method='{{httpMethod}}'{{#bodyParam}},
data=json.dumps({{paramName}}){{^consumes}},
content_type='application/json'{{/consumes}}{{/bodyParam}}{{#headerParams}}{{#-first}},
headers=headers{{/-first}}{{/headerParams}}{{#formParams}}{{#-first}},
data=data{{/-first}}{{/formParams}}{{#consumes}}{{#-first}},
content_type='{{{mediaType}}}'{{/-first}}{{/consumes}}{{#queryParams}}{{#-first}},
query_string=query_string{{/-first}}{{/queryParams}})
self.assert200(response,
'Response body is : ' + response.data.decode('utf-8'))
{{/operation}}
{{/operations}}

View File

@@ -1,6 +1,8 @@
from six import iteritems
from {{modelPackage}}.base_model_ import Model
from connexion.apps.flask_app import FlaskJSONEncoder
import six
from {{modelPackage}}.base_model_ import Model
class JSONEncoder(FlaskJSONEncoder):
include_nulls = False
@@ -8,11 +10,11 @@ class JSONEncoder(FlaskJSONEncoder):
def default(self, o):
if isinstance(o, Model):
dikt = {}
for attr, _ in iteritems(o.swagger_types):
for attr, _ in six.iteritems(o.swagger_types):
value = getattr(o, attr)
if value is None and not self.include_nulls:
continue
attr = o.attribute_map[attr]
dikt[attr] = value
return dikt
return FlaskJSONEncoder.default(self, o)
return FlaskJSONEncoder.default(self, o)

View File

@@ -1,73 +1,74 @@
# coding: utf-8
from __future__ import absolute_import
{{#imports}}{{import}}
from datetime import date, datetime # noqa: F401
from typing import List, Dict # noqa: F401
from {{modelPackage}}.base_model_ import Model
{{#imports}}{{import}} # noqa: E501
{{/imports}}
from .base_model_ import Model
from datetime import date, datetime
from typing import List, Dict
from ..util import deserialize_model
from {{packageName}} import util
{{#models}}
{{#model}}
class {{classname}}(Model):
"""
NOTE: This class is auto generated by the swagger code generator program.
Do not edit the class manually.
"""
"""NOTE: This class is auto generated by the swagger code generator program.
Do not edit the class manually.
"""{{#allowableValues}}
{{#allowableValues}}
"""
allowed enum values
"""
{{#enumVars}}
{{name}} = {{{value}}}
{{/enumVars}}
{{/allowableValues}}
{{name}} = {{{value}}}{{^-last}}
{{/-last}}
{{/enumVars}}{{/allowableValues}}
def __init__(self{{#vars}}, {{name}}{{^supportPython2}}: {{datatype}}{{/supportPython2}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}):
"""
{{classname}} - a model defined in Swagger
def __init__(self{{#vars}}, {{name}}{{^supportPython2}}: {{datatype}}{{/supportPython2}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}): # noqa: E501
"""{{classname}} - a model defined in Swagger
{{#vars}}
:param {{name}}: The {{name}} of this {{classname}}.
:param {{name}}: The {{name}} of this {{classname}}. # noqa: E501
:type {{name}}: {{datatype}}
{{/vars}}
"""
self.swagger_types = {
{{#vars}}'{{name}}': {{{datatype}}}{{#hasMore}},
{{/hasMore}}{{/vars}}
{{#vars}}
'{{name}}': {{{datatype}}}{{#hasMore}},{{/hasMore}}
{{/vars}}
}
self.attribute_map = {
{{#vars}}'{{name}}': '{{baseName}}'{{#hasMore}},
{{/hasMore}}{{/vars}}
}
{{#vars}}
'{{name}}': '{{baseName}}'{{#hasMore}},{{/hasMore}}
{{/vars}}
}
{{#vars}}{{#-first}}
{{/-first}}
self._{{name}} = {{name}}
{{/vars}}
@classmethod
def from_dict(cls, dikt){{^supportPython2}} -> '{{classname}}'{{/supportPython2}}:
"""
Returns the dict as a model
"""Returns the dict as a model
:param dikt: A dict.
:type: dict
:return: The {{name}} of this {{classname}}.
:return: The {{name}} of this {{classname}}. # noqa: E501
:rtype: {{classname}}
"""
return deserialize_model(dikt, cls)
{{#vars}}{{#-first}}
return util.deserialize_model(dikt, cls){{#vars}}{{#-first}}
{{/-first}}
@property
def {{name}}(self){{^supportPython2}} -> {{datatype}}{{/supportPython2}}:
"""
Gets the {{name}} of this {{classname}}.
"""Gets the {{name}} of this {{classname}}.
{{#description}}
{{{description}}}
{{{description}}} # noqa: E501
{{/description}}
:return: The {{name}} of this {{classname}}.
@@ -77,31 +78,31 @@ class {{classname}}(Model):
@{{name}}.setter
def {{name}}(self, {{name}}{{^supportPython2}}: {{datatype}}{{/supportPython2}}):
"""
Sets the {{name}} of this {{classname}}.
"""Sets the {{name}} of this {{classname}}.
{{#description}}
{{{description}}}
{{{description}}} # noqa: E501
{{/description}}
:param {{name}}: The {{name}} of this {{classname}}.
:type {{name}}: {{datatype}}
"""
{{#isEnum}}
allowed_values = [{{#allowableValues}}{{#values}}"{{{this}}}"{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}]
allowed_values = [{{#allowableValues}}{{#values}}"{{{this}}}"{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501
{{#isContainer}}
{{#isListContainer}}
if not set({{{name}}}).issubset(set(allowed_values)):
raise ValueError(
"Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]"
.format(", ".join(map(str, set({{{name}}})-set(allowed_values))),
"Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501
.format(", ".join(map(str, set({{{name}}})-set(allowed_values))), # noqa: E501
", ".join(map(str, allowed_values)))
)
{{/isListContainer}}
{{#isMapContainer}}
if not set({{{name}}}.keys()).issubset(set(allowed_values)):
raise ValueError(
"Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]"
.format(", ".join(map(str, set({{{name}}}.keys())-set(allowed_values))),
"Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501
.format(", ".join(map(str, set({{{name}}}.keys())-set(allowed_values))), # noqa: E501
", ".join(map(str, allowed_values)))
)
{{/isMapContainer}}
@@ -117,42 +118,44 @@ class {{classname}}(Model):
{{^isEnum}}
{{#required}}
if {{name}} is None:
raise ValueError("Invalid value for `{{name}}`, must not be `None`")
raise ValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501
{{/required}}
{{#hasValidation}}
{{#maxLength}}
if {{name}} is not None and len({{name}}) > {{maxLength}}:
raise ValueError("Invalid value for `{{name}}`, length must be less than or equal to `{{maxLength}}`")
raise ValueError("Invalid value for `{{name}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501
{{/maxLength}}
{{#minLength}}
if {{name}} is not None and len({{name}}) < {{minLength}}:
raise ValueError("Invalid value for `{{name}}`, length must be greater than or equal to `{{minLength}}`")
raise ValueError("Invalid value for `{{name}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501
{{/minLength}}
{{#maximum}}
if {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}:
raise ValueError("Invalid value for `{{name}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`")
if {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501
raise ValueError("Invalid value for `{{name}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501
{{/maximum}}
{{#minimum}}
if {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}:
raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`")
if {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501
raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501
{{/minimum}}
{{#pattern}}
if {{name}} is not None and not re.search('{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}):
raise ValueError("Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`")
if {{name}} is not None and not re.search('{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501
raise ValueError("Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`") # noqa: E501
{{/pattern}}
{{#maxItems}}
if {{name}} is not None and len({{name}}) > {{maxItems}}:
raise ValueError("Invalid value for `{{name}}`, number of items must be less than or equal to `{{maxItems}}`")
raise ValueError("Invalid value for `{{name}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501
{{/maxItems}}
{{#minItems}}
if {{name}} is not None and len({{name}}) < {{minItems}}:
raise ValueError("Invalid value for `{{name}}`, number of items must be greater than or equal to `{{minItems}}`")
raise ValueError("Invalid value for `{{name}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501
{{/minItems}}
{{/hasValidation}}
{{/isEnum}}
self._{{name}} = {{name}}
self._{{name}} = {{name}}{{^-last}}
{{/-last}}
{{/vars}}
{{/model}}
{{/models}}
{{/models}}

View File

@@ -1,11 +1,11 @@
from typing import GenericMeta
from datetime import datetime, date
from six import integer_types, iteritems
import datetime
import six
import typing
def _deserialize(data, klass):
"""
Deserializes dict, list, str into an object.
"""Deserializes dict, list, str into an object.
:param data: dict, list or str.
:param klass: class literal, or string of class name.
@@ -15,15 +15,15 @@ def _deserialize(data, klass):
if data is None:
return None
if klass in integer_types or klass in (float, str, bool):
if klass in six.integer_types or klass in (float, str, bool):
return _deserialize_primitive(data, klass)
elif klass == object:
return _deserialize_object(data)
elif klass == date:
elif klass == datetime.date:
return deserialize_date(data)
elif klass == datetime:
elif klass == datetime.datetime:
return deserialize_datetime(data)
elif type(klass) == GenericMeta:
elif type(klass) == typing.GenericMeta:
if klass.__extra__ == list:
return _deserialize_list(data, klass.__args__[0])
if klass.__extra__ == dict:
@@ -33,8 +33,7 @@ def _deserialize(data, klass):
def _deserialize_primitive(data, klass):
"""
Deserializes to primitive type.
"""Deserializes to primitive type.
:param data: data to deserialize.
:param klass: class literal.
@@ -52,8 +51,7 @@ def _deserialize_primitive(data, klass):
def _deserialize_object(value):
"""
Return a original value.
"""Return a original value.
:return: object.
"""
@@ -61,8 +59,7 @@ def _deserialize_object(value):
def deserialize_date(string):
"""
Deserializes string to date.
"""Deserializes string to date.
:param string: str.
:type string: str
@@ -77,8 +74,7 @@ def deserialize_date(string):
def deserialize_datetime(string):
"""
Deserializes string to datetime.
"""Deserializes string to datetime.
The string should be in iso8601 datetime format.
@@ -95,8 +91,7 @@ def deserialize_datetime(string):
def deserialize_model(data, klass):
"""
Deserializes list or dict to model.
"""Deserializes list or dict to model.
:param data: dict, list.
:type data: dict | list
@@ -108,7 +103,7 @@ def deserialize_model(data, klass):
if not instance.swagger_types:
return data
for attr, attr_type in iteritems(instance.swagger_types):
for attr, attr_type in six.iteritems(instance.swagger_types):
if data is not None \
and instance.attribute_map[attr] in data \
and isinstance(data, (list, dict)):
@@ -119,8 +114,7 @@ def deserialize_model(data, klass):
def _deserialize_list(data, boxed_type):
"""
Deserializes a list and its elements.
"""Deserializes a list and its elements.
:param data: list to deserialize.
:type data: list
@@ -133,10 +127,8 @@ def _deserialize_list(data, boxed_type):
for sub_data in data]
def _deserialize_dict(data, boxed_type):
"""
Deserializes a dict and its elements.
"""Deserializes a dict and its elements.
:param data: dict to deserialize.
:type data: dict
@@ -146,4 +138,4 @@ def _deserialize_dict(data, boxed_type):
:rtype: dict
"""
return {k: _deserialize(v, boxed_type)
for k, v in iteritems(data)}
for k, v in six.iteritems(data)}