forked from loafle/openapi-generator-original
The linting results for the generated samples are as follows where the first number is the BEFORE and the second is AFTER. pyclient 7714 vs. 120 pyclient3 7717 vs. 120 pyclient3-asyncio 7584 vs. 120 pyclient-tornado 7633 vs. 120 pyclient3-tornado 7633 vs. 120 For the complete details please see the following gist. https://gist.github.com/kenjones-cisco/2eb69a7e8db75e9fd53789f01570d9f2 Enforces linting for python clients by running flake8 for the generated python client.
251 lines
9.8 KiB
Plaintext
251 lines
9.8 KiB
Plaintext
# coding: utf-8
|
|
|
|
{{>partial_header}}
|
|
|
|
import io
|
|
import json
|
|
import logging
|
|
import re
|
|
import ssl
|
|
|
|
import aiohttp
|
|
import certifi
|
|
# python 2 and python 3 compatibility library
|
|
from six.moves.urllib.parse import urlencode
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class RESTResponse(io.IOBase):
|
|
|
|
def __init__(self, resp, data):
|
|
self.aiohttp_response = resp
|
|
self.status = resp.status
|
|
self.reason = resp.reason
|
|
self.data = data
|
|
|
|
def getheaders(self):
|
|
"""Returns a CIMultiDictProxy of the response headers."""
|
|
return self.aiohttp_response.headers
|
|
|
|
def getheader(self, name, default=None):
|
|
"""Returns a given response header."""
|
|
return self.aiohttp_response.headers.get(name, default)
|
|
|
|
|
|
class RESTClientObject(object):
|
|
|
|
def __init__(self, configuration, pools_size=4, maxsize=4):
|
|
# maxsize is number of requests to host that are allowed in parallel
|
|
# ca_certs vs cert_file vs key_file
|
|
# http://stackoverflow.com/a/23957365/2985775
|
|
|
|
# ca_certs
|
|
if configuration.ssl_ca_cert:
|
|
ca_certs = configuration.ssl_ca_cert
|
|
else:
|
|
# if not set certificate file, use Mozilla's root certificates.
|
|
ca_certs = certifi.where()
|
|
|
|
ssl_context = ssl.SSLContext()
|
|
ssl_context.load_verify_locations(cafile=ca_certs)
|
|
if configuration.cert_file:
|
|
ssl_context.load_cert_chain(
|
|
configuration.cert_file, keyfile=configuration.key_file
|
|
)
|
|
|
|
connector = aiohttp.TCPConnector(
|
|
limit=maxsize,
|
|
ssl_context=ssl_context,
|
|
verify_ssl=configuration.verify_ssl
|
|
)
|
|
|
|
# https pool manager
|
|
if configuration.proxy:
|
|
self.pool_manager = aiohttp.ClientSession(
|
|
connector=connector,
|
|
proxy=configuration.proxy
|
|
)
|
|
else:
|
|
self.pool_manager = aiohttp.ClientSession(
|
|
connector=connector
|
|
)
|
|
|
|
async def request(self, method, url, query_params=None, headers=None,
|
|
body=None, post_params=None, _preload_content=True,
|
|
_request_timeout=None):
|
|
"""Execute request
|
|
|
|
:param method: http request method
|
|
:param url: http request url
|
|
:param query_params: query parameters in the url
|
|
:param headers: http request headers
|
|
:param body: request json body, for `application/json`
|
|
:param post_params: request post parameters,
|
|
`application/x-www-form-urlencoded`
|
|
and `multipart/form-data`
|
|
:param _preload_content: this is a non-applicable field for
|
|
the AiohttpClient.
|
|
:param _request_timeout: timeout setting for this request. If one
|
|
number provided, it will be total request
|
|
timeout. It can also be a pair (tuple) of
|
|
(connection, read) timeouts.
|
|
"""
|
|
method = method.upper()
|
|
assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT',
|
|
'PATCH', 'OPTIONS']
|
|
|
|
if post_params and body:
|
|
raise ValueError(
|
|
"body parameter cannot be used with post_params parameter."
|
|
)
|
|
|
|
post_params = post_params or {}
|
|
headers = headers or {}
|
|
timeout = _request_timeout or 5 * 60
|
|
|
|
if 'Content-Type' not in headers:
|
|
headers['Content-Type'] = 'application/json'
|
|
|
|
args = {
|
|
"method": method,
|
|
"url": url,
|
|
"timeout": timeout,
|
|
"headers": headers
|
|
}
|
|
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
|
|
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
|
|
if query_params:
|
|
url += '?' + urlencode(query_params)
|
|
if re.search('json', headers['Content-Type'], re.IGNORECASE):
|
|
if body is not None:
|
|
body = json.dumps(body)
|
|
args["data"] = body
|
|
elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501
|
|
data = aiohttp.FormData()
|
|
for k, v in post_params.items():
|
|
data.add_field(k, v)
|
|
args["data"] = data
|
|
elif headers['Content-Type'] == 'multipart/form-data':
|
|
args["data"] = post_params
|
|
# Pass a `bytes` parameter directly in the body to support
|
|
# other content types than Json when `body` argument is provided
|
|
# in serialized form
|
|
elif isinstance(body, bytes):
|
|
args["data"] = body
|
|
else:
|
|
# Cannot generate the request from given parameters
|
|
msg = """Cannot prepare a request message for provided
|
|
arguments. Please check that your arguments match
|
|
declared content type."""
|
|
raise ApiException(status=0, reason=msg)
|
|
else:
|
|
args["data"] = query_params
|
|
|
|
async with self.pool_manager.request(**args) as r:
|
|
data = await r.text()
|
|
r = RESTResponse(r, data)
|
|
|
|
# log response body
|
|
logger.debug("response body: %s", r.data)
|
|
|
|
if not 200 <= r.status <= 299:
|
|
raise ApiException(http_resp=r)
|
|
|
|
return r
|
|
|
|
async def GET(self, url, headers=None, query_params=None,
|
|
_preload_content=True, _request_timeout=None):
|
|
return (await self.request("GET", url,
|
|
headers=headers,
|
|
_preload_content=_preload_content,
|
|
_request_timeout=_request_timeout,
|
|
query_params=query_params))
|
|
|
|
async def HEAD(self, url, headers=None, query_params=None,
|
|
_preload_content=True, _request_timeout=None):
|
|
return (await self.request("HEAD", url,
|
|
headers=headers,
|
|
_preload_content=_preload_content,
|
|
_request_timeout=_request_timeout,
|
|
query_params=query_params))
|
|
|
|
async def OPTIONS(self, url, headers=None, query_params=None,
|
|
post_params=None, body=None, _preload_content=True,
|
|
_request_timeout=None):
|
|
return (await self.request("OPTIONS", url,
|
|
headers=headers,
|
|
query_params=query_params,
|
|
post_params=post_params,
|
|
_preload_content=_preload_content,
|
|
_request_timeout=_request_timeout,
|
|
body=body))
|
|
|
|
async def DELETE(self, url, headers=None, query_params=None, body=None,
|
|
_preload_content=True, _request_timeout=None):
|
|
return (await self.request("DELETE", url,
|
|
headers=headers,
|
|
query_params=query_params,
|
|
_preload_content=_preload_content,
|
|
_request_timeout=_request_timeout,
|
|
body=body))
|
|
|
|
async def POST(self, url, headers=None, query_params=None,
|
|
post_params=None, body=None, _preload_content=True,
|
|
_request_timeout=None):
|
|
return (await self.request("POST", url,
|
|
headers=headers,
|
|
query_params=query_params,
|
|
post_params=post_params,
|
|
_preload_content=_preload_content,
|
|
_request_timeout=_request_timeout,
|
|
body=body))
|
|
|
|
async def PUT(self, url, headers=None, query_params=None, post_params=None,
|
|
body=None, _preload_content=True, _request_timeout=None):
|
|
return (await self.request("PUT", url,
|
|
headers=headers,
|
|
query_params=query_params,
|
|
post_params=post_params,
|
|
_preload_content=_preload_content,
|
|
_request_timeout=_request_timeout,
|
|
body=body))
|
|
|
|
async def PATCH(self, url, headers=None, query_params=None,
|
|
post_params=None, body=None, _preload_content=True,
|
|
_request_timeout=None):
|
|
return (await self.request("PATCH", url,
|
|
headers=headers,
|
|
query_params=query_params,
|
|
post_params=post_params,
|
|
_preload_content=_preload_content,
|
|
_request_timeout=_request_timeout,
|
|
body=body))
|
|
|
|
|
|
class ApiException(Exception):
|
|
|
|
def __init__(self, status=None, reason=None, http_resp=None):
|
|
if http_resp:
|
|
self.status = http_resp.status
|
|
self.reason = http_resp.reason
|
|
self.body = http_resp.data
|
|
self.headers = http_resp.getheaders()
|
|
else:
|
|
self.status = status
|
|
self.reason = reason
|
|
self.body = None
|
|
self.headers = None
|
|
|
|
def __str__(self):
|
|
"""Custom error messages for exception"""
|
|
error_message = "({0})\nReason: {1}\n".format(self.status, self.reason)
|
|
if self.headers:
|
|
error_message += "HTTP response headers: {0}\n".format(
|
|
self.headers)
|
|
|
|
if self.body:
|
|
error_message += "HTTP response body: {0}\n".format(self.body)
|
|
|
|
return error_message
|