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'])