aboutsummaryrefslogtreecommitdiffstats
path: root/python_openapi_client/fatcat_openapi_client/api_client.py
diff options
context:
space:
mode:
Diffstat (limited to 'python_openapi_client/fatcat_openapi_client/api_client.py')
-rw-r--r--python_openapi_client/fatcat_openapi_client/api_client.py796
1 files changed, 526 insertions, 270 deletions
diff --git a/python_openapi_client/fatcat_openapi_client/api_client.py b/python_openapi_client/fatcat_openapi_client/api_client.py
index eb23f1cd..fb811427 100644
--- a/python_openapi_client/fatcat_openapi_client/api_client.py
+++ b/python_openapi_client/fatcat_openapi_client/api_client.py
@@ -1,4 +1,3 @@
-# coding: utf-8
"""
fatcat
@@ -9,24 +8,36 @@
Generated by: https://openapi-generator.tech
"""
-from __future__ import absolute_import
-import datetime
import json
+import atexit
import mimetypes
from multiprocessing.pool import ThreadPool
+import io
import os
import re
-import tempfile
+import typing
+from urllib.parse import quote
+from urllib3.fields import RequestField
-# python 2 and python 3 compatibility library
-import six
-from six.moves.urllib.parse import quote
-from fatcat_openapi_client.configuration import Configuration
-import fatcat_openapi_client.models
from fatcat_openapi_client import rest
-from fatcat_openapi_client.exceptions import ApiValueError
+from fatcat_openapi_client.configuration import Configuration
+from fatcat_openapi_client.exceptions import ApiTypeError, ApiValueError, ApiException
+from fatcat_openapi_client.model_utils import (
+ ModelNormal,
+ ModelSimple,
+ ModelComposed,
+ check_allowed_values,
+ check_validations,
+ date,
+ datetime,
+ deserialize_file,
+ file_type,
+ model_to_dict,
+ none_type,
+ validate_and_convert_types
+)
class ApiClient(object):
@@ -51,23 +62,12 @@ class ApiClient(object):
to the API. More threads means more concurrent API requests.
"""
- PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types
- NATIVE_TYPES_MAPPING = {
- 'int': int,
- 'long': int if six.PY3 else long, # noqa: F821
- 'float': float,
- 'str': str,
- 'bool': bool,
- 'date': datetime.date,
- 'datetime': datetime.datetime,
- 'object': object,
- }
_pool = None
def __init__(self, configuration=None, header_name=None, header_value=None,
cookie=None, pool_threads=1):
if configuration is None:
- configuration = Configuration()
+ configuration = Configuration.get_default_copy()
self.configuration = configuration
self.pool_threads = pool_threads
@@ -77,13 +77,21 @@ class ApiClient(object):
self.default_headers[header_name] = header_value
self.cookie = cookie
# Set default User-Agent.
- self.user_agent = 'OpenAPI-Generator/0.5.0/python'
+ self.user_agent = 'OpenAPI-Generator/0.5.1/python'
+
+ def __enter__(self):
+ return self
- def __del__(self):
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.close()
+
+ def close(self):
if self._pool:
self._pool.close()
self._pool.join()
self._pool = None
+ if hasattr(atexit, 'unregister'):
+ atexit.unregister(self.close)
@property
def pool(self):
@@ -91,6 +99,7 @@ class ApiClient(object):
avoids instantiating unused threadpool for blocking clients.
"""
if self._pool is None:
+ atexit.register(self.close)
self._pool = ThreadPool(self.pool_threads)
return self._pool
@@ -107,11 +116,26 @@ class ApiClient(object):
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,
- _return_http_data_only=None, collection_formats=None,
- _preload_content=True, _request_timeout=None, _host=None):
+ self,
+ resource_path: str,
+ method: str,
+ path_params: typing.Optional[typing.Dict[str, typing.Any]] = None,
+ query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None,
+ header_params: typing.Optional[typing.Dict[str, typing.Any]] = None,
+ body: typing.Optional[typing.Any] = None,
+ post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None,
+ files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None,
+ response_type: typing.Optional[typing.Tuple[typing.Any]] = None,
+ auth_settings: typing.Optional[typing.List[str]] = None,
+ _return_http_data_only: typing.Optional[bool] = None,
+ collection_formats: typing.Optional[typing.Dict[str, str]] = None,
+ _preload_content: bool = True,
+ _request_timeout: typing.Optional[typing.Union[int, float, typing.Tuple]] = None,
+ _host: typing.Optional[str] = None,
+ _check_type: typing.Optional[bool] = None,
+ _content_type: typing.Optional[str] = None,
+ _request_auths: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None
+ ):
config = self.configuration
@@ -150,14 +174,19 @@ class ApiClient(object):
post_params = self.parameters_to_tuples(post_params,
collection_formats)
post_params.extend(self.files_parameters(files))
-
- # auth setting
- self.update_params_for_auth(header_params, query_params, auth_settings)
+ if header_params['Content-Type'].startswith("multipart"):
+ post_params = self.parameters_to_multipart(post_params,
+ (dict))
# body
if body:
body = self.sanitize_for_serialization(body)
+ # auth setting
+ self.update_params_for_auth(header_params, query_params,
+ auth_settings, resource_path, method, body,
+ request_auths=_request_auths)
+
# request url
if _host is None:
url = self.configuration.host + resource_path
@@ -165,22 +194,43 @@ class ApiClient(object):
# use server/host defined in path or operation instead
url = _host + resource_path
- # perform request and return response
- response_data = self.request(
- method, url, query_params=query_params, headers=header_params,
- post_params=post_params, body=body,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout)
+ try:
+ # perform request and return response
+ response_data = self.request(
+ method, url, query_params=query_params, headers=header_params,
+ post_params=post_params, body=body,
+ _preload_content=_preload_content,
+ _request_timeout=_request_timeout)
+ except ApiException as e:
+ e.body = e.body.decode('utf-8')
+ raise e
self.last_response = response_data
return_data = response_data
- if _preload_content:
- # deserialize response data
- if response_type:
- return_data = self.deserialize(response_data, response_type)
- else:
- return_data = None
+
+ if not _preload_content:
+ return (return_data)
+ return return_data
+
+ # deserialize response data
+ if response_type:
+ if response_type != (file_type,):
+ encoding = "utf-8"
+ content_type = response_data.getheader('content-type')
+ if content_type is not None:
+ match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type)
+ if match:
+ encoding = match.group(1)
+ response_data.data = response_data.data.decode(encoding)
+
+ return_data = self.deserialize(
+ response_data,
+ response_type,
+ _check_type
+ )
+ else:
+ return_data = None
if _return_http_data_only:
return (return_data)
@@ -188,9 +238,30 @@ class ApiClient(object):
return (return_data, response_data.status,
response_data.getheaders())
- def sanitize_for_serialization(self, obj):
- """Builds a JSON POST object.
+ def parameters_to_multipart(self, params, collection_types):
+ """Get parameters as list of tuples, formatting as json if value is collection_types
+
+ :param params: Parameters as list of two-tuples
+ :param dict collection_types: Parameter collection types
+ :return: Parameters as list of tuple or urllib3.fields.RequestField
+ """
+ new_params = []
+ if collection_types is None:
+ collection_types = (dict)
+ for k, v in params.items() if isinstance(params, dict) else params: # noqa: E501
+ if isinstance(
+ v, collection_types): # v is instance of collection_type, formatting as application/json
+ v = json.dumps(v, ensure_ascii=False).encode("utf-8")
+ field = RequestField(k, v)
+ field.make_multipart(content_type="application/json; charset=utf-8")
+ new_params.append(field)
+ else:
+ new_params.append((k, v))
+ return new_params
+ @classmethod
+ def sanitize_for_serialization(cls, obj):
+ """Prepares data for transmission before it is sent with the rest client
If obj is None, return None.
If obj is str, int, long, float, bool, return directly.
If obj is datetime.datetime, datetime.date
@@ -198,105 +269,98 @@ class ApiClient(object):
If obj is list, sanitize each element in the list.
If obj is dict, return the dict.
If obj is OpenAPI model, return the properties dict.
-
+ If obj is io.IOBase, return the bytes
:param obj: The data to serialize.
:return: The serialized form of data.
"""
- if obj is None:
- return None
- elif isinstance(obj, self.PRIMITIVE_TYPES):
+ if isinstance(obj, (ModelNormal, ModelComposed)):
+ return {
+ key: cls.sanitize_for_serialization(val) for key,
+ val in model_to_dict(
+ obj,
+ serialize=True).items()}
+ elif isinstance(obj, io.IOBase):
+ return cls.get_file_data_and_close_file(obj)
+ elif isinstance(obj, (str, int, float, none_type, bool)):
return obj
- elif isinstance(obj, list):
- return [self.sanitize_for_serialization(sub_obj)
- for sub_obj in obj]
- elif isinstance(obj, tuple):
- return tuple(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()
-
+ elif isinstance(obj, ModelSimple):
+ return cls.sanitize_for_serialization(obj.value)
+ elif isinstance(obj, (list, tuple)):
+ return [cls.sanitize_for_serialization(item) for item in obj]
if isinstance(obj, dict):
- obj_dict = obj
- else:
- # Convert model obj to dict except
- # attributes `openapi_types`, `attribute_map`
- # and attributes which value is not None.
- # Convert attribute name to json key in
- # model definition for request.
- obj_dict = {obj.attribute_map[attr]: getattr(obj, attr)
- for attr, _ in six.iteritems(obj.openapi_types)
- if getattr(obj, attr) is not None}
-
- return {key: self.sanitize_for_serialization(val)
- for key, val in six.iteritems(obj_dict)}
-
- def deserialize(self, response, response_type):
+ return {key: cls.sanitize_for_serialization(val) for key, val in obj.items()}
+ raise ApiValueError(
+ 'Unable to prepare type {} for serialization'.format(
+ obj.__class__.__name__))
+
+ def deserialize(self, response, response_type, _check_type):
"""Deserializes response into an object.
:param response: RESTResponse object to be deserialized.
- :param response_type: class literal for
- deserialized object, or string of class name.
+ :param response_type: For the response, a tuple containing:
+ valid classes
+ a list containing valid classes (for list schemas)
+ a dict containing a tuple of valid classes as the value
+ Example values:
+ (str,)
+ (Pet,)
+ (float, none_type)
+ ([int, none_type],)
+ ({str: (bool, str, int, float, date, datetime, str, none_type)},)
+ :param _check_type: boolean, whether to check the types of the data
+ received from the server
+ :type _check_type: bool
:return: deserialized object.
"""
# handle file downloading
# save response body into a tmp file and return the instance
- if response_type == "file":
- return self.__deserialize_file(response)
+ if response_type == (file_type,):
+ content_disposition = response.getheader("Content-Disposition")
+ return deserialize_file(response.data, self.configuration,
+ content_disposition=content_disposition)
# fetch data from response object
try:
- data = json.loads(response.data)
+ received_data = json.loads(response.data)
except ValueError:
- data = response.data
-
- return self.__deserialize(data, response_type)
-
- def __deserialize(self, data, klass):
- """Deserializes dict, list, str into an object.
-
- :param data: dict, list or str.
- :param klass: class literal, or string of class name.
-
- :return: object.
- """
- if data is None:
- return None
-
- if type(klass) == str:
- if klass.startswith('list['):
- sub_kls = re.match(r'list\[(.*)\]', klass).group(1)
- return [self.__deserialize(sub_data, sub_kls)
- for sub_data in data]
-
- if klass.startswith('dict('):
- sub_kls = re.match(r'dict\(([^,]*), (.*)\)', klass).group(2)
- return {k: self.__deserialize(v, sub_kls)
- for k, v in six.iteritems(data)}
-
- # convert str to class
- if klass in self.NATIVE_TYPES_MAPPING:
- klass = self.NATIVE_TYPES_MAPPING[klass]
- else:
- klass = getattr(fatcat_openapi_client.models, klass)
-
- if klass in self.PRIMITIVE_TYPES:
- return self.__deserialize_primitive(data, klass)
- elif klass == object:
- return self.__deserialize_object(data)
- elif klass == datetime.date:
- return self.__deserialize_date(data)
- elif klass == datetime.datetime:
- return self.__deserialize_datatime(data)
- else:
- return self.__deserialize_model(data, klass)
-
- 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, async_req=None,
- _return_http_data_only=None, collection_formats=None,
- _preload_content=True, _request_timeout=None, _host=None):
+ received_data = response.data
+
+ # store our data under the key of 'received_data' so users have some
+ # context if they are deserializing a string and the data type is wrong
+ deserialized_data = validate_and_convert_types(
+ received_data,
+ response_type,
+ ['received_data'],
+ True,
+ _check_type,
+ configuration=self.configuration
+ )
+ return deserialized_data
+
+ def call_api(
+ self,
+ resource_path: str,
+ method: str,
+ path_params: typing.Optional[typing.Dict[str, typing.Any]] = None,
+ query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None,
+ header_params: typing.Optional[typing.Dict[str, typing.Any]] = None,
+ body: typing.Optional[typing.Any] = None,
+ post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None,
+ files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None,
+ response_type: typing.Optional[typing.Tuple[typing.Any]] = None,
+ auth_settings: typing.Optional[typing.List[str]] = None,
+ async_req: typing.Optional[bool] = None,
+ _return_http_data_only: typing.Optional[bool] = None,
+ collection_formats: typing.Optional[typing.Dict[str, str]] = None,
+ _preload_content: bool = True,
+ _request_timeout: typing.Optional[typing.Union[int, float, typing.Tuple]] = None,
+ _host: typing.Optional[str] = None,
+ _check_type: typing.Optional[bool] = None,
+ _request_auths: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None
+ ):
"""Makes the HTTP request (synchronous) and returns deserialized data.
To make an async_req request, set the async_req parameter.
@@ -311,21 +375,42 @@ class ApiClient(object):
: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 response_type: For the response, a tuple containing:
+ valid classes
+ a list containing valid classes (for list schemas)
+ a dict containing a tuple of valid classes as the value
+ Example values:
+ (str,)
+ (Pet,)
+ (float, none_type)
+ ([int, none_type],)
+ ({str: (bool, str, int, float, date, datetime, str, none_type)},)
+ :param files: key -> field name, value -> a list of open file
+ objects for `multipart/form-data`.
+ :type files: dict
:param async_req bool: execute request asynchronously
+ :type async_req: bool, optional
:param _return_http_data_only: response data without head status code
and headers
+ :type _return_http_data_only: bool, optional
:param collection_formats: dict of collection formats for path, query,
header, and post parameters.
+ :type collection_formats: dict, optional
:param _preload_content: if False, the urllib3.HTTPResponse object will
be returned without reading/decoding response
data. Default is True.
+ :type _preload_content: bool, optional
: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.
+ :param _check_type: boolean describing if the data back from the server
+ should have its type checked.
+ :type _check_type: bool, optional
+ :param _request_auths: set to override the auth_settings for an a single
+ request; this effectively ignores the authentication
+ in the spec for a single request.
+ :type _request_auths: list, optional
:return:
If async_req parameter is True,
the request will be called asynchronously.
@@ -339,19 +424,21 @@ class ApiClient(object):
body, post_params, files,
response_type, auth_settings,
_return_http_data_only, collection_formats,
- _preload_content, _request_timeout, _host)
- else:
- thread = self.pool.apply_async(self.__call_api, (resource_path,
- method, path_params, query_params,
- header_params, body,
- post_params, files,
- response_type, auth_settings,
- _return_http_data_only,
- collection_formats,
- _preload_content,
- _request_timeout,
- _host))
- return thread
+ _preload_content, _request_timeout, _host,
+ _check_type, _request_auths=_request_auths)
+
+ return self.pool.apply_async(self.__call_api, (resource_path,
+ method, path_params,
+ query_params,
+ header_params, body,
+ post_params, files,
+ response_type,
+ auth_settings,
+ _return_http_data_only,
+ collection_formats,
+ _preload_content,
+ _request_timeout,
+ _host, _check_type, None, _request_auths))
def request(self, method, url, query_params=None, headers=None,
post_params=None, body=None, _preload_content=True,
@@ -424,7 +511,7 @@ class ApiClient(object):
new_params = []
if collection_formats is None:
collection_formats = {}
- for k, v in six.iteritems(params) if isinstance(params, dict) else params: # noqa: E501
+ for k, v in params.items() if isinstance(params, dict) else params: # noqa: E501
if k in collection_formats:
collection_format = collection_formats[k]
if collection_format == 'multi':
@@ -444,27 +531,44 @@ class ApiClient(object):
new_params.append((k, v))
return new_params
- def files_parameters(self, files=None):
+ @staticmethod
+ def get_file_data_and_close_file(file_instance: io.IOBase) -> bytes:
+ file_data = file_instance.read()
+ file_instance.close()
+ return file_data
+
+ def files_parameters(self,
+ files: typing.Optional[typing.Dict[str,
+ typing.List[io.IOBase]]] = None):
"""Builds form parameters.
- :param files: File parameters.
- :return: Form parameters with files.
+ :param files: None or a dict with key=param_name and
+ value is a list of open file objects
+ :return: List of tuples of form parameters with file data
"""
- params = []
+ if files is None:
+ return []
- if files:
- for k, v in six.iteritems(files):
- if not v:
+ params = []
+ for param_name, file_instances in files.items():
+ if file_instances is None:
+ # if the file field is nullable, skip None values
+ continue
+ for file_instance in file_instances:
+ if file_instance is None:
+ # if the file field is nullable, skip None values
continue
- file_names = v if type(v) is list else [v]
- for n in file_names:
- with open(n, 'rb') as f:
- filename = os.path.basename(f.name)
- filedata = f.read()
- mimetype = (mimetypes.guess_type(filename)[0] or
- 'application/octet-stream')
- params.append(
- tuple([k, tuple([filename, filedata, mimetype])]))
+ if file_instance.closed is True:
+ raise ApiValueError(
+ "Cannot read a closed file. The passed in file_type "
+ "for %s must be open." % param_name
+ )
+ filename = os.path.basename(file_instance.name)
+ filedata = self.get_file_data_and_close_file(file_instance)
+ mimetype = (mimetypes.guess_type(filename)[0] or
+ 'application/octet-stream')
+ params.append(
+ tuple([param_name, tuple([filename, filedata, mimetype])]))
return params
@@ -484,158 +588,310 @@ class ApiClient(object):
else:
return ', '.join(accepts)
- def select_header_content_type(self, content_types):
+ def select_header_content_type(self, content_types, method=None, body=None):
"""Returns `Content-Type` based on an array of content_types provided.
:param content_types: List of content-types.
+ :param method: http method (e.g. POST, PATCH).
+ :param body: http body to send.
:return: Content-Type (e.g. application/json).
"""
if not content_types:
- return 'application/json'
+ return None
content_types = [x.lower() for x in content_types]
+ if (method == 'PATCH' and
+ 'application/json-patch+json' in content_types and
+ isinstance(body, list)):
+ return 'application/json-patch+json'
+
if 'application/json' in content_types or '*/*' in content_types:
return 'application/json'
else:
return content_types[0]
- def update_params_for_auth(self, headers, querys, auth_settings):
+ def update_params_for_auth(self, headers, queries, auth_settings,
+ resource_path, method, body, request_auths=None):
"""Updates header and query params based on authentication setting.
:param headers: Header parameters dict to be updated.
- :param querys: Query parameters tuple list to be updated.
+ :param queries: Query parameters tuple list to be updated.
:param auth_settings: Authentication setting identifiers list.
+ :param resource_path: A string representation of the HTTP request resource path.
+ :param method: A string representation of the HTTP request method.
+ :param body: A object representing the body of the HTTP request.
+ The object type is the return value of _encoder.default().
+ :param request_auths: if set, the provided settings will
+ override the token in the configuration.
"""
if not auth_settings:
return
+ if request_auths:
+ for auth_setting in request_auths:
+ self._apply_auth_params(
+ headers, queries, resource_path, method, body, auth_setting)
+ return
+
for auth in auth_settings:
auth_setting = self.configuration.auth_settings().get(auth)
if auth_setting:
- if not auth_setting['value']:
- continue
- elif auth_setting['in'] == 'cookie':
- headers['Cookie'] = auth_setting['value']
- elif auth_setting['in'] == 'header':
- headers[auth_setting['key']] = auth_setting['value']
- elif auth_setting['in'] == 'query':
- querys.append((auth_setting['key'], auth_setting['value']))
- else:
- raise ApiValueError(
- 'Authentication token must be in `query` or `header`'
- )
-
- def __deserialize_file(self, response):
- """Deserializes body to file
+ self._apply_auth_params(
+ headers, queries, resource_path, method, body, auth_setting)
+
+ def _apply_auth_params(self, headers, queries, resource_path, method, body, auth_setting):
+ if auth_setting['in'] == 'cookie':
+ headers['Cookie'] = auth_setting['key'] + "=" + auth_setting['value']
+ elif auth_setting['in'] == 'header':
+ if auth_setting['type'] != 'http-signature':
+ headers[auth_setting['key']] = auth_setting['value']
+ elif auth_setting['in'] == 'query':
+ queries.append((auth_setting['key'], auth_setting['value']))
+ else:
+ raise ApiValueError(
+ 'Authentication token must be in `query` or `header`'
+ )
- Saves response body into a file in a temporary folder,
- using the filename from the `Content-Disposition` header if provided.
- :param response: RESTResponse.
- :return: file path.
+class Endpoint(object):
+ def __init__(self, settings=None, params_map=None, root_map=None,
+ headers_map=None, api_client=None, callable=None):
+ """Creates an endpoint
+
+ Args:
+ settings (dict): see below key value pairs
+ 'response_type' (tuple/None): response type
+ 'auth' (list): a list of auth type keys
+ 'endpoint_path' (str): the endpoint path
+ 'operation_id' (str): endpoint string identifier
+ 'http_method' (str): POST/PUT/PATCH/GET etc
+ 'servers' (list): list of str servers that this endpoint is at
+ params_map (dict): see below key value pairs
+ 'all' (list): list of str endpoint parameter names
+ 'required' (list): list of required parameter names
+ 'nullable' (list): list of nullable parameter names
+ 'enum' (list): list of parameters with enum values
+ 'validation' (list): list of parameters with validations
+ root_map
+ 'validations' (dict): the dict mapping endpoint parameter tuple
+ paths to their validation dictionaries
+ 'allowed_values' (dict): the dict mapping endpoint parameter
+ tuple paths to their allowed_values (enum) dictionaries
+ 'openapi_types' (dict): param_name to openapi type
+ 'attribute_map' (dict): param_name to camelCase name
+ 'location_map' (dict): param_name to 'body', 'file', 'form',
+ 'header', 'path', 'query'
+ collection_format_map (dict): param_name to `csv` etc.
+ headers_map (dict): see below key value pairs
+ 'accept' (list): list of Accept header strings
+ 'content_type' (list): list of Content-Type header strings
+ api_client (ApiClient) api client instance
+ callable (function): the function which is invoked when the
+ Endpoint is called
"""
- fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path)
- os.close(fd)
- os.remove(path)
-
- content_disposition = response.getheader("Content-Disposition")
- if content_disposition:
- filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?',
- content_disposition).group(1)
- path = os.path.join(os.path.dirname(path), filename)
+ self.settings = settings
+ self.params_map = params_map
+ self.params_map['all'].extend([
+ 'async_req',
+ '_host_index',
+ '_preload_content',
+ '_request_timeout',
+ '_return_http_data_only',
+ '_check_input_type',
+ '_check_return_type',
+ '_content_type',
+ '_spec_property_naming',
+ '_request_auths'
+ ])
+ self.params_map['nullable'].extend(['_request_timeout'])
+ self.validations = root_map['validations']
+ self.allowed_values = root_map['allowed_values']
+ self.openapi_types = root_map['openapi_types']
+ extra_types = {
+ 'async_req': (bool,),
+ '_host_index': (none_type, int),
+ '_preload_content': (bool,),
+ '_request_timeout': (none_type, float, (float,), [float], int, (int,), [int]),
+ '_return_http_data_only': (bool,),
+ '_check_input_type': (bool,),
+ '_check_return_type': (bool,),
+ '_spec_property_naming': (bool,),
+ '_content_type': (none_type, str),
+ '_request_auths': (none_type, list)
+ }
+ self.openapi_types.update(extra_types)
+ self.attribute_map = root_map['attribute_map']
+ self.location_map = root_map['location_map']
+ self.collection_format_map = root_map['collection_format_map']
+ self.headers_map = headers_map
+ self.api_client = api_client
+ self.callable = callable
+
+ def __validate_inputs(self, kwargs):
+ for param in self.params_map['enum']:
+ if param in kwargs:
+ check_allowed_values(
+ self.allowed_values,
+ (param,),
+ kwargs[param]
+ )
- with open(path, "wb") as f:
- f.write(response.data)
+ for param in self.params_map['validation']:
+ if param in kwargs:
+ check_validations(
+ self.validations,
+ (param,),
+ kwargs[param],
+ configuration=self.api_client.configuration
+ )
- return path
+ if kwargs['_check_input_type'] is False:
+ return
- def __deserialize_primitive(self, data, klass):
- """Deserializes string to primitive type.
+ for key, value in kwargs.items():
+ fixed_val = validate_and_convert_types(
+ value,
+ self.openapi_types[key],
+ [key],
+ kwargs['_spec_property_naming'],
+ kwargs['_check_input_type'],
+ configuration=self.api_client.configuration
+ )
+ kwargs[key] = fixed_val
+
+ def __gather_params(self, kwargs):
+ params = {
+ 'body': None,
+ 'collection_format': {},
+ 'file': {},
+ 'form': [],
+ 'header': {},
+ 'path': {},
+ 'query': []
+ }
+
+ for param_name, param_value in kwargs.items():
+ param_location = self.location_map.get(param_name)
+ if param_location is None:
+ continue
+ if param_location:
+ if param_location == 'body':
+ params['body'] = param_value
+ continue
+ base_name = self.attribute_map[param_name]
+ if (param_location == 'form' and
+ self.openapi_types[param_name] == (file_type,)):
+ params['file'][base_name] = [param_value]
+ elif (param_location == 'form' and
+ self.openapi_types[param_name] == ([file_type],)):
+ # param_value is already a list
+ params['file'][base_name] = param_value
+ elif param_location in {'form', 'query'}:
+ param_value_full = (base_name, param_value)
+ params[param_location].append(param_value_full)
+ if param_location not in {'form', 'query'}:
+ params[param_location][base_name] = param_value
+ collection_format = self.collection_format_map.get(param_name)
+ if collection_format:
+ params['collection_format'][base_name] = collection_format
- :param data: str.
- :param klass: class literal.
+ return params
- :return: int, long, float, str, bool.
- """
- try:
- return klass(data)
- except UnicodeEncodeError:
- return six.text_type(data)
- except TypeError:
- return data
+ def __call__(self, *args, **kwargs):
+ """ This method is invoked when endpoints are called
+ Example:
- def __deserialize_object(self, value):
- """Return an original value.
+ api_instance = AuthApi()
+ api_instance.auth_check # this is an instance of the class Endpoint
+ api_instance.auth_check() # this invokes api_instance.auth_check.__call__()
+ which then invokes the callable functions stored in that endpoint at
+ api_instance.auth_check.callable or self.callable in this class
- :return: object.
"""
- return value
+ return self.callable(self, *args, **kwargs)
- def __deserialize_date(self, string):
- """Deserializes string to date.
+ def call_with_http_info(self, **kwargs):
- :param string: str.
- :return: date.
- """
try:
- from dateutil.parser import parse
- return parse(string).date()
- except ImportError:
- return string
- except ValueError:
- raise rest.ApiException(
- status=0,
- reason="Failed to parse `{0}` as date object".format(string)
+ index = self.api_client.configuration.server_operation_index.get(
+ self.settings['operation_id'], self.api_client.configuration.server_index
+ ) if kwargs['_host_index'] is None else kwargs['_host_index']
+ server_variables = self.api_client.configuration.server_operation_variables.get(
+ self.settings['operation_id'], self.api_client.configuration.server_variables
)
+ _host = self.api_client.configuration.get_host_from_settings(
+ index, variables=server_variables, servers=self.settings['servers']
+ )
+ except IndexError:
+ if self.settings['servers']:
+ raise ApiValueError(
+ "Invalid host index. Must be 0 <= index < %s" %
+ len(self.settings['servers'])
+ )
+ _host = None
+
+ for key, value in kwargs.items():
+ if key not in self.params_map['all']:
+ raise ApiTypeError(
+ "Got an unexpected parameter '%s'"
+ " to method `%s`" %
+ (key, self.settings['operation_id'])
+ )
+ # only throw this nullable ApiValueError if _check_input_type
+ # is False, if _check_input_type==True we catch this case
+ # in self.__validate_inputs
+ if (key not in self.params_map['nullable'] and value is None
+ and kwargs['_check_input_type'] is False):
+ raise ApiValueError(
+ "Value may not be None for non-nullable parameter `%s`"
+ " when calling `%s`" %
+ (key, self.settings['operation_id'])
+ )
- def __deserialize_datatime(self, string):
- """Deserializes string to datetime.
-
- The string should be in iso8601 datetime format.
-
- :param string: str.
- :return: datetime.
- """
- try:
- from dateutil.parser import parse
- return parse(string)
- except ImportError:
- return string
- except ValueError:
- raise rest.ApiException(
- status=0,
- reason=(
- "Failed to parse `{0}` as datetime object"
- .format(string)
+ for key in self.params_map['required']:
+ if key not in kwargs.keys():
+ raise ApiValueError(
+ "Missing the required parameter `%s` when calling "
+ "`%s`" % (key, self.settings['operation_id'])
)
- )
- def __deserialize_model(self, data, klass):
- """Deserializes list or dict to model.
+ self.__validate_inputs(kwargs)
- :param data: dict, list.
- :param klass: class literal.
- :return: model object.
- """
+ params = self.__gather_params(kwargs)
- if not klass.openapi_types and not hasattr(klass,
- 'get_real_child_model'):
- return data
-
- kwargs = {}
- if klass.openapi_types is not None:
- for attr, attr_type in six.iteritems(klass.openapi_types):
- if (data is not None and
- klass.attribute_map[attr] in data and
- isinstance(data, (list, dict))):
- value = data[klass.attribute_map[attr]]
- kwargs[attr] = self.__deserialize(value, attr_type)
-
- instance = klass(**kwargs)
-
- if hasattr(instance, 'get_real_child_model'):
- klass_name = instance.get_real_child_model(data)
- if klass_name:
- instance = self.__deserialize(data, klass_name)
- return instance
+ accept_headers_list = self.headers_map['accept']
+ if accept_headers_list:
+ params['header']['Accept'] = self.api_client.select_header_accept(
+ accept_headers_list)
+
+ if kwargs.get('_content_type'):
+ params['header']['Content-Type'] = kwargs['_content_type']
+ else:
+ content_type_headers_list = self.headers_map['content_type']
+ if content_type_headers_list:
+ if params['body'] != "":
+ content_types_list = self.api_client.select_header_content_type(
+ content_type_headers_list, self.settings['http_method'],
+ params['body'])
+ if content_types_list:
+ params['header']['Content-Type'] = content_types_list
+
+ return self.api_client.call_api(
+ self.settings['endpoint_path'], self.settings['http_method'],
+ params['path'],
+ params['query'],
+ params['header'],
+ body=params['body'],
+ post_params=params['form'],
+ files=params['file'],
+ response_type=self.settings['response_type'],
+ auth_settings=self.settings['auth'],
+ async_req=kwargs['async_req'],
+ _check_type=kwargs['_check_return_type'],
+ _return_http_data_only=kwargs['_return_http_data_only'],
+ _preload_content=kwargs['_preload_content'],
+ _request_timeout=kwargs['_request_timeout'],
+ _host=_host,
+ _request_auths=kwargs['_request_auths'],
+ collection_formats=params['collection_format'])