github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/clients/python-legacy/lakefs_client/api_client.py (about)

     1  """
     2      lakeFS API
     3  
     4      lakeFS HTTP API  # noqa: E501
     5  
     6      The version of the OpenAPI document: 1.0.0
     7      Contact: services@treeverse.io
     8      Generated by: https://openapi-generator.tech
     9  """
    10  
    11  
    12  import json
    13  import atexit
    14  import mimetypes
    15  from multiprocessing.pool import ThreadPool
    16  import io
    17  import os
    18  import re
    19  import typing
    20  from urllib.parse import quote
    21  from urllib3.fields import RequestField
    22  
    23  
    24  from lakefs_client import rest
    25  from lakefs_client.configuration import Configuration
    26  from lakefs_client.exceptions import ApiTypeError, ApiValueError, ApiException
    27  from lakefs_client.model_utils import (
    28      ModelNormal,
    29      ModelSimple,
    30      ModelComposed,
    31      check_allowed_values,
    32      check_validations,
    33      date,
    34      datetime,
    35      deserialize_file,
    36      file_type,
    37      model_to_dict,
    38      none_type,
    39      validate_and_convert_types
    40  )
    41  
    42  
    43  class ApiClient(object):
    44      """Generic API client for OpenAPI client library builds.
    45  
    46      OpenAPI generic API client. This client handles the client-
    47      server communication, and is invariant across implementations. Specifics of
    48      the methods and models for each application are generated from the OpenAPI
    49      templates.
    50  
    51      NOTE: This class is auto generated by OpenAPI Generator.
    52      Ref: https://openapi-generator.tech
    53      Do not edit the class manually.
    54  
    55      :param configuration: .Configuration object for this client
    56      :param header_name: a header to pass when making calls to the API.
    57      :param header_value: a header value to pass when making calls to
    58          the API.
    59      :param cookie: a cookie to include in the header when making calls
    60          to the API
    61      :param pool_threads: The number of threads to use for async requests
    62          to the API. More threads means more concurrent API requests.
    63      """
    64  
    65      _pool = None
    66  
    67      def __init__(self, configuration=None, header_name=None, header_value=None,
    68                   cookie=None, pool_threads=1):
    69          if configuration is None:
    70              configuration = Configuration.get_default_copy()
    71          self.configuration = configuration
    72          self.pool_threads = pool_threads
    73  
    74          self.rest_client = rest.RESTClientObject(configuration)
    75          self.default_headers = {}
    76          if header_name is not None:
    77              self.default_headers[header_name] = header_value
    78          self.cookie = cookie
    79          # Set default User-Agent.
    80          self.user_agent = 'lakefs-python-sdk/0.1.0-SNAPSHOT-legacy'
    81  
    82      def __enter__(self):
    83          return self
    84  
    85      def __exit__(self, exc_type, exc_value, traceback):
    86          self.close()
    87  
    88      def close(self):
    89          if self._pool:
    90              self._pool.close()
    91              self._pool.join()
    92              self._pool = None
    93              if hasattr(atexit, 'unregister'):
    94                  atexit.unregister(self.close)
    95  
    96      @property
    97      def pool(self):
    98          """Create thread pool on first request
    99           avoids instantiating unused threadpool for blocking clients.
   100          """
   101          if self._pool is None:
   102              atexit.register(self.close)
   103              self._pool = ThreadPool(self.pool_threads)
   104          return self._pool
   105  
   106      @property
   107      def user_agent(self):
   108          """User agent for this API client"""
   109          return self.default_headers['User-Agent']
   110  
   111      @user_agent.setter
   112      def user_agent(self, value):
   113          self.default_headers['User-Agent'] = value
   114  
   115      def set_default_header(self, header_name, header_value):
   116          self.default_headers[header_name] = header_value
   117  
   118      def __call_api(
   119          self,
   120          resource_path: str,
   121          method: str,
   122          path_params: typing.Optional[typing.Dict[str, typing.Any]] = None,
   123          query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None,
   124          header_params: typing.Optional[typing.Dict[str, typing.Any]] = None,
   125          body: typing.Optional[typing.Any] = None,
   126          post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None,
   127          files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None,
   128          response_type: typing.Optional[typing.Tuple[typing.Any]] = None,
   129          auth_settings: typing.Optional[typing.List[str]] = None,
   130          _return_http_data_only: typing.Optional[bool] = None,
   131          collection_formats: typing.Optional[typing.Dict[str, str]] = None,
   132          _preload_content: bool = True,
   133          _request_timeout: typing.Optional[typing.Union[int, float, typing.Tuple]] = None,
   134          _host: typing.Optional[str] = None,
   135          _check_type: typing.Optional[bool] = None
   136      ):
   137  
   138          config = self.configuration
   139  
   140          # header parameters
   141          header_params = header_params or {}
   142          header_params.update(self.default_headers)
   143          if self.cookie:
   144              header_params['Cookie'] = self.cookie
   145          if header_params:
   146              header_params = self.sanitize_for_serialization(header_params)
   147              header_params = dict(self.parameters_to_tuples(header_params,
   148                                                             collection_formats))
   149  
   150          # path parameters
   151          if path_params:
   152              path_params = self.sanitize_for_serialization(path_params)
   153              path_params = self.parameters_to_tuples(path_params,
   154                                                      collection_formats)
   155              for k, v in path_params:
   156                  # specified safe chars, encode everything
   157                  resource_path = resource_path.replace(
   158                      '{%s}' % k,
   159                      quote(str(v), safe=config.safe_chars_for_path_param)
   160                  )
   161  
   162          # query parameters
   163          if query_params:
   164              query_params = self.sanitize_for_serialization(query_params)
   165              query_params = self.parameters_to_tuples(query_params,
   166                                                       collection_formats)
   167  
   168          # post parameters
   169          if post_params or files:
   170              post_params = post_params if post_params else []
   171              post_params = self.sanitize_for_serialization(post_params)
   172              post_params = self.parameters_to_tuples(post_params,
   173                                                      collection_formats)
   174              post_params.extend(self.files_parameters(files))
   175              if header_params['Content-Type'].startswith("multipart"):
   176                  post_params = self.parameters_to_multipart(post_params,
   177                                                            (dict) )
   178  
   179          # body
   180          if body:
   181              body = self.sanitize_for_serialization(body)
   182  
   183          # auth setting
   184          self.update_params_for_auth(header_params, query_params,
   185                                      auth_settings, resource_path, method, body)
   186  
   187          # request url
   188          if _host is None:
   189              url = self.configuration.host + resource_path
   190          else:
   191              # use server/host defined in path or operation instead
   192              url = _host + resource_path
   193  
   194          try:
   195              # perform request and return response
   196              response_data = self.request(
   197                  method, url, query_params=query_params, headers=header_params,
   198                  post_params=post_params, body=body,
   199                  _preload_content=_preload_content,
   200                  _request_timeout=_request_timeout)
   201          except ApiException as e:
   202              e.body = e.body.decode('utf-8')
   203              raise e
   204  
   205          self.last_response = response_data
   206  
   207          return_data = response_data
   208  
   209          if not _preload_content:
   210              return (return_data)
   211              return return_data
   212  
   213          # deserialize response data
   214          if response_type:
   215              if response_type != (file_type,):
   216                  encoding = "utf-8"
   217                  content_type = response_data.getheader('content-type')
   218                  if content_type is not None:
   219                      match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type)
   220                      if match:
   221                          encoding = match.group(1)
   222                  response_data.data = response_data.data.decode(encoding)
   223  
   224              return_data = self.deserialize(
   225                  response_data,
   226                  response_type,
   227                  _check_type
   228              )
   229          else:
   230              return_data = None
   231  
   232          if _return_http_data_only:
   233              return (return_data)
   234          else:
   235              return (return_data, response_data.status,
   236                      response_data.getheaders())
   237  
   238      def parameters_to_multipart(self, params, collection_types):
   239          """Get parameters as list of tuples, formatting as json if value is collection_types
   240  
   241          :param params: Parameters as list of two-tuples
   242          :param dict collection_types: Parameter collection types
   243          :return: Parameters as list of tuple or urllib3.fields.RequestField
   244          """
   245          new_params = []
   246          if collection_types is None:
   247              collection_types = (dict)
   248          for k, v in params.items() if isinstance(params, dict) else params:  # noqa: E501
   249              if isinstance(v, collection_types): # v is instance of collection_type, formatting as application/json
   250                   v = json.dumps(v, ensure_ascii=False).encode("utf-8")
   251                   field = RequestField(k, v)
   252                   field.make_multipart(content_type="application/json; charset=utf-8")
   253                   new_params.append(field)
   254              else:
   255                   new_params.append((k, v))
   256          return new_params
   257  
   258      @classmethod
   259      def sanitize_for_serialization(cls, obj):
   260          """Prepares data for transmission before it is sent with the rest client
   261          If obj is None, return None.
   262          If obj is str, int, long, float, bool, return directly.
   263          If obj is datetime.datetime, datetime.date
   264              convert to string in iso8601 format.
   265          If obj is list, sanitize each element in the list.
   266          If obj is dict, return the dict.
   267          If obj is OpenAPI model, return the properties dict.
   268          If obj is io.IOBase, return the bytes
   269          :param obj: The data to serialize.
   270          :return: The serialized form of data.
   271          """
   272          if isinstance(obj, (ModelNormal, ModelComposed)):
   273              return {
   274                  key: cls.sanitize_for_serialization(val) for key, val in model_to_dict(obj, serialize=True).items()
   275              }
   276          elif isinstance(obj, io.IOBase):
   277              return cls.get_file_data_and_close_file(obj)
   278          elif isinstance(obj, (str, int, float, none_type, bool)):
   279              return obj
   280          elif isinstance(obj, (datetime, date)):
   281              return obj.isoformat()
   282          elif isinstance(obj, ModelSimple):
   283              return cls.sanitize_for_serialization(obj.value)
   284          elif isinstance(obj, (list, tuple)):
   285              return [cls.sanitize_for_serialization(item) for item in obj]
   286          if isinstance(obj, dict):
   287              return {key: cls.sanitize_for_serialization(val) for key, val in obj.items()}
   288          raise ApiValueError('Unable to prepare type {} for serialization'.format(obj.__class__.__name__))
   289  
   290      def deserialize(self, response, response_type, _check_type):
   291          """Deserializes response into an object.
   292  
   293          :param response: RESTResponse object to be deserialized.
   294          :param response_type: For the response, a tuple containing:
   295              valid classes
   296              a list containing valid classes (for list schemas)
   297              a dict containing a tuple of valid classes as the value
   298              Example values:
   299              (str,)
   300              (Pet,)
   301              (float, none_type)
   302              ([int, none_type],)
   303              ({str: (bool, str, int, float, date, datetime, str, none_type)},)
   304          :param _check_type: boolean, whether to check the types of the data
   305              received from the server
   306          :type _check_type: bool
   307  
   308          :return: deserialized object.
   309          """
   310          # handle file downloading
   311          # save response body into a tmp file and return the instance
   312          if response_type == (file_type,):
   313              content_disposition = response.getheader("Content-Disposition")
   314              return deserialize_file(response.data, self.configuration,
   315                                      content_disposition=content_disposition)
   316  
   317          # fetch data from response object
   318          try:
   319              received_data = json.loads(response.data)
   320          except ValueError:
   321              received_data = response.data
   322  
   323          # store our data under the key of 'received_data' so users have some
   324          # context if they are deserializing a string and the data type is wrong
   325          deserialized_data = validate_and_convert_types(
   326              received_data,
   327              response_type,
   328              ['received_data'],
   329              True,
   330              _check_type,
   331              configuration=self.configuration
   332          )
   333          return deserialized_data
   334  
   335      def call_api(
   336          self,
   337          resource_path: str,
   338          method: str,
   339          path_params: typing.Optional[typing.Dict[str, typing.Any]] = None,
   340          query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None,
   341          header_params: typing.Optional[typing.Dict[str, typing.Any]] = None,
   342          body: typing.Optional[typing.Any] = None,
   343          post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None,
   344          files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None,
   345          response_type: typing.Optional[typing.Tuple[typing.Any]] = None,
   346          auth_settings: typing.Optional[typing.List[str]] = None,
   347          async_req: typing.Optional[bool] = None,
   348          _return_http_data_only: typing.Optional[bool] = None,
   349          collection_formats: typing.Optional[typing.Dict[str, str]] = None,
   350          _preload_content: bool = True,
   351          _request_timeout: typing.Optional[typing.Union[int, float, typing.Tuple]] = None,
   352          _host: typing.Optional[str] = None,
   353          _check_type: typing.Optional[bool] = None
   354      ):
   355          """Makes the HTTP request (synchronous) and returns deserialized data.
   356  
   357          To make an async_req request, set the async_req parameter.
   358  
   359          :param resource_path: Path to method endpoint.
   360          :param method: Method to call.
   361          :param path_params: Path parameters in the url.
   362          :param query_params: Query parameters in the url.
   363          :param header_params: Header parameters to be
   364              placed in the request header.
   365          :param body: Request body.
   366          :param post_params dict: Request post form parameters,
   367              for `application/x-www-form-urlencoded`, `multipart/form-data`.
   368          :param auth_settings list: Auth Settings names for the request.
   369          :param response_type: For the response, a tuple containing:
   370              valid classes
   371              a list containing valid classes (for list schemas)
   372              a dict containing a tuple of valid classes as the value
   373              Example values:
   374              (str,)
   375              (Pet,)
   376              (float, none_type)
   377              ([int, none_type],)
   378              ({str: (bool, str, int, float, date, datetime, str, none_type)},)
   379          :param files: key -> field name, value -> a list of open file
   380              objects for `multipart/form-data`.
   381          :type files: dict
   382          :param async_req bool: execute request asynchronously
   383          :type async_req: bool, optional
   384          :param _return_http_data_only: response data without head status code
   385                                         and headers
   386          :type _return_http_data_only: bool, optional
   387          :param collection_formats: dict of collection formats for path, query,
   388              header, and post parameters.
   389          :type collection_formats: dict, optional
   390          :param _preload_content: if False, the urllib3.HTTPResponse object will
   391                                   be returned without reading/decoding response
   392                                   data. Default is True.
   393          :type _preload_content: bool, optional
   394          :param _request_timeout: timeout setting for this request. If one
   395                                   number provided, it will be total request
   396                                   timeout. It can also be a pair (tuple) of
   397                                   (connection, read) timeouts.
   398          :param _check_type: boolean describing if the data back from the server
   399              should have its type checked.
   400          :type _check_type: bool, optional
   401          :return:
   402              If async_req parameter is True,
   403              the request will be called asynchronously.
   404              The method will return the request thread.
   405              If parameter async_req is False or missing,
   406              then the method will return the response directly.
   407          """
   408          if not async_req:
   409              return self.__call_api(resource_path, method,
   410                                     path_params, query_params, header_params,
   411                                     body, post_params, files,
   412                                     response_type, auth_settings,
   413                                     _return_http_data_only, collection_formats,
   414                                     _preload_content, _request_timeout, _host,
   415                                     _check_type)
   416  
   417          return self.pool.apply_async(self.__call_api, (resource_path,
   418                                                         method, path_params,
   419                                                         query_params,
   420                                                         header_params, body,
   421                                                         post_params, files,
   422                                                         response_type,
   423                                                         auth_settings,
   424                                                         _return_http_data_only,
   425                                                         collection_formats,
   426                                                         _preload_content,
   427                                                         _request_timeout,
   428                                                         _host, _check_type))
   429  
   430      def request(self, method, url, query_params=None, headers=None,
   431                  post_params=None, body=None, _preload_content=True,
   432                  _request_timeout=None):
   433          """Makes the HTTP request using RESTClient."""
   434          if method == "GET":
   435              return self.rest_client.GET(url,
   436                                          query_params=query_params,
   437                                          _preload_content=_preload_content,
   438                                          _request_timeout=_request_timeout,
   439                                          headers=headers)
   440          elif method == "HEAD":
   441              return self.rest_client.HEAD(url,
   442                                           query_params=query_params,
   443                                           _preload_content=_preload_content,
   444                                           _request_timeout=_request_timeout,
   445                                           headers=headers)
   446          elif method == "OPTIONS":
   447              return self.rest_client.OPTIONS(url,
   448                                              query_params=query_params,
   449                                              headers=headers,
   450                                              post_params=post_params,
   451                                              _preload_content=_preload_content,
   452                                              _request_timeout=_request_timeout,
   453                                              body=body)
   454          elif method == "POST":
   455              return self.rest_client.POST(url,
   456                                           query_params=query_params,
   457                                           headers=headers,
   458                                           post_params=post_params,
   459                                           _preload_content=_preload_content,
   460                                           _request_timeout=_request_timeout,
   461                                           body=body)
   462          elif method == "PUT":
   463              return self.rest_client.PUT(url,
   464                                          query_params=query_params,
   465                                          headers=headers,
   466                                          post_params=post_params,
   467                                          _preload_content=_preload_content,
   468                                          _request_timeout=_request_timeout,
   469                                          body=body)
   470          elif method == "PATCH":
   471              return self.rest_client.PATCH(url,
   472                                            query_params=query_params,
   473                                            headers=headers,
   474                                            post_params=post_params,
   475                                            _preload_content=_preload_content,
   476                                            _request_timeout=_request_timeout,
   477                                            body=body)
   478          elif method == "DELETE":
   479              return self.rest_client.DELETE(url,
   480                                             query_params=query_params,
   481                                             headers=headers,
   482                                             _preload_content=_preload_content,
   483                                             _request_timeout=_request_timeout,
   484                                             body=body)
   485          else:
   486              raise ApiValueError(
   487                  "http method must be `GET`, `HEAD`, `OPTIONS`,"
   488                  " `POST`, `PATCH`, `PUT` or `DELETE`."
   489              )
   490  
   491      def parameters_to_tuples(self, params, collection_formats):
   492          """Get parameters as list of tuples, formatting collections.
   493  
   494          :param params: Parameters as dict or list of two-tuples
   495          :param dict collection_formats: Parameter collection formats
   496          :return: Parameters as list of tuples, collections formatted
   497          """
   498          new_params = []
   499          if collection_formats is None:
   500              collection_formats = {}
   501          for k, v in params.items() if isinstance(params, dict) else params:  # noqa: E501
   502              if k in collection_formats:
   503                  collection_format = collection_formats[k]
   504                  if collection_format == 'multi':
   505                      new_params.extend((k, value) for value in v)
   506                  else:
   507                      if collection_format == 'ssv':
   508                          delimiter = ' '
   509                      elif collection_format == 'tsv':
   510                          delimiter = '\t'
   511                      elif collection_format == 'pipes':
   512                          delimiter = '|'
   513                      else:  # csv is the default
   514                          delimiter = ','
   515                      new_params.append(
   516                          (k, delimiter.join(str(value) for value in v)))
   517              else:
   518                  new_params.append((k, v))
   519          return new_params
   520  
   521      @staticmethod
   522      def get_file_data_and_close_file(file_instance: io.IOBase) -> bytes:
   523          file_data = file_instance.read()
   524          file_instance.close()
   525          return file_data
   526  
   527      def files_parameters(self, files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None):
   528          """Builds form parameters.
   529  
   530          :param files: None or a dict with key=param_name and
   531              value is a list of open file objects
   532          :return: List of tuples of form parameters with file data
   533          """
   534          if files is None:
   535              return []
   536  
   537          params = []
   538          for param_name, file_instances in files.items():
   539              if file_instances is None:
   540                  # if the file field is nullable, skip None values
   541                  continue
   542              for file_instance in file_instances:
   543                  if file_instance is None:
   544                      # if the file field is nullable, skip None values
   545                      continue
   546                  if file_instance.closed is True:
   547                      raise ApiValueError(
   548                          "Cannot read a closed file. The passed in file_type "
   549                          "for %s must be open." % param_name
   550                      )
   551                  filename = os.path.basename(file_instance.name)
   552                  filedata = self.get_file_data_and_close_file(file_instance)
   553                  mimetype = (mimetypes.guess_type(filename)[0] or
   554                              'application/octet-stream')
   555                  params.append(
   556                      tuple([param_name, tuple([filename, filedata, mimetype])]))
   557  
   558          return params
   559  
   560      def select_header_accept(self, accepts):
   561          """Returns `Accept` based on an array of accepts provided.
   562  
   563          :param accepts: List of headers.
   564          :return: Accept (e.g. application/json).
   565          """
   566          if not accepts:
   567              return
   568  
   569          accepts = [x.lower() for x in accepts]
   570  
   571          if 'application/json' in accepts:
   572              return 'application/json'
   573          else:
   574              return ', '.join(accepts)
   575  
   576      def select_header_content_type(self, content_types):
   577          """Returns `Content-Type` based on an array of content_types provided.
   578  
   579          :param content_types: List of content-types.
   580          :return: Content-Type (e.g. application/json).
   581          """
   582          if not content_types:
   583              return 'application/json'
   584  
   585          content_types = [x.lower() for x in content_types]
   586  
   587          if 'application/json' in content_types or '*/*' in content_types:
   588              return 'application/json'
   589          else:
   590              return content_types[0]
   591  
   592      def update_params_for_auth(self, headers, queries, auth_settings,
   593                                 resource_path, method, body):
   594          """Updates header and query params based on authentication setting.
   595  
   596          :param headers: Header parameters dict to be updated.
   597          :param queries: Query parameters tuple list to be updated.
   598          :param auth_settings: Authentication setting identifiers list.
   599          :param resource_path: A string representation of the HTTP request resource path.
   600          :param method: A string representation of the HTTP request method.
   601          :param body: A object representing the body of the HTTP request.
   602              The object type is the return value of _encoder.default().
   603          """
   604          if not auth_settings:
   605              return
   606  
   607          for auth in auth_settings:
   608              auth_setting = self.configuration.auth_settings().get(auth)
   609              if auth_setting:
   610                  if auth_setting['in'] == 'cookie':
   611                      headers['Cookie'] = auth_setting['value']
   612                  elif auth_setting['in'] == 'header':
   613                      if auth_setting['type'] != 'http-signature':
   614                          headers[auth_setting['key']] = auth_setting['value']
   615                  elif auth_setting['in'] == 'query':
   616                      queries.append((auth_setting['key'], auth_setting['value']))
   617                  else:
   618                      raise ApiValueError(
   619                          'Authentication token must be in `query` or `header`'
   620                      )
   621  
   622  
   623  class Endpoint(object):
   624      def __init__(self, settings=None, params_map=None, root_map=None,
   625                   headers_map=None, api_client=None, callable=None):
   626          """Creates an endpoint
   627  
   628          Args:
   629              settings (dict): see below key value pairs
   630                  'response_type' (tuple/None): response type
   631                  'auth' (list): a list of auth type keys
   632                  'endpoint_path' (str): the endpoint path
   633                  'operation_id' (str): endpoint string identifier
   634                  'http_method' (str): POST/PUT/PATCH/GET etc
   635                  'servers' (list): list of str servers that this endpoint is at
   636              params_map (dict): see below key value pairs
   637                  'all' (list): list of str endpoint parameter names
   638                  'required' (list): list of required parameter names
   639                  'nullable' (list): list of nullable parameter names
   640                  'enum' (list): list of parameters with enum values
   641                  'validation' (list): list of parameters with validations
   642              root_map
   643                  'validations' (dict): the dict mapping endpoint parameter tuple
   644                      paths to their validation dictionaries
   645                  'allowed_values' (dict): the dict mapping endpoint parameter
   646                      tuple paths to their allowed_values (enum) dictionaries
   647                  'openapi_types' (dict): param_name to openapi type
   648                  'attribute_map' (dict): param_name to camelCase name
   649                  'location_map' (dict): param_name to  'body', 'file', 'form',
   650                      'header', 'path', 'query'
   651                  collection_format_map (dict): param_name to `csv` etc.
   652              headers_map (dict): see below key value pairs
   653                  'accept' (list): list of Accept header strings
   654                  'content_type' (list): list of Content-Type header strings
   655              api_client (ApiClient) api client instance
   656              callable (function): the function which is invoked when the
   657                  Endpoint is called
   658          """
   659          self.settings = settings
   660          self.params_map = params_map
   661          self.params_map['all'].extend([
   662              'async_req',
   663              '_host_index',
   664              '_preload_content',
   665              '_request_timeout',
   666              '_return_http_data_only',
   667              '_check_input_type',
   668              '_check_return_type'
   669          ])
   670          self.params_map['nullable'].extend(['_request_timeout'])
   671          self.validations = root_map['validations']
   672          self.allowed_values = root_map['allowed_values']
   673          self.openapi_types = root_map['openapi_types']
   674          extra_types = {
   675              'async_req': (bool,),
   676              '_host_index': (none_type, int),
   677              '_preload_content': (bool,),
   678              '_request_timeout': (none_type, float, (float,), [float], int, (int,), [int]),
   679              '_return_http_data_only': (bool,),
   680              '_check_input_type': (bool,),
   681              '_check_return_type': (bool,)
   682          }
   683          self.openapi_types.update(extra_types)
   684          self.attribute_map = root_map['attribute_map']
   685          self.location_map = root_map['location_map']
   686          self.collection_format_map = root_map['collection_format_map']
   687          self.headers_map = headers_map
   688          self.api_client = api_client
   689          self.callable = callable
   690  
   691      def __validate_inputs(self, kwargs):
   692          for param in self.params_map['enum']:
   693              if param in kwargs:
   694                  check_allowed_values(
   695                      self.allowed_values,
   696                      (param,),
   697                      kwargs[param]
   698                  )
   699  
   700          for param in self.params_map['validation']:
   701              if param in kwargs:
   702                  check_validations(
   703                      self.validations,
   704                      (param,),
   705                      kwargs[param],
   706                      configuration=self.api_client.configuration
   707                  )
   708  
   709          if kwargs['_check_input_type'] is False:
   710              return
   711  
   712          for key, value in kwargs.items():
   713              fixed_val = validate_and_convert_types(
   714                  value,
   715                  self.openapi_types[key],
   716                  [key],
   717                  False,
   718                  kwargs['_check_input_type'],
   719                  configuration=self.api_client.configuration
   720              )
   721              kwargs[key] = fixed_val
   722  
   723      def __gather_params(self, kwargs):
   724          params = {
   725              'body': None,
   726              'collection_format': {},
   727              'file': {},
   728              'form': [],
   729              'header': {},
   730              'path': {},
   731              'query': []
   732          }
   733  
   734          for param_name, param_value in kwargs.items():
   735              param_location = self.location_map.get(param_name)
   736              if param_location is None:
   737                  continue
   738              if param_location:
   739                  if param_location == 'body':
   740                      params['body'] = param_value
   741                      continue
   742                  base_name = self.attribute_map[param_name]
   743                  if (param_location == 'form' and
   744                          self.openapi_types[param_name] == (file_type,)):
   745                      params['file'][param_name] = [param_value]
   746                  elif (param_location == 'form' and
   747                          self.openapi_types[param_name] == ([file_type],)):
   748                      # param_value is already a list
   749                      params['file'][param_name] = param_value
   750                  elif param_location in {'form', 'query'}:
   751                      param_value_full = (base_name, param_value)
   752                      params[param_location].append(param_value_full)
   753                  if param_location not in {'form', 'query'}:
   754                      params[param_location][base_name] = param_value
   755                  collection_format = self.collection_format_map.get(param_name)
   756                  if collection_format:
   757                      params['collection_format'][base_name] = collection_format
   758  
   759          return params
   760  
   761      def __call__(self, *args, **kwargs):
   762          """ This method is invoked when endpoints are called
   763          Example:
   764  
   765          api_instance = ActionsApi()
   766          api_instance.get_run  # this is an instance of the class Endpoint
   767          api_instance.get_run()  # this invokes api_instance.get_run.__call__()
   768          which then invokes the callable functions stored in that endpoint at
   769          api_instance.get_run.callable or self.callable in this class
   770  
   771          """
   772          return self.callable(self, *args, **kwargs)
   773  
   774      def call_with_http_info(self, **kwargs):
   775  
   776          try:
   777              index = self.api_client.configuration.server_operation_index.get(
   778                  self.settings['operation_id'], self.api_client.configuration.server_index
   779              ) if kwargs['_host_index'] is None else kwargs['_host_index']
   780              server_variables = self.api_client.configuration.server_operation_variables.get(
   781                  self.settings['operation_id'], self.api_client.configuration.server_variables
   782              )
   783              _host = self.api_client.configuration.get_host_from_settings(
   784                  index, variables=server_variables, servers=self.settings['servers']
   785              )
   786          except IndexError:
   787              if self.settings['servers']:
   788                  raise ApiValueError(
   789                      "Invalid host index. Must be 0 <= index < %s" %
   790                      len(self.settings['servers'])
   791                  )
   792              _host = None
   793  
   794          for key, value in kwargs.items():
   795              if key not in self.params_map['all']:
   796                  raise ApiTypeError(
   797                      "Got an unexpected parameter '%s'"
   798                      " to method `%s`" %
   799                      (key, self.settings['operation_id'])
   800                  )
   801              # only throw this nullable ApiValueError if _check_input_type
   802              # is False, if _check_input_type==True we catch this case
   803              # in self.__validate_inputs
   804              if (key not in self.params_map['nullable'] and value is None
   805                      and kwargs['_check_input_type'] is False):
   806                  raise ApiValueError(
   807                      "Value may not be None for non-nullable parameter `%s`"
   808                      " when calling `%s`" %
   809                      (key, self.settings['operation_id'])
   810                  )
   811  
   812          for key in self.params_map['required']:
   813              if key not in kwargs.keys():
   814                  raise ApiValueError(
   815                      "Missing the required parameter `%s` when calling "
   816                      "`%s`" % (key, self.settings['operation_id'])
   817                  )
   818  
   819          self.__validate_inputs(kwargs)
   820  
   821          params = self.__gather_params(kwargs)
   822  
   823          accept_headers_list = self.headers_map['accept']
   824          if accept_headers_list:
   825              params['header']['Accept'] = self.api_client.select_header_accept(
   826                  accept_headers_list)
   827  
   828          content_type_headers_list = self.headers_map['content_type']
   829          if content_type_headers_list:
   830              if params['body'] != "":
   831                  header_list = self.api_client.select_header_content_type(
   832                      content_type_headers_list)
   833                  params['header']['Content-Type'] = header_list
   834  
   835          return self.api_client.call_api(
   836              self.settings['endpoint_path'], self.settings['http_method'],
   837              params['path'],
   838              params['query'],
   839              params['header'],
   840              body=params['body'],
   841              post_params=params['form'],
   842              files=params['file'],
   843              response_type=self.settings['response_type'],
   844              auth_settings=self.settings['auth'],
   845              async_req=kwargs['async_req'],
   846              _check_type=kwargs['_check_return_type'],
   847              _return_http_data_only=kwargs['_return_http_data_only'],
   848              _preload_content=kwargs['_preload_content'],
   849              _request_timeout=kwargs['_request_timeout'],
   850              _host=_host,
   851              collection_formats=params['collection_format'])