qi-compute-api-client 0.53.0__py3-none-any.whl → 0.54.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of qi-compute-api-client might be problematic. Click here for more details.

Files changed (188) hide show
  1. compute_api_client/__init__.py +194 -95
  2. compute_api_client/api/algorithms_api.py +75 -81
  3. compute_api_client/api/auth_config_api.py +16 -24
  4. compute_api_client/api/backend_api.py +70 -86
  5. compute_api_client/api/backend_types_api.py +43 -56
  6. compute_api_client/api/batch_jobs_api.py +102 -120
  7. compute_api_client/api/commits_api.py +85 -80
  8. compute_api_client/api/files_api.py +62 -67
  9. compute_api_client/api/final_results_api.py +42 -53
  10. compute_api_client/api/health_api.py +16 -25
  11. compute_api_client/api/jobs_api.py +76 -83
  12. compute_api_client/api/languages_api.py +30 -42
  13. compute_api_client/api/members_api.py +62 -67
  14. compute_api_client/api/permissions_api.py +56 -70
  15. compute_api_client/api/projects_api.py +89 -97
  16. compute_api_client/api/reservations_api.py +57 -72
  17. compute_api_client/api/results_api.py +76 -83
  18. compute_api_client/api/teams_api.py +30 -42
  19. compute_api_client/api/transactions_api.py +31 -44
  20. compute_api_client/api/users_api.py +62 -67
  21. compute_api_client/api_client.py +135 -75
  22. compute_api_client/api_response.py +3 -3
  23. compute_api_client/configuration.py +176 -36
  24. compute_api_client/docs/Algorithm.md +8 -7
  25. compute_api_client/docs/AlgorithmIn.md +7 -6
  26. compute_api_client/docs/AlgorithmType.md +5 -3
  27. compute_api_client/docs/AlgorithmsApi.md +15 -10
  28. compute_api_client/docs/AuthConfig.md +3 -2
  29. compute_api_client/docs/AuthConfigApi.md +3 -2
  30. compute_api_client/docs/Backend.md +9 -8
  31. compute_api_client/docs/BackendApi.md +15 -10
  32. compute_api_client/docs/BackendIn.md +8 -7
  33. compute_api_client/docs/BackendPatch.md +5 -4
  34. compute_api_client/docs/BackendStatus.md +9 -3
  35. compute_api_client/docs/BackendType.md +20 -19
  36. compute_api_client/docs/BackendTypePatch.md +3 -2
  37. compute_api_client/docs/BackendTypesApi.md +15 -8
  38. compute_api_client/docs/BackendWithAuthentication.md +10 -9
  39. compute_api_client/docs/BatchJob.md +10 -9
  40. compute_api_client/docs/BatchJobIn.md +4 -3
  41. compute_api_client/docs/BatchJobStatus.md +11 -3
  42. compute_api_client/docs/BatchJobsApi.md +23 -16
  43. compute_api_client/docs/Commit.md +8 -7
  44. compute_api_client/docs/CommitIn.md +5 -4
  45. compute_api_client/docs/CommitsApi.md +15 -10
  46. compute_api_client/docs/CompilePayload.md +4 -3
  47. compute_api_client/docs/CompileStage.md +11 -3
  48. compute_api_client/docs/Domain.md +7 -3
  49. compute_api_client/docs/File.md +10 -9
  50. compute_api_client/docs/FileIn.md +9 -8
  51. compute_api_client/docs/FilesApi.md +12 -8
  52. compute_api_client/docs/FinalResult.md +7 -6
  53. compute_api_client/docs/FinalResultIn.md +5 -4
  54. compute_api_client/docs/FinalResultsApi.md +9 -6
  55. compute_api_client/docs/HTTPBadRequestError.md +3 -2
  56. compute_api_client/docs/HTTPNotFoundError.md +3 -2
  57. compute_api_client/docs/HTTPValidationError.md +3 -2
  58. compute_api_client/docs/HealthApi.md +3 -2
  59. compute_api_client/docs/Job.md +13 -12
  60. compute_api_client/docs/JobIn.md +6 -5
  61. compute_api_client/docs/JobPatch.md +8 -7
  62. compute_api_client/docs/JobStatus.md +11 -3
  63. compute_api_client/docs/JobsApi.md +15 -10
  64. compute_api_client/docs/Language.md +6 -5
  65. compute_api_client/docs/LanguagesApi.md +6 -4
  66. compute_api_client/docs/Member.md +8 -7
  67. compute_api_client/docs/MemberId.md +28 -0
  68. compute_api_client/docs/MemberIn.md +7 -6
  69. compute_api_client/docs/MembersApi.md +12 -8
  70. compute_api_client/docs/PageAlgorithm.md +3 -2
  71. compute_api_client/docs/PageBackend.md +3 -2
  72. compute_api_client/docs/PageBackendType.md +3 -2
  73. compute_api_client/docs/PageBatchJob.md +3 -2
  74. compute_api_client/docs/PageCommit.md +3 -2
  75. compute_api_client/docs/PageFile.md +3 -2
  76. compute_api_client/docs/PageJob.md +3 -2
  77. compute_api_client/docs/PageLanguage.md +3 -2
  78. compute_api_client/docs/PageMember.md +3 -2
  79. compute_api_client/docs/PagePermission.md +3 -2
  80. compute_api_client/docs/PagePermissionGroup.md +3 -2
  81. compute_api_client/docs/PageProject.md +3 -2
  82. compute_api_client/docs/PageReservation.md +3 -2
  83. compute_api_client/docs/PageResult.md +3 -2
  84. compute_api_client/docs/PageTeam.md +3 -2
  85. compute_api_client/docs/PageTransaction.md +3 -2
  86. compute_api_client/docs/PageUser.md +3 -2
  87. compute_api_client/docs/Permission.md +6 -5
  88. compute_api_client/docs/PermissionGroup.md +5 -4
  89. compute_api_client/docs/PermissionsApi.md +12 -8
  90. compute_api_client/docs/Project.md +9 -8
  91. compute_api_client/docs/ProjectIn.md +7 -6
  92. compute_api_client/docs/ProjectPatch.md +3 -2
  93. compute_api_client/docs/ProjectsApi.md +23 -13
  94. compute_api_client/docs/Reservation.md +9 -8
  95. compute_api_client/docs/ReservationIn.md +7 -6
  96. compute_api_client/docs/ReservationsApi.md +12 -8
  97. compute_api_client/docs/Result.md +7 -6
  98. compute_api_client/docs/ResultIn.md +5 -4
  99. compute_api_client/docs/ResultsApi.md +15 -10
  100. compute_api_client/docs/Role.md +5 -3
  101. compute_api_client/docs/ShareType.md +7 -3
  102. compute_api_client/docs/Team.md +7 -6
  103. compute_api_client/docs/TeamsApi.md +6 -4
  104. compute_api_client/docs/Transaction.md +6 -5
  105. compute_api_client/docs/TransactionDomain.md +28 -0
  106. compute_api_client/docs/TransactionsApi.md +6 -4
  107. compute_api_client/docs/User.md +11 -10
  108. compute_api_client/docs/UserIn.md +10 -9
  109. compute_api_client/docs/UsersApi.md +12 -8
  110. compute_api_client/docs/ValidationError.md +4 -3
  111. compute_api_client/docs/ValidationErrorLocInner.md +28 -0
  112. compute_api_client/exceptions.py +74 -24
  113. compute_api_client/models/__init__.py +1 -1
  114. compute_api_client/models/algorithm.py +19 -20
  115. compute_api_client/models/algorithm_in.py +18 -19
  116. compute_api_client/models/algorithm_type.py +1 -9
  117. compute_api_client/models/auth_config.py +14 -14
  118. compute_api_client/models/backend.py +20 -20
  119. compute_api_client/models/backend_in.py +19 -19
  120. compute_api_client/models/backend_patch.py +16 -15
  121. compute_api_client/models/backend_status.py +1 -9
  122. compute_api_client/models/backend_type.py +31 -32
  123. compute_api_client/models/backend_type_patch.py +14 -15
  124. compute_api_client/models/backend_with_authentication.py +21 -21
  125. compute_api_client/models/batch_job.py +21 -20
  126. compute_api_client/models/batch_job_in.py +15 -15
  127. compute_api_client/models/batch_job_status.py +1 -9
  128. compute_api_client/models/commit.py +19 -19
  129. compute_api_client/models/commit_in.py +16 -16
  130. compute_api_client/models/compile_payload.py +15 -15
  131. compute_api_client/models/compile_stage.py +1 -9
  132. compute_api_client/models/domain.py +1 -9
  133. compute_api_client/models/file.py +21 -22
  134. compute_api_client/models/file_in.py +20 -21
  135. compute_api_client/models/final_result.py +18 -17
  136. compute_api_client/models/final_result_in.py +16 -16
  137. compute_api_client/models/http_bad_request_error.py +14 -14
  138. compute_api_client/models/http_not_found_error.py +14 -14
  139. compute_api_client/models/http_validation_error.py +18 -18
  140. compute_api_client/models/job.py +24 -24
  141. compute_api_client/models/job_in.py +17 -17
  142. compute_api_client/models/job_patch.py +19 -20
  143. compute_api_client/models/job_status.py +1 -9
  144. compute_api_client/models/language.py +17 -18
  145. compute_api_client/models/member.py +19 -19
  146. compute_api_client/models/member_id.py +144 -0
  147. compute_api_client/models/member_in.py +18 -18
  148. compute_api_client/models/page_algorithm.py +18 -19
  149. compute_api_client/models/page_backend.py +18 -19
  150. compute_api_client/models/page_backend_type.py +18 -19
  151. compute_api_client/models/page_batch_job.py +18 -19
  152. compute_api_client/models/page_commit.py +18 -19
  153. compute_api_client/models/page_file.py +18 -19
  154. compute_api_client/models/page_job.py +18 -19
  155. compute_api_client/models/page_language.py +18 -19
  156. compute_api_client/models/page_member.py +18 -19
  157. compute_api_client/models/page_permission.py +18 -19
  158. compute_api_client/models/page_permission_group.py +18 -19
  159. compute_api_client/models/page_project.py +18 -19
  160. compute_api_client/models/page_reservation.py +18 -19
  161. compute_api_client/models/page_result.py +18 -19
  162. compute_api_client/models/page_team.py +18 -19
  163. compute_api_client/models/page_transaction.py +18 -19
  164. compute_api_client/models/page_user.py +18 -19
  165. compute_api_client/models/permission.py +17 -18
  166. compute_api_client/models/permission_group.py +16 -17
  167. compute_api_client/models/project.py +20 -20
  168. compute_api_client/models/project_in.py +18 -19
  169. compute_api_client/models/project_patch.py +14 -15
  170. compute_api_client/models/reservation.py +20 -19
  171. compute_api_client/models/reservation_in.py +18 -17
  172. compute_api_client/models/result.py +18 -17
  173. compute_api_client/models/result_in.py +16 -16
  174. compute_api_client/models/role.py +1 -9
  175. compute_api_client/models/share_type.py +1 -9
  176. compute_api_client/models/team.py +18 -19
  177. compute_api_client/models/transaction.py +17 -17
  178. compute_api_client/models/transaction_domain.py +142 -0
  179. compute_api_client/models/user.py +22 -23
  180. compute_api_client/models/user_in.py +21 -22
  181. compute_api_client/models/validation_error.py +20 -20
  182. compute_api_client/models/validation_error_loc_inner.py +138 -0
  183. compute_api_client/rest.py +51 -26
  184. {qi_compute_api_client-0.53.0.dist-info → qi_compute_api_client-0.54.1.dist-info}/METADATA +12 -9
  185. qi_compute_api_client-0.54.1.dist-info/RECORD +203 -0
  186. qi_compute_api_client-0.53.0.dist-info/RECORD +0 -197
  187. {qi_compute_api_client-0.53.0.dist-info → qi_compute_api_client-0.54.1.dist-info}/WHEEL +0 -0
  188. {qi_compute_api_client-0.53.0.dist-info → qi_compute_api_client-0.54.1.dist-info}/licenses/LICENSE.md +0 -0
@@ -12,9 +12,10 @@
12
12
  """ # noqa: E501
13
13
 
14
14
 
15
- import atexit
16
15
  import datetime
17
16
  from dateutil.parser import parse
17
+ from enum import Enum
18
+ import decimal
18
19
  import json
19
20
  import mimetypes
20
21
  import os
@@ -22,10 +23,11 @@ import re
22
23
  import tempfile
23
24
 
24
25
  from urllib.parse import quote
25
- from typing import Tuple, Optional, List
26
+ from typing import Tuple, Optional, List, Dict, Union
27
+ from pydantic import SecretStr
26
28
 
27
29
  from compute_api_client.configuration import Configuration
28
- from compute_api_client.api_response import ApiResponse
30
+ from compute_api_client.api_response import ApiResponse, T as ApiResponseT
29
31
  import compute_api_client.models
30
32
  from compute_api_client import rest
31
33
  from compute_api_client.exceptions import (
@@ -38,6 +40,7 @@ from compute_api_client.exceptions import (
38
40
  ServiceException
39
41
  )
40
42
 
43
+ RequestSerialized = Tuple[str, str, Dict[str, str], Optional[str], List[str]]
41
44
 
42
45
  class ApiClient:
43
46
  """Generic API client for OpenAPI client library builds.
@@ -64,6 +67,7 @@ class ApiClient:
64
67
  'bool': bool,
65
68
  'date': datetime.date,
66
69
  'datetime': datetime.datetime,
70
+ 'decimal': decimal.Decimal,
67
71
  'object': object,
68
72
  }
69
73
  _pool = None
@@ -150,7 +154,7 @@ class ApiClient:
150
154
  collection_formats=None,
151
155
  _host=None,
152
156
  _request_auth=None
153
- ) -> Tuple:
157
+ ) -> RequestSerialized:
154
158
 
155
159
  """Builds the HTTP request params needed by the request.
156
160
  :param method: Method to call.
@@ -209,7 +213,8 @@ class ApiClient:
209
213
  post_params,
210
214
  collection_formats
211
215
  )
212
- post_params.extend(self.files_parameters(files))
216
+ if files:
217
+ post_params.extend(self.files_parameters(files))
213
218
 
214
219
  # auth setting
215
220
  self.update_params_for_auth(
@@ -227,7 +232,7 @@ class ApiClient:
227
232
  body = self.sanitize_for_serialization(body)
228
233
 
229
234
  # request url
230
- if _host is None:
235
+ if _host is None or self.configuration.ignore_operation_servers:
231
236
  url = self.configuration.host + resource_path
232
237
  else:
233
238
  # use server/host defined in path or operation instead
@@ -276,62 +281,52 @@ class ApiClient:
276
281
  )
277
282
 
278
283
  except ApiException as e:
279
- if e.body:
280
- e.body = e.body.decode('utf-8')
281
284
  raise e
282
285
 
283
286
  return response_data
284
287
 
285
288
  def response_deserialize(
286
289
  self,
287
- response_data=None,
288
- response_types_map=None
289
- ) -> ApiResponse:
290
+ response_data: rest.RESTResponse,
291
+ response_types_map: Optional[Dict[str, ApiResponseT]]=None
292
+ ) -> ApiResponse[ApiResponseT]:
290
293
  """Deserializes response into an object.
291
294
  :param response_data: RESTResponse object to be deserialized.
292
295
  :param response_types_map: dict of response types.
293
296
  :return: ApiResponse
294
297
  """
295
298
 
299
+ msg = "RESTResponse.read() must be called before passing it to response_deserialize()"
300
+ assert response_data.data is not None, msg
296
301
 
297
302
  response_type = response_types_map.get(str(response_data.status), None)
298
303
  if not response_type and isinstance(response_data.status, int) and 100 <= response_data.status <= 599:
299
304
  # if not found, look for '1XX', '2XX', etc.
300
305
  response_type = response_types_map.get(str(response_data.status)[0] + "XX", None)
301
306
 
302
- if not 200 <= response_data.status <= 299:
303
- if response_data.status == 400:
304
- raise BadRequestException(http_resp=response_data)
305
-
306
- if response_data.status == 401:
307
- raise UnauthorizedException(http_resp=response_data)
308
-
309
- if response_data.status == 403:
310
- raise ForbiddenException(http_resp=response_data)
311
-
312
- if response_data.status == 404:
313
- raise NotFoundException(http_resp=response_data)
314
-
315
- if 500 <= response_data.status <= 599:
316
- raise ServiceException(http_resp=response_data)
317
- raise ApiException(http_resp=response_data)
318
-
319
307
  # deserialize response data
320
-
321
- if response_type == "bytearray":
322
- return_data = response_data.data
323
- elif response_type is None:
324
- return_data = None
325
- elif response_type == "file":
326
- return_data = self.__deserialize_file(response_data)
327
- else:
328
- match = None
329
- content_type = response_data.getheader('content-type')
330
- if content_type is not None:
331
- match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type)
332
- encoding = match.group(1) if match else "utf-8"
333
- response_text = response_data.data.decode(encoding)
334
- return_data = self.deserialize(response_text, response_type)
308
+ response_text = None
309
+ return_data = None
310
+ try:
311
+ if response_type == "bytearray":
312
+ return_data = response_data.data
313
+ elif response_type == "file":
314
+ return_data = self.__deserialize_file(response_data)
315
+ elif response_type is not None:
316
+ match = None
317
+ content_type = response_data.getheader('content-type')
318
+ if content_type is not None:
319
+ match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type)
320
+ encoding = match.group(1) if match else "utf-8"
321
+ response_text = response_data.data.decode(encoding)
322
+ return_data = self.deserialize(response_text, response_type, content_type)
323
+ finally:
324
+ if not 200 <= response_data.status <= 299:
325
+ raise ApiException.from_response(
326
+ http_resp=response_data,
327
+ body=response_text,
328
+ data=return_data,
329
+ )
335
330
 
336
331
  return ApiResponse(
337
332
  status_code = response_data.status,
@@ -344,9 +339,11 @@ class ApiClient:
344
339
  """Builds a JSON POST object.
345
340
 
346
341
  If obj is None, return None.
342
+ If obj is SecretStr, return obj.get_secret_value()
347
343
  If obj is str, int, long, float, bool, return directly.
348
344
  If obj is datetime.datetime, datetime.date
349
345
  convert to string in iso8601 format.
346
+ If obj is decimal.Decimal return string representation.
350
347
  If obj is list, sanitize each element in the list.
351
348
  If obj is dict, return the dict.
352
349
  If obj is OpenAPI model, return the properties dict.
@@ -356,6 +353,10 @@ class ApiClient:
356
353
  """
357
354
  if obj is None:
358
355
  return None
356
+ elif isinstance(obj, Enum):
357
+ return obj.value
358
+ elif isinstance(obj, SecretStr):
359
+ return obj.get_secret_value()
359
360
  elif isinstance(obj, self.PRIMITIVE_TYPES):
360
361
  return obj
361
362
  elif isinstance(obj, list):
@@ -368,6 +369,8 @@ class ApiClient:
368
369
  )
369
370
  elif isinstance(obj, (datetime.datetime, datetime.date)):
370
371
  return obj.isoformat()
372
+ elif isinstance(obj, decimal.Decimal):
373
+ return str(obj)
371
374
 
372
375
  elif isinstance(obj, dict):
373
376
  obj_dict = obj
@@ -377,28 +380,49 @@ class ApiClient:
377
380
  # and attributes which value is not None.
378
381
  # Convert attribute name to json key in
379
382
  # model definition for request.
380
- obj_dict = obj.to_dict()
383
+ if hasattr(obj, 'to_dict') and callable(getattr(obj, 'to_dict')):
384
+ obj_dict = obj.to_dict()
385
+ else:
386
+ obj_dict = obj.__dict__
387
+
388
+ if isinstance(obj_dict, list):
389
+ # here we handle instances that can either be a list or something else, and only became a real list by calling to_dict()
390
+ return self.sanitize_for_serialization(obj_dict)
381
391
 
382
392
  return {
383
393
  key: self.sanitize_for_serialization(val)
384
394
  for key, val in obj_dict.items()
385
395
  }
386
396
 
387
- def deserialize(self, response_text, response_type):
397
+ def deserialize(self, response_text: str, response_type: str, content_type: Optional[str]):
388
398
  """Deserializes response into an object.
389
399
 
390
400
  :param response: RESTResponse object to be deserialized.
391
401
  :param response_type: class literal for
392
402
  deserialized object, or string of class name.
403
+ :param content_type: content type of response.
393
404
 
394
405
  :return: deserialized object.
395
406
  """
396
407
 
397
408
  # fetch data from response object
398
- try:
399
- data = json.loads(response_text)
400
- except ValueError:
409
+ if content_type is None:
410
+ try:
411
+ data = json.loads(response_text)
412
+ except ValueError:
413
+ data = response_text
414
+ elif re.match(r'^application/(json|[\w!#$&.+-^_]+\+json)\s*(;|$)', content_type, re.IGNORECASE):
415
+ if response_text == "":
416
+ data = ""
417
+ else:
418
+ data = json.loads(response_text)
419
+ elif re.match(r'^text\/[a-z.+-]+\s*(;|$)', content_type, re.IGNORECASE):
401
420
  data = response_text
421
+ else:
422
+ raise ApiException(
423
+ status=0,
424
+ reason="Unsupported content type: {0}".format(content_type)
425
+ )
402
426
 
403
427
  return self.__deserialize(data, response_type)
404
428
 
@@ -415,12 +439,16 @@ class ApiClient:
415
439
 
416
440
  if isinstance(klass, str):
417
441
  if klass.startswith('List['):
418
- sub_kls = re.match(r'List\[(.*)]', klass).group(1)
442
+ m = re.match(r'List\[(.*)]', klass)
443
+ assert m is not None, "Malformed List type definition"
444
+ sub_kls = m.group(1)
419
445
  return [self.__deserialize(sub_data, sub_kls)
420
446
  for sub_data in data]
421
447
 
422
448
  if klass.startswith('Dict['):
423
- sub_kls = re.match(r'Dict\[([^,]*), (.*)]', klass).group(2)
449
+ m = re.match(r'Dict\[([^,]*), (.*)]', klass)
450
+ assert m is not None, "Malformed Dict type definition"
451
+ sub_kls = m.group(2)
424
452
  return {k: self.__deserialize(v, sub_kls)
425
453
  for k, v in data.items()}
426
454
 
@@ -438,6 +466,10 @@ class ApiClient:
438
466
  return self.__deserialize_date(data)
439
467
  elif klass == datetime.datetime:
440
468
  return self.__deserialize_datetime(data)
469
+ elif klass == decimal.Decimal:
470
+ return decimal.Decimal(data)
471
+ elif issubclass(klass, Enum):
472
+ return self.__deserialize_enum(data, klass)
441
473
  else:
442
474
  return self.__deserialize_model(data, klass)
443
475
 
@@ -448,7 +480,7 @@ class ApiClient:
448
480
  :param dict collection_formats: Parameter collection formats
449
481
  :return: Parameters as list of tuples, collections formatted
450
482
  """
451
- new_params = []
483
+ new_params: List[Tuple[str, str]] = []
452
484
  if collection_formats is None:
453
485
  collection_formats = {}
454
486
  for k, v in params.items() if isinstance(params, dict) else params:
@@ -478,7 +510,7 @@ class ApiClient:
478
510
  :param dict collection_formats: Parameter collection formats
479
511
  :return: URL query string (e.g. a=Hello%20World&b=123)
480
512
  """
481
- new_params = []
513
+ new_params: List[Tuple[str, str]] = []
482
514
  if collection_formats is None:
483
515
  collection_formats = {}
484
516
  for k, v in params.items() if isinstance(params, dict) else params:
@@ -492,7 +524,7 @@ class ApiClient:
492
524
  if k in collection_formats:
493
525
  collection_format = collection_formats[k]
494
526
  if collection_format == 'multi':
495
- new_params.extend((k, value) for value in v)
527
+ new_params.extend((k, quote(str(value))) for value in v)
496
528
  else:
497
529
  if collection_format == 'ssv':
498
530
  delimiter = ' '
@@ -508,33 +540,41 @@ class ApiClient:
508
540
  else:
509
541
  new_params.append((k, quote(str(v))))
510
542
 
511
- return "&".join(["=".join(item) for item in new_params])
543
+ return "&".join(["=".join(map(str, item)) for item in new_params])
512
544
 
513
- def files_parameters(self, files=None):
545
+ def files_parameters(
546
+ self,
547
+ files: Dict[str, Union[str, bytes, List[str], List[bytes], Tuple[str, bytes]]],
548
+ ):
514
549
  """Builds form parameters.
515
550
 
516
551
  :param files: File parameters.
517
552
  :return: Form parameters with files.
518
553
  """
519
554
  params = []
520
-
521
- if files:
522
- for k, v in files.items():
523
- if not v:
524
- continue
525
- file_names = v if type(v) is list else [v]
526
- for n in file_names:
527
- with open(n, 'rb') as f:
528
- filename = os.path.basename(f.name)
529
- filedata = f.read()
530
- mimetype = (
531
- mimetypes.guess_type(filename)[0]
532
- or 'application/octet-stream'
533
- )
534
- params.append(
535
- tuple([k, tuple([filename, filedata, mimetype])])
536
- )
537
-
555
+ for k, v in files.items():
556
+ if isinstance(v, str):
557
+ with open(v, 'rb') as f:
558
+ filename = os.path.basename(f.name)
559
+ filedata = f.read()
560
+ elif isinstance(v, bytes):
561
+ filename = k
562
+ filedata = v
563
+ elif isinstance(v, tuple):
564
+ filename, filedata = v
565
+ elif isinstance(v, list):
566
+ for file_param in v:
567
+ params.extend(self.files_parameters({k: file_param}))
568
+ continue
569
+ else:
570
+ raise ValueError("Unsupported file value")
571
+ mimetype = (
572
+ mimetypes.guess_type(filename)[0]
573
+ or 'application/octet-stream'
574
+ )
575
+ params.append(
576
+ tuple([k, tuple([filename, filedata, mimetype])])
577
+ )
538
578
  return params
539
579
 
540
580
  def select_header_accept(self, accepts: List[str]) -> Optional[str]:
@@ -663,10 +703,12 @@ class ApiClient:
663
703
 
664
704
  content_disposition = response.getheader("Content-Disposition")
665
705
  if content_disposition:
666
- filename = re.search(
706
+ m = re.search(
667
707
  r'filename=[\'"]?([^\'"\s]+)[\'"]?',
668
708
  content_disposition
669
- ).group(1)
709
+ )
710
+ assert m is not None, "Unexpected 'content-disposition' header value"
711
+ filename = m.group(1)
670
712
  path = os.path.join(os.path.dirname(path), filename)
671
713
 
672
714
  with open(path, "wb") as f:
@@ -733,6 +775,24 @@ class ApiClient:
733
775
  )
734
776
  )
735
777
 
778
+ def __deserialize_enum(self, data, klass):
779
+ """Deserializes primitive type to enum.
780
+
781
+ :param data: primitive type.
782
+ :param klass: class literal.
783
+ :return: enum value.
784
+ """
785
+ try:
786
+ return klass(data)
787
+ except ValueError:
788
+ raise rest.ApiException(
789
+ status=0,
790
+ reason=(
791
+ "Failed to parse `{0}` as `{1}`"
792
+ .format(data, klass)
793
+ )
794
+ )
795
+
736
796
  def __deserialize_model(self, data, klass):
737
797
  """Deserializes list or dict to model.
738
798
 
@@ -1,8 +1,8 @@
1
1
  """API response object."""
2
2
 
3
3
  from __future__ import annotations
4
- from typing import Any, Dict, Optional, Generic, TypeVar
5
- from pydantic import Field, StrictInt, StrictStr, StrictBytes, BaseModel
4
+ from typing import Optional, Generic, Mapping, TypeVar
5
+ from pydantic import Field, StrictInt, StrictBytes, BaseModel
6
6
 
7
7
  T = TypeVar("T")
8
8
 
@@ -12,7 +12,7 @@ class ApiResponse(BaseModel, Generic[T]):
12
12
  """
13
13
 
14
14
  status_code: StrictInt = Field(description="HTTP status code")
15
- headers: Optional[Dict[StrictStr, StrictStr]] = Field(None, description="HTTP headers")
15
+ headers: Optional[Mapping[str, str]] = Field(None, description="HTTP headers")
16
16
  data: T = Field(description="Deserialized data given the data type")
17
17
  raw_data: StrictBytes = Field(description="Raw data (HTTP response body)")
18
18