Merge pull request #941 from geekerzp/develop_2.0_python_async

[Python] Support asynchronous request in python client
This commit is contained in:
wing328
2015-07-16 10:47:02 +08:00
14 changed files with 702 additions and 200 deletions

View File

@@ -8,3 +8,7 @@ from __future__ import absolute_import
{{/apis}}{{/apiInfo}}
# import ApiClient
from .api_client import ApiClient
from .configuration import Configuration
configuration = Configuration()

View File

@@ -27,19 +27,20 @@ import os
# python 2 and python 3 compatibility library
from six import iteritems
from .. import configuration
from ..configuration import Configuration
from ..api_client import ApiClient
{{#operations}}
class {{classname}}(object):
def __init__(self, api_client=None):
config = Configuration()
if api_client:
self.api_client = api_client
else:
if not configuration.api_client:
configuration.api_client = ApiClient('{{basePath}}')
self.api_client = configuration.api_client
if not config.api_client:
config.api_client = ApiClient('{{basePath}}')
self.api_client = config.api_client
{{#operation}}
def {{nickname}}(self, {{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}**kwargs):
@@ -47,9 +48,18 @@ class {{classname}}(object):
{{{summary}}}
{{{notes}}}
{{#allParams}}:param {{dataType}} {{paramName}}: {{{description}}} {{#required}}(required){{/required}}{{^required}}(optional){{/required}}
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.{{nickname}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
{{#allParams}}:param {{dataType}} {{paramName}}: {{{description}}} {{#required}}(required){{/required}}{{#optional}}(optional){{/optional}}
{{/allParams}}
:return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}}
If the method is called asynchronously, returns the request thread.
"""
{{#allParams}}{{#required}}
# verify the required parameter '{{paramName}}' is set
@@ -57,6 +67,7 @@ class {{classname}}(object):
raise ValueError("Missing the required parameter `{{paramName}}` when calling `{{nickname}}`")
{{/required}}{{/allParams}}
all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}]
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -107,17 +118,7 @@ class {{classname}}(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, auth_settings=auth_settings)
{{#returnType}}
response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, auth_settings=auth_settings, callback=params.get('callback'))
return response
{{/returnType}}{{/operation}}
{{/operation}}
{{/operations}}

View File

@@ -15,10 +15,13 @@ import os
import re
import urllib
import json
import datetime
import mimetypes
import random
import tempfile
import threading
from datetime import datetime
from datetime import date
# python 2 and python 3 compatibility library
from six import iteritems
@@ -30,7 +33,7 @@ except ImportError:
# for python2
from urllib import quote
from . import configuration
from .configuration import Configuration
class ApiClient(object):
"""
@@ -40,7 +43,7 @@ class ApiClient(object):
:param header_name: a header to pass when making calls to the API
:param header_value: a header value to pass when making calls to the API
"""
def __init__(self, host=configuration.host, header_name=None, header_value=None):
def __init__(self, host=Configuration().host, header_name=None, header_value=None):
self.default_headers = {}
if header_name is not None:
self.default_headers[header_name] = header_value
@@ -60,8 +63,8 @@ class ApiClient(object):
def set_default_header(self, header_name, header_value):
self.default_headers[header_name] = header_value
def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None,
body=None, post_params=None, files=None, response_type=None, auth_settings=None):
def __call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None,
body=None, post_params=None, files=None, response_type=None, auth_settings=None, callback=None):
# headers parameters
header_params = header_params or {}
@@ -106,9 +109,14 @@ class ApiClient(object):
# deserialize response data
if response_type:
return self.deserialize(response_data, response_type)
deserialized_data = self.deserialize(response_data, response_type)
else:
return None
deserialized_data = None
if callback:
callback(deserialized_data)
else:
return deserialized_data
def to_path_value(self, obj):
"""
@@ -140,7 +148,7 @@ class ApiClient(object):
return obj
elif isinstance(obj, list):
return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj]
elif isinstance(obj, (datetime.datetime, datetime.date)):
elif isinstance(obj, (datetime, date)):
return obj.isoformat()
else:
if isinstance(obj, dict):
@@ -197,7 +205,7 @@ class ApiClient(object):
# convert str to class
# for native types
if klass in ['int', 'float', 'str', 'bool', 'datetime', "object"]:
if klass in ['int', 'float', 'str', 'bool', "date", 'datetime', "object"]:
klass = eval(klass)
# for model types
else:
@@ -207,12 +215,54 @@ class ApiClient(object):
return self.__deserialize_primitive(data, klass)
elif klass == object:
return self.__deserialize_object()
elif klass == date:
return self.__deserialize_date(data)
elif klass == datetime:
return self.__deserialize_datatime(data)
else:
return self.__deserialize_model(data, klass)
def request(self, method, url, query_params=None, headers=None, post_params=None, body=None):
def call_api(self, resource_path, method,
path_params=None, query_params=None, header_params=None,
body=None, post_params=None, files=None,
response_type=None, auth_settings=None, callback=None):
"""
Perform http request and return deserialized data
:param resource_path: Path to method endpoint.
:param method: Method to call.
:param path_params: Path parameters in the url.
:param query_params: Query parameters in the url.
:param header_params: Header parameters to be placed in the request header.
:param body: Request body.
:param post_params dict: Request post form parameters, for `application/x-www-form-urlencoded`, `multipart/form-data`.
:param auth_settings list: Auth Settings names for the request.
:param response: Response data type.
:param files dict: key -> filename, value -> filepath, for `multipart/form-data`.
:param callback function: Callback function for asynchronous request.
If provide this parameter, the request will be called asynchronously.
:return:
If provide parameter callback, the request will be called asynchronously.
The method will return the request thread.
If parameter callback is None, then the method will return the response directly.
"""
if callback is None:
return self.__call_api(resource_path, method,
path_params, query_params, header_params,
body, post_params, files,
response_type, auth_settings, callback)
else:
thread = threading.Thread(target=self.__call_api,
args=(resource_path, method,
path_params, query_params, header_params,
body, post_params, files,
response_type, auth_settings, callback))
thread.start()
return thread
def request(self, method, url, query_params=None, headers=None,
post_params=None, body=None):
"""
Perform http request using RESTClient.
"""
@@ -280,11 +330,13 @@ class ApiClient(object):
"""
Update header and query params based on authentication setting
"""
config = Configuration()
if not auth_settings:
return
for auth in auth_settings:
auth_setting = configuration.auth_settings().get(auth)
auth_setting = config.auth_settings().get(auth)
if auth_setting:
if auth_setting['in'] == 'header':
headers[auth_setting['key']] = auth_setting['value']
@@ -338,6 +390,21 @@ class ApiClient(object):
"""
return object()
def __deserialize_date(self, string):
"""
Deserialize string to date
:param string: str
:return: date
"""
try:
from dateutil.parser import parse
return parse(string).date()
except ImportError:
return string
except ValueError:
raise ApiException(status=0, reason="Failed to parse `{0}` into a date object".format(string))
def __deserialize_datatime(self, string):
"""
Deserialize string to datetime.

View File

@@ -1,52 +1,121 @@
from __future__ import absolute_import
import base64
import urllib3
import httplib
import sys
import logging
def get_api_key_with_prefix(key):
global api_key
global api_key_prefix
def singleton(cls, *args, **kw):
instances = {}
if api_key.get(key) and api_key_prefix.get(key):
return api_key_prefix[key] + ' ' + api_key[key]
elif api_key.get(key):
return api_key[key]
def _singleton():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return _singleton
def get_basic_auth_token():
global username
global password
return urllib3.util.make_headers(basic_auth=username + ':' + password).get('authorization')
@singleton
class Configuration(object):
def auth_settings():
return { {{#authMethods}}{{#isApiKey}}
'{{name}}': {
'type': 'api_key',
'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}},
'key': '{{keyParamName}}',
'value': get_api_key_with_prefix('{{keyParamName}}')
},
{{/isApiKey}}{{#isBasic}}
'{{name}}': {
'type': 'basic',
'in': 'header',
'key': 'Authorization',
'value': get_basic_auth_token()
},
{{/isBasic}}{{/authMethods}}
}
def __init__(self):
# Default Base url
self.host = "{{basePath}}"
# Default api client
self.api_client = None
# Authentication Settings
self.api_key = {}
self.api_key_prefix = {}
self.username = ""
self.password = ""
# Logging Settings
self.logging_format = '%(asctime)s %(levelname)s %(message)s'
self.__logging_file = None
self.__debug = False
self.init_logger()
# Default Base url
host = "{{basePath}}"
def init_logger(self):
self.logger = logging.getLogger()
formatter = logging.Formatter(self.logging_format)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
self.logger.addHandler(stream_handler)
if self.__debug:
self.logger.setLevel(logging.DEBUG)
else:
self.logger.setLevel(logging.WARNING)
if self.__logging_file:
file_handler = logging.FileHandler(self.__logging_file)
file_handler.setFormatter(formatter)
self.logger.addFilter(file_handler)
@property
def logging_file(self):
return self.__logging_file
@logging_file.setter
def logging_file(self, value):
self.__logging_file = value
if self.__logging_file:
formater = logging.Formatter(self.logging_format)
file_handler = logging.FileHandler(self.__logging_file)
file_handler.setFormatter(formater)
self.logger.addHandler(file_handler)
@property
def debug(self):
return self.__debug
@debug.setter
def debug(self, value):
self.__debug = value
if self.__debug:
# if debug status is True, turn on debug logging
self.logger.setLevel(logging.DEBUG)
# turn on httplib debug
httplib.HTTPConnection.debuglevel = 1
else:
# if debug status is False, turn off debug logging,
# setting log level to default `logging.WARNING`
self.logger.setLevel(logging.WARNING)
def get_api_key_with_prefix(self, key):
""" Return api key prepend prefix for key """
if self.api_key.get(key) and self.api_key_prefix.get(key):
return self.api_key_prefix[key] + ' ' + self.api_key[key]
elif self.api_key.get(key):
return self.api_key[key]
def get_basic_auth_token(self):
""" Return basic auth header string """
return urllib3.util.make_headers(basic_auth=self.username + ':' + self.password)\
.get('authorization')
def auth_settings(self):
""" Return Auth Settings for api client """
return { {{#authMethods}}{{#isApiKey}}
'{{name}}': {
'type': 'api_key',
'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}},
'key': '{{keyParamName}}',
'value': self.get_api_key_with_prefix('{{keyParamName}}')
},
{{/isApiKey}}{{#isBasic}}
'{{name}}': {
'type': 'basic',
'in': 'header',
'key': 'Authorization',
'value': self.get_basic_auth_token()
},
{{/isBasic}}{{/authMethods}}
}
def to_debug_report(self):
return "Python SDK Debug Report:\n"\
"OS: {env}\n"\
"Python Version: {pyversion}\n"\
"Version of the API: {{version}}\n"\
"SDK Package Version: {{packageVersion}}".format(env=sys.platform, pyversion=sys.version)
# Default api client
api_client = None
# Authentication settings
api_key = {}
api_key_prefix = {}
username = ''
password = ''
# Temp foloder for file download
temp_folder_path = None

View File

@@ -10,6 +10,7 @@ import io
import json
import ssl
import certifi
import logging
# python 2 and python 3 compatibility library
from six import iteritems
@@ -27,6 +28,9 @@ except ImportError:
from urllib import urlencode
logger = logging.getLogger(__name__)
class RESTResponse(io.IOBase):
def __init__(self, resp):
@@ -65,9 +69,10 @@ class RESTClientObject(object):
def agent(self, url):
"""
Return proper pool manager for the http\https schemes.
Use `urllib3.util.parse_url` for backward compatibility.
Return proper pool manager for the http/https schemes.
"""
url = urllib3.util.url.parse_url(url)
url = urllib3.util.parse_url(url)
scheme = url.scheme
if scheme == 'https':
return self.ssl_pool_manager
@@ -130,6 +135,9 @@ class RESTClientObject(object):
if sys.version_info > (3,):
r.data = r.data.decode('utf8')
# log response body
logger.debug("response body: %s" % r.data)
if r.status not in range(200, 206):
raise ApiException(http_resp=r)

View File

@@ -14,3 +14,7 @@ from .apis.store_api import StoreApi
# import ApiClient
from .api_client import ApiClient
from .configuration import Configuration
configuration = Configuration()

View File

@@ -15,10 +15,13 @@ import os
import re
import urllib
import json
import datetime
import mimetypes
import random
import tempfile
import threading
from datetime import datetime
from datetime import date
# python 2 and python 3 compatibility library
from six import iteritems
@@ -30,7 +33,7 @@ except ImportError:
# for python2
from urllib import quote
from . import configuration
from .configuration import Configuration
class ApiClient(object):
"""
@@ -40,7 +43,7 @@ class ApiClient(object):
:param header_name: a header to pass when making calls to the API
:param header_value: a header value to pass when making calls to the API
"""
def __init__(self, host=configuration.host, header_name=None, header_value=None):
def __init__(self, host=Configuration().host, header_name=None, header_value=None):
self.default_headers = {}
if header_name is not None:
self.default_headers[header_name] = header_value
@@ -60,8 +63,8 @@ class ApiClient(object):
def set_default_header(self, header_name, header_value):
self.default_headers[header_name] = header_value
def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None,
body=None, post_params=None, files=None, response_type=None, auth_settings=None):
def __call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None,
body=None, post_params=None, files=None, response_type=None, auth_settings=None, callback=None):
# headers parameters
header_params = header_params or {}
@@ -106,9 +109,14 @@ class ApiClient(object):
# deserialize response data
if response_type:
return self.deserialize(response_data, response_type)
deserialized_data = self.deserialize(response_data, response_type)
else:
return None
deserialized_data = None
if callback:
callback(deserialized_data)
else:
return deserialized_data
def to_path_value(self, obj):
"""
@@ -140,7 +148,7 @@ class ApiClient(object):
return obj
elif isinstance(obj, list):
return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj]
elif isinstance(obj, (datetime.datetime, datetime.date)):
elif isinstance(obj, (datetime, date)):
return obj.isoformat()
else:
if isinstance(obj, dict):
@@ -197,7 +205,7 @@ class ApiClient(object):
# convert str to class
# for native types
if klass in ['int', 'float', 'str', 'bool', 'datetime', "object"]:
if klass in ['int', 'float', 'str', 'bool', "date", 'datetime', "object"]:
klass = eval(klass)
# for model types
else:
@@ -207,12 +215,54 @@ class ApiClient(object):
return self.__deserialize_primitive(data, klass)
elif klass == object:
return self.__deserialize_object()
elif klass == date:
return self.__deserialize_date(data)
elif klass == datetime:
return self.__deserialize_datatime(data)
else:
return self.__deserialize_model(data, klass)
def request(self, method, url, query_params=None, headers=None, post_params=None, body=None):
def call_api(self, resource_path, method,
path_params=None, query_params=None, header_params=None,
body=None, post_params=None, files=None,
response_type=None, auth_settings=None, callback=None):
"""
Perform http request and return deserialized data
:param resource_path: Path to method endpoint.
:param method: Method to call.
:param path_params: Path parameters in the url.
:param query_params: Query parameters in the url.
:param header_params: Header parameters to be placed in the request header.
:param body: Request body.
:param post_params dict: Request post form parameters, for `application/x-www-form-urlencoded`, `multipart/form-data`.
:param auth_settings list: Auth Settings names for the request.
:param response: Response data type.
:param files dict: key -> filename, value -> filepath, for `multipart/form-data`.
:param callback function: Callback function for asynchronous request.
If provide this parameter, the request will be called asynchronously.
:return:
If provide parameter callback, the request will be called asynchronously.
The method will return the request thread.
If parameter callback is None, then the method will return the response directly.
"""
if callback is None:
return self.__call_api(resource_path, method,
path_params, query_params, header_params,
body, post_params, files,
response_type, auth_settings, callback)
else:
thread = threading.Thread(target=self.__call_api,
args=(resource_path, method,
path_params, query_params, header_params,
body, post_params, files,
response_type, auth_settings, callback))
thread.start()
return thread
def request(self, method, url, query_params=None, headers=None,
post_params=None, body=None):
"""
Perform http request using RESTClient.
"""
@@ -280,11 +330,13 @@ class ApiClient(object):
"""
Update header and query params based on authentication setting
"""
config = Configuration()
if not auth_settings:
return
for auth in auth_settings:
auth_setting = configuration.auth_settings().get(auth)
auth_setting = config.auth_settings().get(auth)
if auth_setting:
if auth_setting['in'] == 'header':
headers[auth_setting['key']] = auth_setting['value']
@@ -338,6 +390,21 @@ class ApiClient(object):
"""
return object()
def __deserialize_date(self, string):
"""
Deserialize string to date
:param string: str
:return: date
"""
try:
from dateutil.parser import parse
return parse(string).date()
except ImportError:
return string
except ValueError:
raise ApiException(status=0, reason="Failed to parse `{0}` into a date object".format(string))
def __deserialize_datatime(self, string):
"""
Deserialize string to datetime.

View File

@@ -27,18 +27,19 @@ import os
# python 2 and python 3 compatibility library
from six import iteritems
from .. import configuration
from ..configuration import Configuration
from ..api_client import ApiClient
class PetApi(object):
def __init__(self, api_client=None):
config = Configuration()
if api_client:
self.api_client = api_client
else:
if not configuration.api_client:
configuration.api_client = ApiClient('http://petstore.swagger.io/v2')
self.api_client = configuration.api_client
if not config.api_client:
config.api_client = ApiClient('http://petstore.swagger.io/v2')
self.api_client = config.api_client
def update_pet(self, **kwargs):
@@ -46,12 +47,22 @@ class PetApi(object):
Update an existing pet
:param Pet body: Pet object that needs to be added to the store (optional)
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.update_pet(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param Pet body: Pet object that needs to be added to the store
:return: None
If the method is called asynchronously, returns the request thread.
"""
all_params = ['body']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -90,19 +101,30 @@ class PetApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response
def add_pet(self, **kwargs):
"""
Add a new pet to the store
:param Pet body: Pet object that needs to be added to the store (optional)
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.add_pet(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param Pet body: Pet object that needs to be added to the store
:return: None
If the method is called asynchronously, returns the request thread.
"""
all_params = ['body']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -141,19 +163,30 @@ class PetApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response
def find_pets_by_status(self, **kwargs):
"""
Finds Pets by status
Multiple status values can be provided with comma seperated strings
:param list[str] status: Status values that need to be considered for filter (optional)
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.find_pets_by_status(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param list[str] status: Status values that need to be considered for filter
:return: list[Pet]
If the method is called asynchronously, returns the request thread.
"""
all_params = ['status']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -192,8 +225,7 @@ class PetApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type='list[Pet]', auth_settings=auth_settings)
response_type='list[Pet]', auth_settings=auth_settings, callback=params.get('callback'))
return response
def find_pets_by_tags(self, **kwargs):
@@ -201,12 +233,22 @@ class PetApi(object):
Finds Pets by tags
Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.
:param list[str] tags: Tags to filter by (optional)
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.find_pets_by_tags(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param list[str] tags: Tags to filter by
:return: list[Pet]
If the method is called asynchronously, returns the request thread.
"""
all_params = ['tags']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -245,8 +287,7 @@ class PetApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type='list[Pet]', auth_settings=auth_settings)
response_type='list[Pet]', auth_settings=auth_settings, callback=params.get('callback'))
return response
def get_pet_by_id(self, pet_id, **kwargs):
@@ -254,9 +295,18 @@ class PetApi(object):
Find pet by ID
Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.get_pet_by_id(pet_id, callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param int pet_id: ID of pet that needs to be fetched (required)
:return: Pet
If the method is called asynchronously, returns the request thread.
"""
# verify the required parameter 'pet_id' is set
@@ -264,6 +314,7 @@ class PetApi(object):
raise ValueError("Missing the required parameter `pet_id` when calling `get_pet_by_id`")
all_params = ['pet_id']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -302,8 +353,7 @@ class PetApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type='Pet', auth_settings=auth_settings)
response_type='Pet', auth_settings=auth_settings, callback=params.get('callback'))
return response
def update_pet_with_form(self, pet_id, **kwargs):
@@ -311,11 +361,20 @@ class PetApi(object):
Updates a pet in the store with form data
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.update_pet_with_form(pet_id, callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param str pet_id: ID of pet that needs to be updated (required)
:param str name: Updated name of the pet (optional)
:param str status: Updated status of the pet (optional)
:param str name: Updated name of the pet
:param str status: Updated status of the pet
:return: None
If the method is called asynchronously, returns the request thread.
"""
# verify the required parameter 'pet_id' is set
@@ -323,6 +382,7 @@ class PetApi(object):
raise ValueError("Missing the required parameter `pet_id` when calling `update_pet_with_form`")
all_params = ['pet_id', 'name', 'status']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -367,17 +427,27 @@ class PetApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response
def delete_pet(self, pet_id, **kwargs):
"""
Deletes a pet
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.delete_pet(pet_id, callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param int pet_id: Pet id to delete (required)
:param str api_key: (optional)
:param str api_key:
:return: None
If the method is called asynchronously, returns the request thread.
"""
# verify the required parameter 'pet_id' is set
@@ -385,6 +455,7 @@ class PetApi(object):
raise ValueError("Missing the required parameter `pet_id` when calling `delete_pet`")
all_params = ['pet_id', 'api_key']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -426,18 +497,28 @@ class PetApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response
def upload_file(self, pet_id, **kwargs):
"""
uploads an image
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.upload_file(pet_id, callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param int pet_id: ID of pet to update (required)
:param str additional_metadata: Additional data to pass to server (optional)
:param file file: file to upload (optional)
:param str additional_metadata: Additional data to pass to server
:param file file: file to upload
:return: None
If the method is called asynchronously, returns the request thread.
"""
# verify the required parameter 'pet_id' is set
@@ -445,6 +526,7 @@ class PetApi(object):
raise ValueError("Missing the required parameter `pet_id` when calling `upload_file`")
all_params = ['pet_id', 'additional_metadata', 'file']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -489,14 +571,6 @@ class PetApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response

View File

@@ -27,18 +27,19 @@ import os
# python 2 and python 3 compatibility library
from six import iteritems
from .. import configuration
from ..configuration import Configuration
from ..api_client import ApiClient
class StoreApi(object):
def __init__(self, api_client=None):
config = Configuration()
if api_client:
self.api_client = api_client
else:
if not configuration.api_client:
configuration.api_client = ApiClient('http://petstore.swagger.io/v2')
self.api_client = configuration.api_client
if not config.api_client:
config.api_client = ApiClient('http://petstore.swagger.io/v2')
self.api_client = config.api_client
def get_inventory(self, **kwargs):
@@ -46,11 +47,21 @@ class StoreApi(object):
Returns pet inventories by status
Returns a map of status codes to quantities
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.get_inventory(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:return: dict(str, int)
If the method is called asynchronously, returns the request thread.
"""
all_params = []
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -86,8 +97,7 @@ class StoreApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type='dict(str, int)', auth_settings=auth_settings)
response_type='dict(str, int)', auth_settings=auth_settings, callback=params.get('callback'))
return response
def place_order(self, **kwargs):
@@ -95,12 +105,22 @@ class StoreApi(object):
Place an order for a pet
:param Order body: order placed for purchasing the pet (optional)
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.place_order(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param Order body: order placed for purchasing the pet
:return: Order
If the method is called asynchronously, returns the request thread.
"""
all_params = ['body']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -139,8 +159,7 @@ class StoreApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type='Order', auth_settings=auth_settings)
response_type='Order', auth_settings=auth_settings, callback=params.get('callback'))
return response
def get_order_by_id(self, order_id, **kwargs):
@@ -148,9 +167,18 @@ class StoreApi(object):
Find purchase order by ID
For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.get_order_by_id(order_id, callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param str order_id: ID of pet that needs to be fetched (required)
:return: Order
If the method is called asynchronously, returns the request thread.
"""
# verify the required parameter 'order_id' is set
@@ -158,6 +186,7 @@ class StoreApi(object):
raise ValueError("Missing the required parameter `order_id` when calling `get_order_by_id`")
all_params = ['order_id']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -196,8 +225,7 @@ class StoreApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type='Order', auth_settings=auth_settings)
response_type='Order', auth_settings=auth_settings, callback=params.get('callback'))
return response
def delete_order(self, order_id, **kwargs):
@@ -205,9 +233,18 @@ class StoreApi(object):
Delete purchase order by ID
For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.delete_order(order_id, callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param str order_id: ID of the order that needs to be deleted (required)
:return: None
If the method is called asynchronously, returns the request thread.
"""
# verify the required parameter 'order_id' is set
@@ -215,6 +252,7 @@ class StoreApi(object):
raise ValueError("Missing the required parameter `order_id` when calling `delete_order`")
all_params = ['order_id']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -253,14 +291,6 @@ class StoreApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response

View File

@@ -27,18 +27,19 @@ import os
# python 2 and python 3 compatibility library
from six import iteritems
from .. import configuration
from ..configuration import Configuration
from ..api_client import ApiClient
class UserApi(object):
def __init__(self, api_client=None):
config = Configuration()
if api_client:
self.api_client = api_client
else:
if not configuration.api_client:
configuration.api_client = ApiClient('http://petstore.swagger.io/v2')
self.api_client = configuration.api_client
if not config.api_client:
config.api_client = ApiClient('http://petstore.swagger.io/v2')
self.api_client = config.api_client
def create_user(self, **kwargs):
@@ -46,12 +47,22 @@ class UserApi(object):
Create user
This can only be done by the logged in user.
:param User body: Created user object (optional)
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.create_user(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param User body: Created user object
:return: None
If the method is called asynchronously, returns the request thread.
"""
all_params = ['body']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -90,19 +101,30 @@ class UserApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response
def create_users_with_array_input(self, **kwargs):
"""
Creates list of users with given input array
:param list[User] body: List of user object (optional)
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.create_users_with_array_input(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param list[User] body: List of user object
:return: None
If the method is called asynchronously, returns the request thread.
"""
all_params = ['body']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -141,19 +163,30 @@ class UserApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response
def create_users_with_list_input(self, **kwargs):
"""
Creates list of users with given input array
:param list[User] body: List of user object (optional)
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.create_users_with_list_input(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param list[User] body: List of user object
:return: None
If the method is called asynchronously, returns the request thread.
"""
all_params = ['body']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -192,20 +225,31 @@ class UserApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response
def login_user(self, **kwargs):
"""
Logs user into the system
:param str username: The user name for login (optional)
:param str password: The password for login in clear text (optional)
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.login_user(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param str username: The user name for login
:param str password: The password for login in clear text
:return: str
If the method is called asynchronously, returns the request thread.
"""
all_params = ['username', 'password']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -247,8 +291,7 @@ class UserApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type='str', auth_settings=auth_settings)
response_type='str', auth_settings=auth_settings, callback=params.get('callback'))
return response
def logout_user(self, **kwargs):
@@ -256,11 +299,21 @@ class UserApi(object):
Logs out current logged in user session
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.logout_user(callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:return: None
If the method is called asynchronously, returns the request thread.
"""
all_params = []
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -296,16 +349,26 @@ class UserApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response
def get_user_by_name(self, username, **kwargs):
"""
Get user by user name
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.get_user_by_name(username, callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param str username: The name that needs to be fetched. Use user1 for testing. (required)
:return: User
If the method is called asynchronously, returns the request thread.
"""
# verify the required parameter 'username' is set
@@ -313,6 +376,7 @@ class UserApi(object):
raise ValueError("Missing the required parameter `username` when calling `get_user_by_name`")
all_params = ['username']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -351,8 +415,7 @@ class UserApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type='User', auth_settings=auth_settings)
response_type='User', auth_settings=auth_settings, callback=params.get('callback'))
return response
def update_user(self, username, **kwargs):
@@ -360,10 +423,19 @@ class UserApi(object):
Updated user
This can only be done by the logged in user.
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.update_user(username, callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param str username: name that need to be deleted (required)
:param User body: Updated user object (optional)
:param User body: Updated user object
:return: None
If the method is called asynchronously, returns the request thread.
"""
# verify the required parameter 'username' is set
@@ -371,6 +443,7 @@ class UserApi(object):
raise ValueError("Missing the required parameter `username` when calling `update_user`")
all_params = ['username', 'body']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -412,16 +485,26 @@ class UserApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response
def delete_user(self, username, **kwargs):
"""
Delete user
This can only be done by the logged in user.
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.delete_user(username, callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
:param str username: The name that needs to be deleted (required)
:return: None
If the method is called asynchronously, returns the request thread.
"""
# verify the required parameter 'username' is set
@@ -429,6 +512,7 @@ class UserApi(object):
raise ValueError("Missing the required parameter `username` when calling `delete_user`")
all_params = ['username']
all_params.append('callback')
params = locals()
for key, val in iteritems(params['kwargs']):
@@ -467,14 +551,6 @@ class UserApi(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,
response_type=None, auth_settings=auth_settings)
response_type=None, auth_settings=auth_settings, callback=params.get('callback'))
return response

View File

@@ -1,45 +1,114 @@
from __future__ import absolute_import
import base64
import urllib3
import httplib
import sys
import logging
def get_api_key_with_prefix(key):
global api_key
global api_key_prefix
def singleton(cls, *args, **kw):
instances = {}
if api_key.get(key) and api_key_prefix.get(key):
return api_key_prefix[key] + ' ' + api_key[key]
elif api_key.get(key):
return api_key[key]
def _singleton():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return _singleton
def get_basic_auth_token():
global username
global password
return urllib3.util.make_headers(basic_auth=username + ':' + password).get('authorization')
@singleton
class Configuration(object):
def auth_settings():
return {
'api_key': {
'type': 'api_key',
'in': 'header',
'key': 'api_key',
'value': get_api_key_with_prefix('api_key')
},
}
def __init__(self):
# Default Base url
self.host = "http://petstore.swagger.io/v2"
# Default api client
self.api_client = None
# Authentication Settings
self.api_key = {}
self.api_key_prefix = {}
self.username = ""
self.password = ""
# Logging Settings
self.logging_format = '%(asctime)s %(levelname)s %(message)s'
self.__logging_file = None
self.__debug = False
self.init_logger()
# Default Base url
host = "http://petstore.swagger.io/v2"
def init_logger(self):
self.logger = logging.getLogger()
formatter = logging.Formatter(self.logging_format)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
self.logger.addHandler(stream_handler)
if self.__debug:
self.logger.setLevel(logging.DEBUG)
else:
self.logger.setLevel(logging.WARNING)
if self.__logging_file:
file_handler = logging.FileHandler(self.__logging_file)
file_handler.setFormatter(formatter)
self.logger.addFilter(file_handler)
@property
def logging_file(self):
return self.__logging_file
@logging_file.setter
def logging_file(self, value):
self.__logging_file = value
if self.__logging_file:
formater = logging.Formatter(self.logging_format)
file_handler = logging.FileHandler(self.__logging_file)
file_handler.setFormatter(formater)
self.logger.addHandler(file_handler)
@property
def debug(self):
return self.__debug
@debug.setter
def debug(self, value):
self.__debug = value
if self.__debug:
# if debug status is True, turn on debug logging
self.logger.setLevel(logging.DEBUG)
# turn on httplib debug
httplib.HTTPConnection.debuglevel = 1
else:
# if debug status is False, turn off debug logging,
# setting log level to default `logging.WARNING`
self.logger.setLevel(logging.WARNING)
def get_api_key_with_prefix(self, key):
""" Return api key prepend prefix for key """
if self.api_key.get(key) and self.api_key_prefix.get(key):
return self.api_key_prefix[key] + ' ' + self.api_key[key]
elif self.api_key.get(key):
return self.api_key[key]
def get_basic_auth_token(self):
""" Return basic auth header string """
return urllib3.util.make_headers(basic_auth=self.username + ':' + self.password)\
.get('authorization')
def auth_settings(self):
""" Return Auth Settings for api client """
return {
'api_key': {
'type': 'api_key',
'in': 'header',
'key': 'api_key',
'value': self.get_api_key_with_prefix('api_key')
},
}
def to_debug_report(self):
return "Python SDK Debug Report:\n"\
"OS: {env}\n"\
"Python Version: {pyversion}\n"\
"Version of the API: 1.0.0\n"\
"SDK Package Version: 1.0.0".format(env=sys.platform, pyversion=sys.version)
# Default api client
api_client = None
# Authentication settings
api_key = {}
api_key_prefix = {}
username = ''
password = ''
# Temp foloder for file download
temp_folder_path = None

View File

@@ -10,6 +10,7 @@ import io
import json
import ssl
import certifi
import logging
# python 2 and python 3 compatibility library
from six import iteritems
@@ -27,6 +28,9 @@ except ImportError:
from urllib import urlencode
logger = logging.getLogger(__name__)
class RESTResponse(io.IOBase):
def __init__(self, resp):
@@ -65,9 +69,10 @@ class RESTClientObject(object):
def agent(self, url):
"""
Return proper pool manager for the http\https schemes.
Use `urllib3.util.parse_url` for backward compatibility.
Return proper pool manager for the http/https schemes.
"""
url = urllib3.util.url.parse_url(url)
url = urllib3.util.parse_url(url)
scheme = url.scheme
if scheme == 'https':
return self.ssl_pool_manager
@@ -130,6 +135,9 @@ class RESTClientObject(object):
if sys.version_info > (3,):
r.data = r.data.decode('utf8')
# log response body
logger.debug("response body: %s" % r.data)
if r.status not in range(200, 206):
raise ApiException(http_resp=r)

View File

@@ -63,8 +63,14 @@ class DeserializationTests(unittest.TestCase):
deserialized = self.deserialize(data, "str")
self.assertTrue(isinstance(deserialized, str))
def test_deserialize_date(self):
""" deserialize date """
data = "1997-07-16"
deserialized = self.deserialize(data, "date")
self.assertTrue(isinstance(deserialized, datetime.date))
def test_deserialize_datetime(self):
""" deserialize dateimte """
""" deserialize datetime """
data = "1997-07-16T19:20:30.45+01:00"
deserialized = self.deserialize(data, "datetime")
self.assertTrue(isinstance(deserialized, datetime.datetime))

View File

@@ -68,6 +68,25 @@ class PetApiTests(unittest.TestCase):
self.assertNotEqual(pet_api3.api_client, swagger_client.configuration.api_client)
# customized pet api not using the old pet api's api client
self.assertNotEqual(pet_api3.api_client, pet_api2.api_client)
def test_async_request(self):
self.pet_api.add_pet(body=self.pet)
def callback_function(data):
self.assertIsNotNone(data)
self.assertEqual(data.id, self.pet.id)
self.assertEqual(data.name, self.pet.name)
self.assertIsNotNone(data.category)
self.assertEqual(data.category.id, self.pet.category.id)
self.assertEqual(data.category.name, self.pet.category.name)
self.assertTrue(isinstance(data.tags, list))
self.assertEqual(data.tags[0].id, self.pet.tags[0].id)
self.assertEqual(data.tags[0].name, self.pet.tags[0].name)
thread = self.pet_api.get_pet_by_id(pet_id=self.pet.id, callback=callback_function)
thread.join(10)
if thread.isAlive():
self.fail("Request timeout")
def test_add_pet_and_get_pet_by_id(self):
self.pet_api.add_pet(body=self.pet)