github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/clients/python/bacalhau_apiclient/api_client.py (about) 1 # coding: utf-8 2 """ 3 Bacalhau API 4 5 This page is the reference of the Bacalhau REST API. Project docs are available at https://docs.bacalhau.org/. Find more information about Bacalhau at https://github.com/filecoin-project/bacalhau. # noqa: E501 6 7 OpenAPI spec version: 0.3.22.post4 8 Contact: team@bacalhau.org 9 Generated by: https://github.com/swagger-api/swagger-codegen.git 10 """ 11 12 from __future__ import absolute_import 13 14 import datetime 15 import json 16 import mimetypes 17 from multiprocessing.pool import ThreadPool 18 import os 19 import re 20 import tempfile 21 22 # python 2 and python 3 compatibility library 23 import six 24 from six.moves.urllib.parse import quote 25 26 from bacalhau_apiclient.configuration import Configuration 27 import bacalhau_apiclient.models 28 from bacalhau_apiclient import rest 29 30 31 class ApiClient(object): 32 """Generic API client for Swagger client library builds. 33 34 Swagger generic API client. This client handles the client- 35 server communication, and is invariant across implementations. Specifics of 36 the methods and models for each application are generated from the Swagger 37 templates. 38 39 NOTE: This class is auto generated by the swagger code generator program. 40 Ref: https://github.com/swagger-api/swagger-codegen 41 Do not edit the class manually. 42 43 :param configuration: .Configuration object for this client 44 :param header_name: a header to pass when making calls to the API. 45 :param header_value: a header value to pass when making calls to 46 the API. 47 :param cookie: a cookie to include in the header when making calls 48 to the API 49 """ 50 51 PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types 52 NATIVE_TYPES_MAPPING = { 53 'int': int, 54 'long': int if six.PY3 else long, # noqa: F821 55 'float': float, 56 'str': str, 57 'bool': bool, 58 'date': datetime.date, 59 'datetime': datetime.datetime, 60 'object': object, 61 } 62 63 def __init__(self, configuration=None, header_name=None, header_value=None, 64 cookie=None): 65 if configuration is None: 66 configuration = Configuration() 67 self.configuration = configuration 68 69 # Use the pool property to lazily initialize the ThreadPool. 70 self._pool = None 71 self.rest_client = rest.RESTClientObject(configuration) 72 self.default_headers = {} 73 if header_name is not None: 74 self.default_headers[header_name] = header_value 75 self.cookie = cookie 76 # Set default User-Agent. 77 self.user_agent = 'Swagger-Codegen/0.3.22.post4/python' 78 self.client_side_validation = configuration.client_side_validation 79 80 def __del__(self): 81 if self._pool is not None: 82 self._pool.close() 83 self._pool.join() 84 85 @property 86 def pool(self): 87 if self._pool is None: 88 self._pool = ThreadPool() 89 return self._pool 90 91 @property 92 def user_agent(self): 93 """User agent for this API client""" 94 return self.default_headers['User-Agent'] 95 96 @user_agent.setter 97 def user_agent(self, value): 98 self.default_headers['User-Agent'] = value 99 100 def set_default_header(self, header_name, header_value): 101 self.default_headers[header_name] = header_value 102 103 def __call_api( 104 self, resource_path, method, path_params=None, 105 query_params=None, header_params=None, body=None, post_params=None, 106 files=None, response_type=None, auth_settings=None, 107 _return_http_data_only=None, collection_formats=None, 108 _preload_content=True, _request_timeout=None): 109 110 config = self.configuration 111 112 # header parameters 113 header_params = header_params or {} 114 header_params.update(self.default_headers) 115 if self.cookie: 116 header_params['Cookie'] = self.cookie 117 if header_params: 118 header_params = self.sanitize_for_serialization(header_params) 119 header_params = dict(self.parameters_to_tuples(header_params, 120 collection_formats)) 121 122 # path parameters 123 if path_params: 124 path_params = self.sanitize_for_serialization(path_params) 125 path_params = self.parameters_to_tuples(path_params, 126 collection_formats) 127 for k, v in path_params: 128 # specified safe chars, encode everything 129 resource_path = resource_path.replace( 130 '{%s}' % k, 131 quote(str(v), safe=config.safe_chars_for_path_param) 132 ) 133 134 # query parameters 135 if query_params: 136 query_params = self.sanitize_for_serialization(query_params) 137 query_params = self.parameters_to_tuples(query_params, 138 collection_formats) 139 140 # post parameters 141 if post_params or files: 142 post_params = self.prepare_post_parameters(post_params, files) 143 post_params = self.sanitize_for_serialization(post_params) 144 post_params = self.parameters_to_tuples(post_params, 145 collection_formats) 146 147 # auth setting 148 self.update_params_for_auth(header_params, query_params, auth_settings) 149 150 # body 151 if body: 152 body = self.sanitize_for_serialization(body) 153 154 # request url 155 url = self.configuration.host + resource_path 156 157 # perform request and return response 158 response_data = self.request( 159 method, url, query_params=query_params, headers=header_params, 160 post_params=post_params, body=body, 161 _preload_content=_preload_content, 162 _request_timeout=_request_timeout) 163 164 self.last_response = response_data 165 166 return_data = response_data 167 if _preload_content: 168 # deserialize response data 169 if response_type: 170 return_data = self.deserialize(response_data, response_type) 171 else: 172 return_data = None 173 174 if _return_http_data_only: 175 return (return_data) 176 else: 177 return (return_data, response_data.status, 178 response_data.getheaders()) 179 180 def sanitize_for_serialization(self, obj): 181 """Builds a JSON POST object. 182 183 If obj is None, return None. 184 If obj is str, int, long, float, bool, return directly. 185 If obj is datetime.datetime, datetime.date 186 convert to string in iso8601 format. 187 If obj is list, sanitize each element in the list. 188 If obj is dict, return the dict. 189 If obj is swagger model, return the properties dict. 190 191 :param obj: The data to serialize. 192 :return: The serialized form of data. 193 """ 194 if obj is None: 195 return None 196 elif isinstance(obj, self.PRIMITIVE_TYPES): 197 return obj 198 elif isinstance(obj, list): 199 return [self.sanitize_for_serialization(sub_obj) 200 for sub_obj in obj] 201 elif isinstance(obj, tuple): 202 return tuple(self.sanitize_for_serialization(sub_obj) 203 for sub_obj in obj) 204 elif isinstance(obj, (datetime.datetime, datetime.date)): 205 return obj.isoformat() 206 207 if isinstance(obj, dict): 208 obj_dict = obj 209 else: 210 # Convert model obj to dict except 211 # attributes `swagger_types`, `attribute_map` 212 # and attributes which value is not None. 213 # Convert attribute name to json key in 214 # model definition for request. 215 obj_dict = {obj.attribute_map[attr]: getattr(obj, attr) 216 for attr, _ in six.iteritems(obj.swagger_types) 217 if getattr(obj, attr) is not None} 218 219 return {key: self.sanitize_for_serialization(val) 220 for key, val in six.iteritems(obj_dict)} 221 222 def deserialize(self, response, response_type): 223 """Deserializes response into an object. 224 225 :param response: RESTResponse object to be deserialized. 226 :param response_type: class literal for 227 deserialized object, or string of class name. 228 229 :return: deserialized object. 230 """ 231 # handle file downloading 232 # save response body into a tmp file and return the instance 233 if response_type == "file": 234 return self.__deserialize_file(response) 235 236 # fetch data from response object 237 try: 238 data = json.loads(response.data) 239 except ValueError: 240 data = response.data 241 242 return self.__deserialize(data, response_type) 243 244 def __deserialize(self, data, klass): 245 """Deserializes dict, list, str into an object. 246 247 :param data: dict, list or str. 248 :param klass: class literal, or string of class name. 249 250 :return: object. 251 """ 252 if data is None: 253 return None 254 255 if type(klass) == str: 256 if klass.startswith('list['): 257 sub_kls = re.match(r'list\[(.*)\]', klass).group(1) 258 return [self.__deserialize(sub_data, sub_kls) 259 for sub_data in data] 260 261 if klass.startswith('dict('): 262 sub_kls = re.match(r'dict\(([^,]*), (.*)\)', klass).group(2) 263 return {k: self.__deserialize(v, sub_kls) 264 for k, v in six.iteritems(data)} 265 266 # convert str to class 267 if klass in self.NATIVE_TYPES_MAPPING: 268 klass = self.NATIVE_TYPES_MAPPING[klass] 269 else: 270 klass = getattr(bacalhau_apiclient.models, klass) 271 272 if klass in self.PRIMITIVE_TYPES: 273 return self.__deserialize_primitive(data, klass) 274 elif klass == object: 275 return self.__deserialize_object(data) 276 elif klass == datetime.date: 277 return self.__deserialize_date(data) 278 elif klass == datetime.datetime: 279 return self.__deserialize_datatime(data) 280 else: 281 return self.__deserialize_model(data, klass) 282 283 def call_api(self, resource_path, method, 284 path_params=None, query_params=None, header_params=None, 285 body=None, post_params=None, files=None, 286 response_type=None, auth_settings=None, async_req=None, 287 _return_http_data_only=None, collection_formats=None, 288 _preload_content=True, _request_timeout=None): 289 """Makes the HTTP request (synchronous) and returns deserialized data. 290 291 To make an async request, set the async_req parameter. 292 293 :param resource_path: Path to method endpoint. 294 :param method: Method to call. 295 :param path_params: Path parameters in the url. 296 :param query_params: Query parameters in the url. 297 :param header_params: Header parameters to be 298 placed in the request header. 299 :param body: Request body. 300 :param post_params dict: Request post form parameters, 301 for `application/x-www-form-urlencoded`, `multipart/form-data`. 302 :param auth_settings list: Auth Settings names for the request. 303 :param response: Response data type. 304 :param files dict: key -> filename, value -> filepath, 305 for `multipart/form-data`. 306 :param async_req bool: execute request asynchronously 307 :param _return_http_data_only: response data without head status code 308 and headers 309 :param collection_formats: dict of collection formats for path, query, 310 header, and post parameters. 311 :param _preload_content: if False, the urllib3.HTTPResponse object will 312 be returned without reading/decoding response 313 data. Default is True. 314 :param _request_timeout: timeout setting for this request. If one 315 number provided, it will be total request 316 timeout. It can also be a pair (tuple) of 317 (connection, read) timeouts. 318 :return: 319 If async_req parameter is True, 320 the request will be called asynchronously. 321 The method will return the request thread. 322 If parameter async_req is False or missing, 323 then the method will return the response directly. 324 """ 325 if not async_req: 326 return self.__call_api(resource_path, method, 327 path_params, query_params, header_params, 328 body, post_params, files, 329 response_type, auth_settings, 330 _return_http_data_only, collection_formats, 331 _preload_content, _request_timeout) 332 else: 333 thread = self.pool.apply_async(self.__call_api, (resource_path, 334 method, path_params, query_params, 335 header_params, body, 336 post_params, files, 337 response_type, auth_settings, 338 _return_http_data_only, 339 collection_formats, 340 _preload_content, _request_timeout)) 341 return thread 342 343 def request(self, method, url, query_params=None, headers=None, 344 post_params=None, body=None, _preload_content=True, 345 _request_timeout=None): 346 """Makes the HTTP request using RESTClient.""" 347 if method == "GET": 348 return self.rest_client.GET(url, 349 query_params=query_params, 350 _preload_content=_preload_content, 351 _request_timeout=_request_timeout, 352 headers=headers) 353 elif method == "HEAD": 354 return self.rest_client.HEAD(url, 355 query_params=query_params, 356 _preload_content=_preload_content, 357 _request_timeout=_request_timeout, 358 headers=headers) 359 elif method == "OPTIONS": 360 return self.rest_client.OPTIONS(url, 361 query_params=query_params, 362 headers=headers, 363 post_params=post_params, 364 _preload_content=_preload_content, 365 _request_timeout=_request_timeout, 366 body=body) 367 elif method == "POST": 368 return self.rest_client.POST(url, 369 query_params=query_params, 370 headers=headers, 371 post_params=post_params, 372 _preload_content=_preload_content, 373 _request_timeout=_request_timeout, 374 body=body) 375 elif method == "PUT": 376 return self.rest_client.PUT(url, 377 query_params=query_params, 378 headers=headers, 379 post_params=post_params, 380 _preload_content=_preload_content, 381 _request_timeout=_request_timeout, 382 body=body) 383 elif method == "PATCH": 384 return self.rest_client.PATCH(url, 385 query_params=query_params, 386 headers=headers, 387 post_params=post_params, 388 _preload_content=_preload_content, 389 _request_timeout=_request_timeout, 390 body=body) 391 elif method == "DELETE": 392 return self.rest_client.DELETE(url, 393 query_params=query_params, 394 headers=headers, 395 _preload_content=_preload_content, 396 _request_timeout=_request_timeout, 397 body=body) 398 else: 399 raise ValueError( 400 "http method must be `GET`, `HEAD`, `OPTIONS`," 401 " `POST`, `PATCH`, `PUT` or `DELETE`." 402 ) 403 404 def parameters_to_tuples(self, params, collection_formats): 405 """Get parameters as list of tuples, formatting collections. 406 407 :param params: Parameters as dict or list of two-tuples 408 :param dict collection_formats: Parameter collection formats 409 :return: Parameters as list of tuples, collections formatted 410 """ 411 new_params = [] 412 if collection_formats is None: 413 collection_formats = {} 414 for k, v in six.iteritems(params) if isinstance(params, dict) else params: # noqa: E501 415 if k in collection_formats: 416 collection_format = collection_formats[k] 417 if collection_format == 'multi': 418 new_params.extend((k, value) for value in v) 419 else: 420 if collection_format == 'ssv': 421 delimiter = ' ' 422 elif collection_format == 'tsv': 423 delimiter = '\t' 424 elif collection_format == 'pipes': 425 delimiter = '|' 426 else: # csv is the default 427 delimiter = ',' 428 new_params.append( 429 (k, delimiter.join(str(value) for value in v))) 430 else: 431 new_params.append((k, v)) 432 return new_params 433 434 def prepare_post_parameters(self, post_params=None, files=None): 435 """Builds form parameters. 436 437 :param post_params: Normal form parameters. 438 :param files: File parameters. 439 :return: Form parameters with files. 440 """ 441 params = [] 442 443 if post_params: 444 params = post_params 445 446 if files: 447 for k, v in six.iteritems(files): 448 if not v: 449 continue 450 file_names = v if type(v) is list else [v] 451 for n in file_names: 452 with open(n, 'rb') as f: 453 filename = os.path.basename(f.name) 454 filedata = f.read() 455 mimetype = (mimetypes.guess_type(filename)[0] or 456 'application/octet-stream') 457 params.append( 458 tuple([k, tuple([filename, filedata, mimetype])])) 459 460 return params 461 462 def select_header_accept(self, accepts): 463 """Returns `Accept` based on an array of accepts provided. 464 465 :param accepts: List of headers. 466 :return: Accept (e.g. application/json). 467 """ 468 if not accepts: 469 return 470 471 accepts = [x.lower() for x in accepts] 472 473 if 'application/json' in accepts: 474 return 'application/json' 475 else: 476 return ', '.join(accepts) 477 478 def select_header_content_type(self, content_types): 479 """Returns `Content-Type` based on an array of content_types provided. 480 481 :param content_types: List of content-types. 482 :return: Content-Type (e.g. application/json). 483 """ 484 if not content_types: 485 return 'application/json' 486 487 content_types = [x.lower() for x in content_types] 488 489 if 'application/json' in content_types or '*/*' in content_types: 490 return 'application/json' 491 else: 492 return content_types[0] 493 494 def update_params_for_auth(self, headers, querys, auth_settings): 495 """Updates header and query params based on authentication setting. 496 497 :param headers: Header parameters dict to be updated. 498 :param querys: Query parameters tuple list to be updated. 499 :param auth_settings: Authentication setting identifiers list. 500 """ 501 if not auth_settings: 502 return 503 504 for auth in auth_settings: 505 auth_setting = self.configuration.auth_settings().get(auth) 506 if auth_setting: 507 if not auth_setting['value']: 508 continue 509 elif auth_setting['in'] == 'header': 510 headers[auth_setting['key']] = auth_setting['value'] 511 elif auth_setting['in'] == 'query': 512 querys.append((auth_setting['key'], auth_setting['value'])) 513 else: 514 raise ValueError( 515 'Authentication token must be in `query` or `header`' 516 ) 517 518 def __deserialize_file(self, response): 519 """Deserializes body to file 520 521 Saves response body into a file in a temporary folder, 522 using the filename from the `Content-Disposition` header if provided. 523 524 :param response: RESTResponse. 525 :return: file path. 526 """ 527 fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) 528 os.close(fd) 529 os.remove(path) 530 531 content_disposition = response.getheader("Content-Disposition") 532 if content_disposition: 533 filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', 534 content_disposition).group(1) 535 path = os.path.join(os.path.dirname(path), filename) 536 537 with open(path, "w") as f: 538 f.write(response.data) 539 540 return path 541 542 def __deserialize_primitive(self, data, klass): 543 """Deserializes string to primitive type. 544 545 :param data: str. 546 :param klass: class literal. 547 548 :return: int, long, float, str, bool. 549 """ 550 try: 551 return klass(data) 552 except UnicodeEncodeError: 553 return six.text_type(data) 554 except TypeError: 555 return data 556 557 def __deserialize_object(self, value): 558 """Return a original value. 559 560 :return: object. 561 """ 562 return value 563 564 def __deserialize_date(self, string): 565 """Deserializes string to date. 566 567 :param string: str. 568 :return: date. 569 """ 570 try: 571 from dateutil.parser import parse 572 return parse(string).date() 573 except ImportError: 574 return string 575 except ValueError: 576 raise rest.ApiException( 577 status=0, 578 reason="Failed to parse `{0}` as date object".format(string) 579 ) 580 581 def __deserialize_datatime(self, string): 582 """Deserializes string to datetime. 583 584 The string should be in iso8601 datetime format. 585 586 :param string: str. 587 :return: datetime. 588 """ 589 try: 590 from dateutil.parser import parse 591 return parse(string) 592 except ImportError: 593 return string 594 except ValueError: 595 raise rest.ApiException( 596 status=0, 597 reason=( 598 "Failed to parse `{0}` as datetime object" 599 .format(string) 600 ) 601 ) 602 603 def __hasattr(self, object, name): 604 return name in object.__class__.__dict__ 605 606 def __deserialize_model(self, data, klass): 607 """Deserializes list or dict to model. 608 609 :param data: dict, list. 610 :param klass: class literal. 611 :return: model object. 612 """ 613 614 if (not klass.swagger_types and 615 not self.__hasattr(klass, 'get_real_child_model')): 616 return data 617 618 kwargs = {} 619 if klass.swagger_types is not None: 620 for attr, attr_type in six.iteritems(klass.swagger_types): 621 if (data is not None and 622 klass.attribute_map[attr] in data and 623 isinstance(data, (list, dict))): 624 value = data[klass.attribute_map[attr]] 625 kwargs[attr] = self.__deserialize(value, attr_type) 626 627 instance = klass(**kwargs) 628 629 if (isinstance(instance, dict) and 630 klass.swagger_types is not None and 631 isinstance(data, dict)): 632 for key, value in data.items(): 633 if key not in klass.swagger_types: 634 instance[key] = value 635 if self.__hasattr(instance, 'get_real_child_model'): 636 klass_name = instance.get_real_child_model(data) 637 if klass_name: 638 instance = self.__deserialize(data, klass_name) 639 return instance