gamsapi 52.2.0__cp314-cp314-win_amd64.whl → 52.4.0__cp314-cp314-win_amd64.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.
Files changed (294) hide show
  1. gams/__init__.py +2 -2
  2. gams/_version.py +1 -1
  3. gams/connect/__init__.py +2 -2
  4. gams/connect/agents/__init__.py +2 -2
  5. gams/connect/agents/_excel/__init__.py +2 -2
  6. gams/connect/agents/_excel/excelagent.py +2 -2
  7. gams/connect/agents/_excel/workbook.py +2 -2
  8. gams/connect/agents/_sqlconnectors/__init__.py +2 -2
  9. gams/connect/agents/_sqlconnectors/_accesshandler.py +2 -2
  10. gams/connect/agents/_sqlconnectors/_databasehandler.py +2 -2
  11. gams/connect/agents/_sqlconnectors/_mysqlhandler.py +2 -2
  12. gams/connect/agents/_sqlconnectors/_postgreshandler.py +2 -2
  13. gams/connect/agents/_sqlconnectors/_pyodbchandler.py +2 -2
  14. gams/connect/agents/_sqlconnectors/_sqlalchemyhandler.py +2 -2
  15. gams/connect/agents/_sqlconnectors/_sqlitehandler.py +2 -2
  16. gams/connect/agents/_sqlconnectors/_sqlserverhandler.py +2 -2
  17. gams/connect/agents/concatenate.py +2 -2
  18. gams/connect/agents/connectagent.py +2 -2
  19. gams/connect/agents/csvreader.py +2 -2
  20. gams/connect/agents/csvwriter.py +2 -2
  21. gams/connect/agents/domainwriter.py +2 -2
  22. gams/connect/agents/excelreader.py +2 -2
  23. gams/connect/agents/excelwriter.py +2 -2
  24. gams/connect/agents/filter.py +2 -2
  25. gams/connect/agents/gamsreader.py +2 -2
  26. gams/connect/agents/gamswriter.py +2 -2
  27. gams/connect/agents/gdxreader.py +2 -2
  28. gams/connect/agents/gdxwriter.py +2 -2
  29. gams/connect/agents/labelmanipulator.py +2 -2
  30. gams/connect/agents/projection.py +2 -2
  31. gams/connect/agents/pythoncode.py +2 -2
  32. gams/connect/agents/rawcsvreader.py +2 -2
  33. gams/connect/agents/rawexcelreader.py +2 -2
  34. gams/connect/agents/sqlreader.py +2 -2
  35. gams/connect/agents/sqlwriter.py +2 -2
  36. gams/connect/connectdatabase.py +2 -2
  37. gams/connect/connectvalidator.py +2 -2
  38. gams/connect/errors.py +2 -2
  39. gams/control/__init__.py +2 -2
  40. gams/control/database.py +2 -2
  41. gams/control/execution.py +2 -2
  42. gams/control/options.py +2 -2
  43. gams/control/workspace.py +2 -2
  44. gams/core/__init__.py +2 -2
  45. gams/core/cfg/__init__.py +2 -2
  46. gams/core/cfg/_cfgmcc.cp314-win_amd64.pyd +0 -0
  47. gams/core/dct/__init__.py +2 -2
  48. gams/core/dct/_dctmcc.cp314-win_amd64.pyd +0 -0
  49. gams/core/embedded/__init__.py +2 -2
  50. gams/core/embedded/gamsemb.py +2 -2
  51. gams/core/emp/__init__.py +2 -2
  52. gams/core/emp/emplexer.py +2 -2
  53. gams/core/emp/empyacc.py +2 -2
  54. gams/core/gdx/__init__.py +2 -2
  55. gams/core/gdx/_gdxcc.cp314-win_amd64.pyd +0 -0
  56. gams/core/gev/__init__.py +2 -2
  57. gams/core/gev/_gevmcc.cp314-win_amd64.pyd +0 -0
  58. gams/core/gmd/__init__.py +2 -2
  59. gams/core/gmd/_gmdcc.cp314-win_amd64.pyd +0 -0
  60. gams/core/gmo/__init__.py +2 -2
  61. gams/core/gmo/_gmomcc.cp314-win_amd64.pyd +0 -0
  62. gams/core/idx/__init__.py +2 -2
  63. gams/core/idx/_idxcc.cp314-win_amd64.pyd +0 -0
  64. gams/core/numpy/__init__.py +2 -2
  65. gams/core/numpy/_gams2numpy.cp314-win_amd64.pyd +0 -0
  66. gams/core/numpy/gams2numpy.py +2 -2
  67. gams/core/opt/__init__.py +2 -2
  68. gams/core/opt/_optcc.cp314-win_amd64.pyd +0 -0
  69. gams/engine/__init__.py +193 -16
  70. gams/engine/api/__init__.py +13 -3
  71. gams/engine/api/auth_api.py +7545 -3618
  72. gams/engine/api/cleanup_api.py +712 -320
  73. gams/engine/api/default_api.py +838 -369
  74. gams/engine/api/hypercube_api.py +2576 -1198
  75. gams/engine/api/jobs_api.py +5170 -2458
  76. gams/engine/api/licenses_api.py +2170 -1014
  77. gams/engine/api/namespaces_api.py +7663 -3557
  78. gams/engine/api/usage_api.py +5575 -1867
  79. gams/engine/api/users_api.py +5880 -2382
  80. gams/engine/api_client.py +579 -641
  81. gams/engine/api_response.py +21 -0
  82. gams/engine/configuration.py +233 -102
  83. gams/engine/exceptions.py +86 -29
  84. gams/engine/models/__init__.py +83 -68
  85. gams/engine/models/bad_input.py +89 -0
  86. gams/engine/models/cleanable_job_result.py +104 -0
  87. gams/engine/models/cleanable_job_result_page.py +113 -0
  88. gams/engine/models/engine_license.py +107 -0
  89. gams/engine/models/files_not_found.py +93 -0
  90. gams/engine/models/forwarded_token_response.py +112 -0
  91. gams/engine/models/generic_key_value_pair.py +89 -0
  92. gams/engine/models/hypercube.py +160 -0
  93. gams/engine/models/hypercube_page.py +111 -0
  94. gams/engine/models/hypercube_summary.py +91 -0
  95. gams/engine/models/hypercube_token.py +97 -0
  96. gams/engine/models/identity_provider.py +107 -0
  97. gams/engine/models/identity_provider_ldap.py +121 -0
  98. gams/engine/models/identity_provider_oauth2.py +146 -0
  99. gams/engine/models/identity_provider_oauth2_scope.py +89 -0
  100. gams/engine/models/identity_provider_oauth2_with_secret.py +152 -0
  101. gams/engine/models/identity_provider_oidc.py +133 -0
  102. gams/engine/models/identity_provider_oidc_with_secret.py +143 -0
  103. gams/engine/models/inex.py +91 -0
  104. gams/engine/models/invitation.py +136 -0
  105. gams/engine/models/invitation_quota.py +106 -0
  106. gams/engine/models/invitation_token.py +87 -0
  107. gams/engine/models/job.py +165 -0
  108. gams/engine/models/job_no_text_entry.py +138 -0
  109. gams/engine/models/job_no_text_entry_page.py +111 -0
  110. gams/engine/models/license.py +91 -0
  111. gams/engine/models/log_piece.py +96 -0
  112. gams/engine/models/message.py +87 -0
  113. gams/engine/models/message_and_token.py +99 -0
  114. gams/engine/models/message_with_webhook_id.py +89 -0
  115. gams/engine/models/model_auth_token.py +87 -0
  116. gams/engine/models/model_configuration.py +125 -0
  117. gams/engine/models/model_default_instance.py +99 -0
  118. gams/engine/models/model_default_user_instance.py +98 -0
  119. gams/engine/models/model_hypercube_job.py +106 -0
  120. gams/engine/models/model_hypercube_usage.py +130 -0
  121. gams/engine/models/model_instance_info.py +116 -0
  122. gams/engine/models/model_instance_info_full.py +123 -0
  123. gams/engine/models/model_instance_pool_info.py +112 -0
  124. gams/engine/models/model_job_labels.py +179 -0
  125. gams/engine/models/model_job_usage.py +133 -0
  126. gams/engine/models/model_pool_usage.py +124 -0
  127. gams/engine/models/model_usage.py +115 -0
  128. gams/engine/models/model_user.py +96 -0
  129. gams/engine/models/model_userinstance_info.py +119 -0
  130. gams/engine/models/model_userinstancepool_info.py +95 -0
  131. gams/engine/models/model_version.py +91 -0
  132. gams/engine/models/models.py +120 -0
  133. gams/engine/models/namespace.py +104 -0
  134. gams/engine/models/namespace_quota.py +96 -0
  135. gams/engine/models/namespace_with_permission.py +96 -0
  136. gams/engine/models/not_found.py +91 -0
  137. gams/engine/models/password_policy.py +97 -0
  138. gams/engine/models/perm_and_username.py +89 -0
  139. gams/engine/models/quota.py +117 -0
  140. gams/engine/models/quota_exceeded.py +97 -0
  141. gams/engine/models/status_code_meaning.py +89 -0
  142. gams/engine/models/stream_entry.py +89 -0
  143. gams/engine/models/system_wide_license.py +92 -0
  144. gams/engine/models/text_entries.py +87 -0
  145. gams/engine/models/text_entry.py +101 -0
  146. gams/engine/models/time_span.py +95 -0
  147. gams/engine/models/time_span_pool_worker.py +99 -0
  148. gams/engine/models/token_forward_error.py +87 -0
  149. gams/engine/models/user.py +127 -0
  150. gams/engine/models/user_group_member.py +96 -0
  151. gams/engine/models/user_groups.py +108 -0
  152. gams/engine/models/vapid_info.py +87 -0
  153. gams/engine/models/webhook.py +138 -0
  154. gams/engine/models/webhook_parameterized_event.py +99 -0
  155. gams/engine/py.typed +0 -0
  156. gams/engine/rest.py +141 -229
  157. gams/magic/__init__.py +2 -2
  158. gams/magic/gams_magic.py +2 -2
  159. gams/magic/interactive.py +2 -2
  160. gams/tools/__init__.py +2 -2
  161. gams/tools/errors.py +2 -2
  162. gams/tools/toolcollection/__init__.py +2 -2
  163. gams/tools/toolcollection/alg/__init__.py +2 -2
  164. gams/tools/toolcollection/alg/rank.py +2 -2
  165. gams/tools/toolcollection/data/__init__.py +2 -2
  166. gams/tools/toolcollection/data/csvread.py +2 -2
  167. gams/tools/toolcollection/data/exceldump.py +2 -2
  168. gams/tools/toolcollection/data/sqlitewrite.py +2 -2
  169. gams/tools/toolcollection/gdxservice/__init__.py +2 -2
  170. gams/tools/toolcollection/gdxservice/gdxencoding.py +2 -2
  171. gams/tools/toolcollection/gdxservice/gdxrename.py +2 -2
  172. gams/tools/toolcollection/linalg/__init__.py +2 -2
  173. gams/tools/toolcollection/linalg/cholesky.py +2 -2
  174. gams/tools/toolcollection/linalg/eigenvalue.py +2 -2
  175. gams/tools/toolcollection/linalg/eigenvector.py +2 -2
  176. gams/tools/toolcollection/linalg/invert.py +2 -2
  177. gams/tools/toolcollection/linalg/ols.py +2 -2
  178. gams/tools/toolcollection/tooltemplate.py +2 -2
  179. gams/tools/toolcollection/win32/__init__.py +2 -2
  180. gams/tools/toolcollection/win32/excelmerge.py +2 -2
  181. gams/tools/toolcollection/win32/exceltalk.py +2 -2
  182. gams/tools/toolcollection/win32/msappavail.py +2 -2
  183. gams/tools/toolcollection/win32/shellexecute.py +2 -2
  184. gams/tools/tools.py +2 -2
  185. gams/transfer/__init__.py +2 -2
  186. gams/transfer/_abcs/__init__.py +2 -2
  187. gams/transfer/_abcs/container_abcs.py +2 -2
  188. gams/transfer/_internals/__init__.py +2 -2
  189. gams/transfer/_internals/algorithms.py +2 -2
  190. gams/transfer/_internals/casepreservingdict.py +2 -2
  191. gams/transfer/_internals/constants.py +2 -2
  192. gams/transfer/_internals/domainviolation.py +2 -2
  193. gams/transfer/_internals/specialvalues.py +2 -2
  194. gams/transfer/containers/__init__.py +2 -2
  195. gams/transfer/containers/_container.py +2 -2
  196. gams/transfer/containers/_io/__init__.py +2 -2
  197. gams/transfer/containers/_io/containers.py +2 -2
  198. gams/transfer/containers/_io/gdx.py +2 -2
  199. gams/transfer/containers/_io/gmd.py +2 -2
  200. gams/transfer/containers/_mixins/__init__.py +2 -2
  201. gams/transfer/containers/_mixins/ccc.py +2 -2
  202. gams/transfer/syms/__init__.py +2 -2
  203. gams/transfer/syms/_methods/__init__.py +2 -2
  204. gams/transfer/syms/_methods/tables.py +2 -2
  205. gams/transfer/syms/_methods/toDict.py +2 -2
  206. gams/transfer/syms/_methods/toList.py +2 -2
  207. gams/transfer/syms/_methods/toValue.py +2 -2
  208. gams/transfer/syms/_mixins/__init__.py +2 -2
  209. gams/transfer/syms/_mixins/equals.py +2 -2
  210. gams/transfer/syms/_mixins/generateRecords.py +2 -2
  211. gams/transfer/syms/_mixins/pivot.py +2 -2
  212. gams/transfer/syms/_mixins/pve.py +2 -2
  213. gams/transfer/syms/_mixins/sa.py +2 -2
  214. gams/transfer/syms/_mixins/sapve.py +2 -2
  215. gams/transfer/syms/_mixins/saua.py +2 -2
  216. gams/transfer/syms/_mixins/sauapve.py +2 -2
  217. gams/transfer/syms/_mixins/spve.py +2 -2
  218. gams/transfer/syms/_mixins/ve.py +2 -2
  219. gams/transfer/syms/container_syms/__init__.py +2 -2
  220. gams/transfer/syms/container_syms/_alias.py +2 -2
  221. gams/transfer/syms/container_syms/_equation.py +2 -2
  222. gams/transfer/syms/container_syms/_parameter.py +2 -2
  223. gams/transfer/syms/container_syms/_set.py +2 -2
  224. gams/transfer/syms/container_syms/_universe_alias.py +2 -2
  225. gams/transfer/syms/container_syms/_variable.py +2 -2
  226. {gamsapi-52.2.0.dist-info → gamsapi-52.4.0.dist-info}/METADATA +12 -10
  227. gamsapi-52.4.0.dist-info/RECORD +257 -0
  228. {gamsapi-52.2.0.dist-info → gamsapi-52.4.0.dist-info}/licenses/LICENSE +2 -2
  229. gams/engine/apis/__init__.py +0 -25
  230. gams/engine/model/__init__.py +0 -5
  231. gams/engine/model/bad_input.py +0 -259
  232. gams/engine/model/cleanable_job_result.py +0 -285
  233. gams/engine/model/cleanable_job_result_page.py +0 -277
  234. gams/engine/model/engine_license.py +0 -263
  235. gams/engine/model/files_not_found.py +0 -267
  236. gams/engine/model/forwarded_token_response.py +0 -275
  237. gams/engine/model/generic_key_value_pair.py +0 -259
  238. gams/engine/model/hypercube.py +0 -331
  239. gams/engine/model/hypercube_page.py +0 -273
  240. gams/engine/model/hypercube_summary.py +0 -263
  241. gams/engine/model/hypercube_token.py +0 -265
  242. gams/engine/model/identity_provider.py +0 -287
  243. gams/engine/model/identity_provider_ldap.py +0 -303
  244. gams/engine/model/identity_provider_oauth2.py +0 -309
  245. gams/engine/model/identity_provider_oauth2_scope.py +0 -259
  246. gams/engine/model/identity_provider_oauth2_with_secret.py +0 -321
  247. gams/engine/model/identity_provider_oidc.py +0 -299
  248. gams/engine/model/identity_provider_oidc_with_secret.py +0 -319
  249. gams/engine/model/inex.py +0 -259
  250. gams/engine/model/invitation.py +0 -309
  251. gams/engine/model/invitation_quota.py +0 -263
  252. gams/engine/model/invitation_token.py +0 -255
  253. gams/engine/model/job.py +0 -337
  254. gams/engine/model/job_no_text_entry.py +0 -313
  255. gams/engine/model/job_no_text_entry_page.py +0 -273
  256. gams/engine/model/license.py +0 -263
  257. gams/engine/model/log_piece.py +0 -263
  258. gams/engine/model/message.py +0 -255
  259. gams/engine/model/message_and_token.py +0 -269
  260. gams/engine/model/model_auth_token.py +0 -255
  261. gams/engine/model/model_configuration.py +0 -268
  262. gams/engine/model/model_hypercube_job.py +0 -273
  263. gams/engine/model/model_hypercube_usage.py +0 -303
  264. gams/engine/model/model_instance_info.py +0 -285
  265. gams/engine/model/model_instance_info_full.py +0 -289
  266. gams/engine/model/model_job_labels.py +0 -295
  267. gams/engine/model/model_job_usage.py +0 -299
  268. gams/engine/model/model_usage.py +0 -267
  269. gams/engine/model/model_userinstance_info.py +0 -273
  270. gams/engine/model/model_version.py +0 -263
  271. gams/engine/model/models.py +0 -297
  272. gams/engine/model/namespace.py +0 -269
  273. gams/engine/model/namespace_quota.py +0 -263
  274. gams/engine/model/namespace_with_permission.py +0 -263
  275. gams/engine/model/not_found.py +0 -263
  276. gams/engine/model/perm_and_username.py +0 -259
  277. gams/engine/model/quota.py +0 -275
  278. gams/engine/model/quota_exceeded.py +0 -265
  279. gams/engine/model/result_user.py +0 -263
  280. gams/engine/model/status_code_meaning.py +0 -259
  281. gams/engine/model/stream_entry.py +0 -259
  282. gams/engine/model/system_wide_license.py +0 -255
  283. gams/engine/model/text_entries.py +0 -255
  284. gams/engine/model/text_entry.py +0 -263
  285. gams/engine/model/time_span.py +0 -259
  286. gams/engine/model/token_forward_error.py +0 -255
  287. gams/engine/model/user.py +0 -283
  288. gams/engine/model/user_group_member.py +0 -269
  289. gams/engine/model/user_groups.py +0 -279
  290. gams/engine/model/webhook.py +0 -292
  291. gams/engine/model_utils.py +0 -2037
  292. gamsapi-52.2.0.dist-info/RECORD +0 -248
  293. {gamsapi-52.2.0.dist-info → gamsapi-52.4.0.dist-info}/WHEEL +0 -0
  294. {gamsapi-52.2.0.dist-info → gamsapi-52.4.0.dist-info}/top_level.txt +0 -0
gams/engine/api_client.py CHANGED
@@ -1,45 +1,49 @@
1
+ # coding: utf-8
2
+
1
3
  """
2
4
  GAMS Engine
3
5
 
4
- With GAMS Engine you can register and solve GAMS models. It has a namespace management system, so you can restrict your users to certain models. # noqa: E501
6
+ With GAMS Engine you can register and solve GAMS models. It has a namespace management system, so you can restrict your users to certain models.
5
7
 
6
8
  The version of the OpenAPI document: latest
7
- Generated by: https://openapi-generator.tech
8
- """
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
9
13
 
10
14
 
15
+ import datetime
16
+ from dateutil.parser import parse
17
+ from enum import Enum
18
+ import decimal
11
19
  import json
12
- import atexit
13
20
  import mimetypes
14
- from multiprocessing.pool import ThreadPool
15
- import io
16
21
  import os
17
22
  import re
18
- import typing
19
- from urllib.parse import quote
20
- from urllib3.fields import RequestField
23
+ import tempfile
24
+ import uuid
21
25
 
26
+ from urllib.parse import quote
27
+ from typing import Tuple, Optional, List, Dict, Union
28
+ from pydantic import SecretStr
22
29
 
23
- from gams.engine import rest
24
30
  from gams.engine.configuration import Configuration
25
- from gams.engine.exceptions import ApiTypeError, ApiValueError, ApiException
26
- from gams.engine.model_utils import (
27
- ModelNormal,
28
- ModelSimple,
29
- ModelComposed,
30
- check_allowed_values,
31
- check_validations,
32
- date,
33
- datetime,
34
- deserialize_file,
35
- file_type,
36
- model_to_dict,
37
- none_type,
38
- validate_and_convert_types
31
+ from gams.engine.api_response import ApiResponse, T as ApiResponseT
32
+ import gams.engine.models
33
+ from gams.engine import rest
34
+ from gams.engine.exceptions import (
35
+ ApiValueError,
36
+ ApiException,
37
+ BadRequestException,
38
+ UnauthorizedException,
39
+ ForbiddenException,
40
+ NotFoundException,
41
+ ServiceException
39
42
  )
40
43
 
44
+ RequestSerialized = Tuple[str, str, Dict[str, str], Optional[str], List[str]]
41
45
 
42
- class ApiClient(object):
46
+ class ApiClient:
43
47
  """Generic API client for OpenAPI client library builds.
44
48
 
45
49
  OpenAPI generic API client. This client handles the client-
@@ -47,28 +51,39 @@ class ApiClient(object):
47
51
  the methods and models for each application are generated from the OpenAPI
48
52
  templates.
49
53
 
50
- NOTE: This class is auto generated by OpenAPI Generator.
51
- Ref: https://openapi-generator.tech
52
- Do not edit the class manually.
53
-
54
54
  :param configuration: .Configuration object for this client
55
55
  :param header_name: a header to pass when making calls to the API.
56
56
  :param header_value: a header value to pass when making calls to
57
57
  the API.
58
58
  :param cookie: a cookie to include in the header when making calls
59
59
  to the API
60
- :param pool_threads: The number of threads to use for async requests
61
- to the API. More threads means more concurrent API requests.
62
60
  """
63
61
 
62
+ PRIMITIVE_TYPES = (float, bool, bytes, str, int)
63
+ NATIVE_TYPES_MAPPING = {
64
+ 'int': int,
65
+ 'long': int, # TODO remove as only py3 is supported?
66
+ 'float': float,
67
+ 'str': str,
68
+ 'bool': bool,
69
+ 'date': datetime.date,
70
+ 'datetime': datetime.datetime,
71
+ 'decimal': decimal.Decimal,
72
+ 'object': object,
73
+ }
64
74
  _pool = None
65
75
 
66
- def __init__(self, configuration=None, header_name=None, header_value=None,
67
- cookie=None, pool_threads=1):
76
+ def __init__(
77
+ self,
78
+ configuration=None,
79
+ header_name=None,
80
+ header_value=None,
81
+ cookie=None
82
+ ) -> None:
83
+ # use default configuration if none is provided
68
84
  if configuration is None:
69
- configuration = Configuration.get_default_copy()
85
+ configuration = Configuration.get_default()
70
86
  self.configuration = configuration
71
- self.pool_threads = pool_threads
72
87
 
73
88
  self.rest_client = rest.RESTClientObject(configuration)
74
89
  self.default_headers = {}
@@ -76,31 +91,14 @@ class ApiClient(object):
76
91
  self.default_headers[header_name] = header_value
77
92
  self.cookie = cookie
78
93
  # Set default User-Agent.
79
- self.user_agent = 'OpenAPI-Generator/23.03.31/python'
94
+ self.user_agent = 'OpenAPI-Generator/25.11.13/python'
95
+ self.client_side_validation = configuration.client_side_validation
80
96
 
81
97
  def __enter__(self):
82
98
  return self
83
99
 
84
100
  def __exit__(self, exc_type, exc_value, traceback):
85
- self.close()
86
-
87
- def close(self):
88
- if self._pool:
89
- self._pool.close()
90
- self._pool.join()
91
- self._pool = None
92
- if hasattr(atexit, 'unregister'):
93
- atexit.unregister(self.close)
94
-
95
- @property
96
- def pool(self):
97
- """Create thread pool on first request
98
- avoids instantiating unused threadpool for blocking clients.
99
- """
100
- if self._pool is None:
101
- atexit.register(self.close)
102
- self._pool = ThreadPool(self.pool_threads)
103
- return self._pool
101
+ pass
104
102
 
105
103
  @property
106
104
  def user_agent(self):
@@ -114,26 +112,69 @@ class ApiClient(object):
114
112
  def set_default_header(self, header_name, header_value):
115
113
  self.default_headers[header_name] = header_value
116
114
 
117
- def __call_api(
115
+
116
+ _default = None
117
+
118
+ @classmethod
119
+ def get_default(cls):
120
+ """Return new instance of ApiClient.
121
+
122
+ This method returns newly created, based on default constructor,
123
+ object of ApiClient class or returns a copy of default
124
+ ApiClient.
125
+
126
+ :return: The ApiClient object.
127
+ """
128
+ if cls._default is None:
129
+ cls._default = ApiClient()
130
+ return cls._default
131
+
132
+ @classmethod
133
+ def set_default(cls, default):
134
+ """Set default instance of ApiClient.
135
+
136
+ It stores default ApiClient.
137
+
138
+ :param default: object of ApiClient.
139
+ """
140
+ cls._default = default
141
+
142
+ def param_serialize(
118
143
  self,
119
- resource_path: str,
120
- method: str,
121
- path_params: typing.Optional[typing.Dict[str, typing.Any]] = None,
122
- query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None,
123
- header_params: typing.Optional[typing.Dict[str, typing.Any]] = None,
124
- body: typing.Optional[typing.Any] = None,
125
- post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None,
126
- files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None,
127
- response_type: typing.Optional[typing.Tuple[typing.Any]] = None,
128
- auth_settings: typing.Optional[typing.List[str]] = None,
129
- _return_http_data_only: typing.Optional[bool] = None,
130
- collection_formats: typing.Optional[typing.Dict[str, str]] = None,
131
- _preload_content: bool = True,
132
- _request_timeout: typing.Optional[typing.Union[int, float, typing.Tuple]] = None,
133
- _host: typing.Optional[str] = None,
134
- _check_type: typing.Optional[bool] = None,
135
- _content_type: typing.Optional[str] = None
136
- ):
144
+ method,
145
+ resource_path,
146
+ path_params=None,
147
+ query_params=None,
148
+ header_params=None,
149
+ body=None,
150
+ post_params=None,
151
+ files=None, auth_settings=None,
152
+ collection_formats=None,
153
+ _host=None,
154
+ _request_auth=None
155
+ ) -> RequestSerialized:
156
+
157
+ """Builds the HTTP request params needed by the request.
158
+ :param method: Method to call.
159
+ :param resource_path: Path to method endpoint.
160
+ :param path_params: Path parameters in the url.
161
+ :param query_params: Query parameters in the url.
162
+ :param header_params: Header parameters to be
163
+ placed in the request header.
164
+ :param body: Request body.
165
+ :param post_params dict: Request post form parameters,
166
+ for `application/x-www-form-urlencoded`, `multipart/form-data`.
167
+ :param auth_settings list: Auth Settings names for the request.
168
+ :param files dict: key -> filename, value -> filepath,
169
+ for `multipart/form-data`.
170
+ :param collection_formats: dict of collection formats for path, query,
171
+ header, and post parameters.
172
+ :param _request_auth: set to override the auth_settings for an a single
173
+ request; this effectively ignores the authentication
174
+ in the spec for a single request.
175
+ :return: tuple of form (path, http_method, query_params, header_params,
176
+ body, post_params, files)
177
+ """
137
178
 
138
179
  config = self.configuration
139
180
 
@@ -144,14 +185,17 @@ class ApiClient(object):
144
185
  header_params['Cookie'] = self.cookie
145
186
  if header_params:
146
187
  header_params = self.sanitize_for_serialization(header_params)
147
- header_params = dict(self.parameters_to_tuples(header_params,
148
- collection_formats))
188
+ header_params = dict(
189
+ self.parameters_to_tuples(header_params,collection_formats)
190
+ )
149
191
 
150
192
  # path parameters
151
193
  if path_params:
152
194
  path_params = self.sanitize_for_serialization(path_params)
153
- path_params = self.parameters_to_tuples(path_params,
154
- collection_formats)
195
+ path_params = self.parameters_to_tuples(
196
+ path_params,
197
+ collection_formats
198
+ )
155
199
  for k, v in path_params:
156
200
  # specified safe chars, encode everything
157
201
  resource_path = resource_path.replace(
@@ -159,334 +203,275 @@ class ApiClient(object):
159
203
  quote(str(v), safe=config.safe_chars_for_path_param)
160
204
  )
161
205
 
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
206
  # post parameters
169
207
  if post_params or files:
170
208
  post_params = post_params if post_params else []
171
209
  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) )
210
+ post_params = self.parameters_to_tuples(
211
+ post_params,
212
+ collection_formats
213
+ )
214
+ if files:
215
+ post_params.extend(self.files_parameters(files))
216
+
217
+ # auth setting
218
+ self.update_params_for_auth(
219
+ header_params,
220
+ query_params,
221
+ auth_settings,
222
+ resource_path,
223
+ method,
224
+ body,
225
+ request_auth=_request_auth
226
+ )
178
227
 
179
228
  # body
180
229
  if body:
181
230
  body = self.sanitize_for_serialization(body)
182
231
 
183
- # auth setting
184
- self.update_params_for_auth(header_params, query_params,
185
- auth_settings, resource_path, method, body)
186
-
187
232
  # request url
188
- if _host is None:
233
+ if _host is None or self.configuration.ignore_operation_servers:
189
234
  url = self.configuration.host + resource_path
190
235
  else:
191
236
  # use server/host defined in path or operation instead
192
237
  url = _host + resource_path
193
238
 
239
+ # query parameters
240
+ if query_params:
241
+ query_params = self.sanitize_for_serialization(query_params)
242
+ url_query = self.parameters_to_url_query(
243
+ query_params,
244
+ collection_formats
245
+ )
246
+ url += "?" + url_query
247
+
248
+ return method, url, header_params, body, post_params
249
+
250
+
251
+ def call_api(
252
+ self,
253
+ method,
254
+ url,
255
+ header_params=None,
256
+ body=None,
257
+ post_params=None,
258
+ _request_timeout=None
259
+ ) -> rest.RESTResponse:
260
+ """Makes the HTTP request (synchronous)
261
+ :param method: Method to call.
262
+ :param url: Path to method endpoint.
263
+ :param header_params: Header parameters to be
264
+ placed in the request header.
265
+ :param body: Request body.
266
+ :param post_params dict: Request post form parameters,
267
+ for `application/x-www-form-urlencoded`, `multipart/form-data`.
268
+ :param _request_timeout: timeout setting for this request.
269
+ :return: RESTResponse
270
+ """
271
+
194
272
  try:
195
273
  # 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)
274
+ response_data = self.rest_client.request(
275
+ method, url,
276
+ headers=header_params,
277
+ body=body, post_params=post_params,
278
+ _request_timeout=_request_timeout
279
+ )
280
+
201
281
  except ApiException as e:
202
- e.body = e.body.decode('utf-8')
203
282
  raise e
204
283
 
205
- self.last_response = response_data
284
+ return response_data
285
+
286
+ def response_deserialize(
287
+ self,
288
+ response_data: rest.RESTResponse,
289
+ response_types_map: Optional[Dict[str, ApiResponseT]]=None
290
+ ) -> ApiResponse[ApiResponseT]:
291
+ """Deserializes response into an object.
292
+ :param response_data: RESTResponse object to be deserialized.
293
+ :param response_types_map: dict of response types.
294
+ :return: ApiResponse
295
+ """
206
296
 
207
- return_data = response_data
297
+ msg = "RESTResponse.read() must be called before passing it to response_deserialize()"
298
+ assert response_data.data is not None, msg
208
299
 
209
- if not _preload_content:
210
- return (return_data)
211
- return return_data
300
+ response_type = response_types_map.get(str(response_data.status), None)
301
+ if not response_type and isinstance(response_data.status, int) and 100 <= response_data.status <= 599:
302
+ # if not found, look for '1XX', '2XX', etc.
303
+ response_type = response_types_map.get(str(response_data.status)[0] + "XX", None)
212
304
 
213
305
  # deserialize response data
214
- if response_type:
215
- if response_type != (file_type,):
216
- encoding = "utf-8"
306
+ response_text = None
307
+ return_data = None
308
+ try:
309
+ if response_type == "bytearray":
310
+ return_data = response_data.data
311
+ elif response_type == "file":
312
+ return_data = self.__deserialize_file(response_data)
313
+ elif response_type is not None:
314
+ match = None
217
315
  content_type = response_data.getheader('content-type')
218
316
  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())
317
+ match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type)
318
+ encoding = match.group(1) if match else "utf-8"
319
+ response_text = response_data.data.decode(encoding)
320
+ return_data = self.deserialize(response_text, response_type, content_type)
321
+ finally:
322
+ if not 200 <= response_data.status <= 299:
323
+ raise ApiException.from_response(
324
+ http_resp=response_data,
325
+ body=response_text,
326
+ data=return_data,
327
+ )
237
328
 
238
- def parameters_to_multipart(self, params, collection_types):
239
- """Get parameters as list of tuples, formatting as json if value is collection_types
329
+ return ApiResponse(
330
+ status_code = response_data.status,
331
+ data = return_data,
332
+ headers = response_data.getheaders(),
333
+ raw_data = response_data.data
334
+ )
240
335
 
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
336
+ def sanitize_for_serialization(self, obj):
337
+ """Builds a JSON POST object.
257
338
 
258
- @classmethod
259
- def sanitize_for_serialization(cls, obj):
260
- """Prepares data for transmission before it is sent with the rest client
261
339
  If obj is None, return None.
340
+ If obj is SecretStr, return obj.get_secret_value()
262
341
  If obj is str, int, long, float, bool, return directly.
263
342
  If obj is datetime.datetime, datetime.date
264
343
  convert to string in iso8601 format.
344
+ If obj is decimal.Decimal return string representation.
265
345
  If obj is list, sanitize each element in the list.
266
346
  If obj is dict, return the dict.
267
347
  If obj is OpenAPI model, return the properties dict.
268
- If obj is io.IOBase, return the bytes
348
+
269
349
  :param obj: The data to serialize.
270
350
  :return: The serialized form of data.
271
351
  """
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)):
352
+ if obj is None:
353
+ return None
354
+ elif isinstance(obj, Enum):
355
+ return obj.value
356
+ elif isinstance(obj, SecretStr):
357
+ return obj.get_secret_value()
358
+ elif isinstance(obj, self.PRIMITIVE_TYPES):
279
359
  return obj
280
- elif isinstance(obj, (datetime, date)):
360
+ elif isinstance(obj, uuid.UUID):
361
+ return str(obj)
362
+ elif isinstance(obj, list):
363
+ return [
364
+ self.sanitize_for_serialization(sub_obj) for sub_obj in obj
365
+ ]
366
+ elif isinstance(obj, tuple):
367
+ return tuple(
368
+ self.sanitize_for_serialization(sub_obj) for sub_obj in obj
369
+ )
370
+ elif isinstance(obj, (datetime.datetime, datetime.date)):
281
371
  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):
372
+ elif isinstance(obj, decimal.Decimal):
373
+ return str(obj)
374
+
375
+ elif isinstance(obj, dict):
376
+ obj_dict = obj
377
+ else:
378
+ # Convert model obj to dict except
379
+ # attributes `openapi_types`, `attribute_map`
380
+ # and attributes which value is not None.
381
+ # Convert attribute name to json key in
382
+ # model definition for request.
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)
391
+
392
+ return {
393
+ key: self.sanitize_for_serialization(val)
394
+ for key, val in obj_dict.items()
395
+ }
396
+
397
+ def deserialize(self, response_text: str, response_type: str, content_type: Optional[str]):
291
398
  """Deserializes response into an object.
292
399
 
293
400
  :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
401
+ :param response_type: class literal for
402
+ deserialized object, or string of class name.
403
+ :param content_type: content type of response.
307
404
 
308
405
  :return: deserialized object.
309
406
  """
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
407
 
317
408
  # 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
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):
420
+ data = response_text
421
+ else:
422
+ raise ApiException(
423
+ status=0,
424
+ reason="Unsupported content type: {0}".format(content_type)
425
+ )
334
426
 
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.
427
+ return self.__deserialize(data, response_type)
356
428
 
357
- To make an async_req request, set the async_req parameter.
429
+ def __deserialize(self, data, klass):
430
+ """Deserializes dict, list, str into an object.
358
431
 
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.
432
+ :param data: dict, list or str.
433
+ :param klass: class literal, or string of class name.
434
+
435
+ :return: object.
407
436
  """
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)
437
+ if data is None:
438
+ return None
439
+
440
+ if isinstance(klass, str):
441
+ if klass.startswith('List['):
442
+ m = re.match(r'List\[(.*)]', klass)
443
+ assert m is not None, "Malformed List type definition"
444
+ sub_kls = m.group(1)
445
+ return [self.__deserialize(sub_data, sub_kls)
446
+ for sub_data in data]
447
+
448
+ if klass.startswith('Dict['):
449
+ m = re.match(r'Dict\[([^,]*), (.*)]', klass)
450
+ assert m is not None, "Malformed Dict type definition"
451
+ sub_kls = m.group(2)
452
+ return {k: self.__deserialize(v, sub_kls)
453
+ for k, v in data.items()}
454
+
455
+ # convert str to class
456
+ if klass in self.NATIVE_TYPES_MAPPING:
457
+ klass = self.NATIVE_TYPES_MAPPING[klass]
458
+ else:
459
+ klass = getattr(gams.engine.models, klass)
460
+
461
+ if klass in self.PRIMITIVE_TYPES:
462
+ return self.__deserialize_primitive(data, klass)
463
+ elif klass is object:
464
+ return self.__deserialize_object(data)
465
+ elif klass is datetime.date:
466
+ return self.__deserialize_date(data)
467
+ elif klass is datetime.datetime:
468
+ return self.__deserialize_datetime(data)
469
+ elif klass is decimal.Decimal:
470
+ return decimal.Decimal(data)
471
+ elif issubclass(klass, Enum):
472
+ return self.__deserialize_enum(data, klass)
485
473
  else:
486
- raise ApiValueError(
487
- "http method must be `GET`, `HEAD`, `OPTIONS`,"
488
- " `POST`, `PATCH`, `PUT` or `DELETE`."
489
- )
474
+ return self.__deserialize_model(data, klass)
490
475
 
491
476
  def parameters_to_tuples(self, params, collection_formats):
492
477
  """Get parameters as list of tuples, formatting collections.
@@ -495,10 +480,10 @@ class ApiClient(object):
495
480
  :param dict collection_formats: Parameter collection formats
496
481
  :return: Parameters as list of tuples, collections formatted
497
482
  """
498
- new_params = []
483
+ new_params: List[Tuple[str, str]] = []
499
484
  if collection_formats is None:
500
485
  collection_formats = {}
501
- for k, v in params.items() if isinstance(params, dict) else params: # noqa: E501
486
+ for k, v in params.items() if isinstance(params, dict) else params:
502
487
  if k in collection_formats:
503
488
  collection_format = collection_formats[k]
504
489
  if collection_format == 'multi':
@@ -518,349 +503,302 @@ class ApiClient(object):
518
503
  new_params.append((k, v))
519
504
  return new_params
520
505
 
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
506
+ def parameters_to_url_query(self, params, collection_formats):
507
+ """Get parameters as list of tuples, formatting collections.
508
+
509
+ :param params: Parameters as dict or list of two-tuples
510
+ :param dict collection_formats: Parameter collection formats
511
+ :return: URL query string (e.g. a=Hello%20World&b=123)
512
+ """
513
+ new_params: List[Tuple[str, str]] = []
514
+ if collection_formats is None:
515
+ collection_formats = {}
516
+ for k, v in params.items() if isinstance(params, dict) else params:
517
+ if isinstance(v, bool):
518
+ v = str(v).lower()
519
+ if isinstance(v, (int, float)):
520
+ v = str(v)
521
+ if isinstance(v, dict):
522
+ v = json.dumps(v)
523
+
524
+ if k in collection_formats:
525
+ collection_format = collection_formats[k]
526
+ if collection_format == 'multi':
527
+ new_params.extend((k, quote(str(value))) for value in v)
528
+ else:
529
+ if collection_format == 'ssv':
530
+ delimiter = ' '
531
+ elif collection_format == 'tsv':
532
+ delimiter = '\t'
533
+ elif collection_format == 'pipes':
534
+ delimiter = '|'
535
+ else: # csv is the default
536
+ delimiter = ','
537
+ new_params.append(
538
+ (k, delimiter.join(quote(str(value)) for value in v))
539
+ )
540
+ else:
541
+ new_params.append((k, quote(str(v))))
526
542
 
527
- def files_parameters(self, files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None):
543
+ return "&".join(["=".join(map(str, item)) for item in new_params])
544
+
545
+ def files_parameters(
546
+ self,
547
+ files: Dict[str, Union[str, bytes, List[str], List[bytes], Tuple[str, bytes]]],
548
+ ):
528
549
  """Builds form parameters.
529
550
 
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
551
+ :param files: File parameters.
552
+ :return: Form parameters with files.
533
553
  """
534
- if files is None:
535
- return []
536
-
537
554
  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
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}))
541
568
  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
-
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
+ )
558
578
  return params
559
579
 
560
- def select_header_accept(self, accepts):
580
+ def select_header_accept(self, accepts: List[str]) -> Optional[str]:
561
581
  """Returns `Accept` based on an array of accepts provided.
562
582
 
563
583
  :param accepts: List of headers.
564
584
  :return: Accept (e.g. application/json).
565
585
  """
566
586
  if not accepts:
567
- return
587
+ return None
568
588
 
569
- accepts = [x.lower() for x in accepts]
589
+ for accept in accepts:
590
+ if re.search('json', accept, re.IGNORECASE):
591
+ return accept
570
592
 
571
- if 'application/json' in accepts:
572
- return 'application/json'
573
- else:
574
- return ', '.join(accepts)
593
+ return accepts[0]
575
594
 
576
- def select_header_content_type(self, content_types, method=None, body=None):
595
+ def select_header_content_type(self, content_types):
577
596
  """Returns `Content-Type` based on an array of content_types provided.
578
597
 
579
598
  :param content_types: List of content-types.
580
- :param method: http method (e.g. POST, PATCH).
581
- :param body: http body to send.
582
599
  :return: Content-Type (e.g. application/json).
583
600
  """
584
601
  if not content_types:
585
- return 'application/json'
586
-
587
- content_types = [x.lower() for x in content_types]
602
+ return None
588
603
 
589
- if (method == 'PATCH' and
590
- 'application/json-patch+json' in content_types and
591
- isinstance(body, list)):
592
- return 'application/json-patch+json'
604
+ for content_type in content_types:
605
+ if re.search('json', content_type, re.IGNORECASE):
606
+ return content_type
593
607
 
594
- if 'application/json' in content_types or '*/*' in content_types:
595
- return 'application/json'
596
- else:
597
- return content_types[0]
608
+ return content_types[0]
598
609
 
599
- def update_params_for_auth(self, headers, queries, auth_settings,
600
- resource_path, method, body):
610
+ def update_params_for_auth(
611
+ self,
612
+ headers,
613
+ queries,
614
+ auth_settings,
615
+ resource_path,
616
+ method,
617
+ body,
618
+ request_auth=None
619
+ ) -> None:
601
620
  """Updates header and query params based on authentication setting.
602
621
 
603
622
  :param headers: Header parameters dict to be updated.
604
623
  :param queries: Query parameters tuple list to be updated.
605
624
  :param auth_settings: Authentication setting identifiers list.
606
- :param resource_path: A string representation of the HTTP request resource path.
607
- :param method: A string representation of the HTTP request method.
608
- :param body: A object representing the body of the HTTP request.
609
- The object type is the return value of _encoder.default().
625
+ :resource_path: A string representation of the HTTP request resource path.
626
+ :method: A string representation of the HTTP request method.
627
+ :body: A object representing the body of the HTTP request.
628
+ The object type is the return value of sanitize_for_serialization().
629
+ :param request_auth: if set, the provided settings will
630
+ override the token in the configuration.
610
631
  """
611
632
  if not auth_settings:
612
633
  return
613
634
 
614
- for auth in auth_settings:
615
- auth_setting = self.configuration.auth_settings().get(auth)
616
- if auth_setting:
617
- if auth_setting['in'] == 'cookie':
618
- headers['Cookie'] = auth_setting['value']
619
- elif auth_setting['in'] == 'header':
620
- if auth_setting['type'] != 'http-signature':
621
- headers[auth_setting['key']] = auth_setting['value']
622
- elif auth_setting['in'] == 'query':
623
- queries.append((auth_setting['key'], auth_setting['value']))
624
- else:
625
- raise ApiValueError(
626
- 'Authentication token must be in `query` or `header`'
635
+ if request_auth:
636
+ self._apply_auth_params(
637
+ headers,
638
+ queries,
639
+ resource_path,
640
+ method,
641
+ body,
642
+ request_auth
643
+ )
644
+ else:
645
+ for auth in auth_settings:
646
+ auth_setting = self.configuration.auth_settings().get(auth)
647
+ if auth_setting:
648
+ self._apply_auth_params(
649
+ headers,
650
+ queries,
651
+ resource_path,
652
+ method,
653
+ body,
654
+ auth_setting
627
655
  )
628
656
 
657
+ def _apply_auth_params(
658
+ self,
659
+ headers,
660
+ queries,
661
+ resource_path,
662
+ method,
663
+ body,
664
+ auth_setting
665
+ ) -> None:
666
+ """Updates the request parameters based on a single auth_setting
629
667
 
630
- class Endpoint(object):
631
- def __init__(self, settings=None, params_map=None, root_map=None,
632
- headers_map=None, api_client=None, callable=None):
633
- """Creates an endpoint
634
-
635
- Args:
636
- settings (dict): see below key value pairs
637
- 'response_type' (tuple/None): response type
638
- 'auth' (list): a list of auth type keys
639
- 'endpoint_path' (str): the endpoint path
640
- 'operation_id' (str): endpoint string identifier
641
- 'http_method' (str): POST/PUT/PATCH/GET etc
642
- 'servers' (list): list of str servers that this endpoint is at
643
- params_map (dict): see below key value pairs
644
- 'all' (list): list of str endpoint parameter names
645
- 'required' (list): list of required parameter names
646
- 'nullable' (list): list of nullable parameter names
647
- 'enum' (list): list of parameters with enum values
648
- 'validation' (list): list of parameters with validations
649
- root_map
650
- 'validations' (dict): the dict mapping endpoint parameter tuple
651
- paths to their validation dictionaries
652
- 'allowed_values' (dict): the dict mapping endpoint parameter
653
- tuple paths to their allowed_values (enum) dictionaries
654
- 'openapi_types' (dict): param_name to openapi type
655
- 'attribute_map' (dict): param_name to camelCase name
656
- 'location_map' (dict): param_name to 'body', 'file', 'form',
657
- 'header', 'path', 'query'
658
- collection_format_map (dict): param_name to `csv` etc.
659
- headers_map (dict): see below key value pairs
660
- 'accept' (list): list of Accept header strings
661
- 'content_type' (list): list of Content-Type header strings
662
- api_client (ApiClient) api client instance
663
- callable (function): the function which is invoked when the
664
- Endpoint is called
668
+ :param headers: Header parameters dict to be updated.
669
+ :param queries: Query parameters tuple list to be updated.
670
+ :resource_path: A string representation of the HTTP request resource path.
671
+ :method: A string representation of the HTTP request method.
672
+ :body: A object representing the body of the HTTP request.
673
+ The object type is the return value of sanitize_for_serialization().
674
+ :param auth_setting: auth settings for the endpoint
665
675
  """
666
- self.settings = settings
667
- self.params_map = params_map
668
- self.params_map['all'].extend([
669
- 'async_req',
670
- '_host_index',
671
- '_preload_content',
672
- '_request_timeout',
673
- '_return_http_data_only',
674
- '_check_input_type',
675
- '_check_return_type',
676
- '_content_type',
677
- '_spec_property_naming'
678
- ])
679
- self.params_map['nullable'].extend(['_request_timeout'])
680
- self.validations = root_map['validations']
681
- self.allowed_values = root_map['allowed_values']
682
- self.openapi_types = root_map['openapi_types']
683
- extra_types = {
684
- 'async_req': (bool,),
685
- '_host_index': (none_type, int),
686
- '_preload_content': (bool,),
687
- '_request_timeout': (none_type, float, (float,), [float], int, (int,), [int]),
688
- '_return_http_data_only': (bool,),
689
- '_check_input_type': (bool,),
690
- '_check_return_type': (bool,),
691
- '_spec_property_naming': (bool,),
692
- '_content_type': (none_type, str)
693
- }
694
- self.openapi_types.update(extra_types)
695
- self.attribute_map = root_map['attribute_map']
696
- self.location_map = root_map['location_map']
697
- self.collection_format_map = root_map['collection_format_map']
698
- self.headers_map = headers_map
699
- self.api_client = api_client
700
- self.callable = callable
701
-
702
- def __validate_inputs(self, kwargs):
703
- for param in self.params_map['enum']:
704
- if param in kwargs:
705
- check_allowed_values(
706
- self.allowed_values,
707
- (param,),
708
- kwargs[param]
709
- )
676
+ if auth_setting['in'] == 'cookie':
677
+ headers['Cookie'] = auth_setting['value']
678
+ elif auth_setting['in'] == 'header':
679
+ if auth_setting['type'] != 'http-signature':
680
+ headers[auth_setting['key']] = auth_setting['value']
681
+ elif auth_setting['in'] == 'query':
682
+ queries.append((auth_setting['key'], auth_setting['value']))
683
+ else:
684
+ raise ApiValueError(
685
+ 'Authentication token must be in `query` or `header`'
686
+ )
710
687
 
711
- for param in self.params_map['validation']:
712
- if param in kwargs:
713
- check_validations(
714
- self.validations,
715
- (param,),
716
- kwargs[param],
717
- configuration=self.api_client.configuration
718
- )
688
+ def __deserialize_file(self, response):
689
+ """Deserializes body to file
719
690
 
720
- if kwargs['_check_input_type'] is False:
721
- return
691
+ Saves response body into a file in a temporary folder,
692
+ using the filename from the `Content-Disposition` header if provided.
693
+
694
+ handle file downloading
695
+ save response body into a tmp file and return the instance
722
696
 
723
- for key, value in kwargs.items():
724
- fixed_val = validate_and_convert_types(
725
- value,
726
- self.openapi_types[key],
727
- [key],
728
- kwargs['_spec_property_naming'],
729
- kwargs['_check_input_type'],
730
- configuration=self.api_client.configuration
697
+ :param response: RESTResponse.
698
+ :return: file path.
699
+ """
700
+ fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path)
701
+ os.close(fd)
702
+ os.remove(path)
703
+
704
+ content_disposition = response.getheader("Content-Disposition")
705
+ if content_disposition:
706
+ m = re.search(
707
+ r'filename=[\'"]?([^\'"\s]+)[\'"]?',
708
+ content_disposition
731
709
  )
732
- kwargs[key] = fixed_val
733
-
734
- def __gather_params(self, kwargs):
735
- params = {
736
- 'body': None,
737
- 'collection_format': {},
738
- 'file': {},
739
- 'form': [],
740
- 'header': {},
741
- 'path': {},
742
- 'query': []
743
- }
710
+ assert m is not None, "Unexpected 'content-disposition' header value"
711
+ filename = m.group(1)
712
+ path = os.path.join(os.path.dirname(path), filename)
744
713
 
745
- for param_name, param_value in kwargs.items():
746
- param_location = self.location_map.get(param_name)
747
- if param_location is None:
748
- continue
749
- if param_location:
750
- if param_location == 'body':
751
- params['body'] = param_value
752
- continue
753
- base_name = self.attribute_map[param_name]
754
- if (param_location == 'form' and
755
- self.openapi_types[param_name] == (file_type,)):
756
- params['file'][base_name] = [param_value]
757
- elif (param_location == 'form' and
758
- self.openapi_types[param_name] == ([file_type],)):
759
- # param_value is already a list
760
- params['file'][base_name] = param_value
761
- elif param_location in {'form', 'query'}:
762
- param_value_full = (base_name, param_value)
763
- params[param_location].append(param_value_full)
764
- if param_location not in {'form', 'query'}:
765
- params[param_location][base_name] = param_value
766
- collection_format = self.collection_format_map.get(param_name)
767
- if collection_format:
768
- params['collection_format'][base_name] = collection_format
714
+ with open(path, "wb") as f:
715
+ f.write(response.data)
769
716
 
770
- return params
717
+ return path
771
718
 
772
- def __call__(self, *args, **kwargs):
773
- """ This method is invoked when endpoints are called
774
- Example:
719
+ def __deserialize_primitive(self, data, klass):
720
+ """Deserializes string to primitive type.
775
721
 
776
- api_instance = AuthApi()
777
- api_instance.create_jwt_token # this is an instance of the class Endpoint
778
- api_instance.create_jwt_token() # this invokes api_instance.create_jwt_token.__call__()
779
- which then invokes the callable functions stored in that endpoint at
780
- api_instance.create_jwt_token.callable or self.callable in this class
722
+ :param data: str.
723
+ :param klass: class literal.
781
724
 
725
+ :return: int, long, float, str, bool.
782
726
  """
783
- return self.callable(self, *args, **kwargs)
727
+ try:
728
+ return klass(data)
729
+ except UnicodeEncodeError:
730
+ return str(data)
731
+ except TypeError:
732
+ return data
784
733
 
785
- def call_with_http_info(self, **kwargs):
734
+ def __deserialize_object(self, value):
735
+ """Return an original value.
736
+
737
+ :return: object.
738
+ """
739
+ return value
786
740
 
741
+ def __deserialize_date(self, string):
742
+ """Deserializes string to date.
743
+
744
+ :param string: str.
745
+ :return: date.
746
+ """
787
747
  try:
788
- index = self.api_client.configuration.server_operation_index.get(
789
- self.settings['operation_id'], self.api_client.configuration.server_index
790
- ) if kwargs['_host_index'] is None else kwargs['_host_index']
791
- server_variables = self.api_client.configuration.server_operation_variables.get(
792
- self.settings['operation_id'], self.api_client.configuration.server_variables
793
- )
794
- _host = self.api_client.configuration.get_host_from_settings(
795
- index, variables=server_variables, servers=self.settings['servers']
748
+ return parse(string).date()
749
+ except ImportError:
750
+ return string
751
+ except ValueError:
752
+ raise rest.ApiException(
753
+ status=0,
754
+ reason="Failed to parse `{0}` as date object".format(string)
796
755
  )
797
- except IndexError:
798
- if self.settings['servers']:
799
- raise ApiValueError(
800
- "Invalid host index. Must be 0 <= index < %s" %
801
- len(self.settings['servers'])
802
- )
803
- _host = None
804
-
805
- for key, value in kwargs.items():
806
- if key not in self.params_map['all']:
807
- raise ApiTypeError(
808
- "Got an unexpected parameter '%s'"
809
- " to method `%s`" %
810
- (key, self.settings['operation_id'])
811
- )
812
- # only throw this nullable ApiValueError if _check_input_type
813
- # is False, if _check_input_type==True we catch this case
814
- # in self.__validate_inputs
815
- if (key not in self.params_map['nullable'] and value is None
816
- and kwargs['_check_input_type'] is False):
817
- raise ApiValueError(
818
- "Value may not be None for non-nullable parameter `%s`"
819
- " when calling `%s`" %
820
- (key, self.settings['operation_id'])
821
- )
822
756
 
823
- for key in self.params_map['required']:
824
- if key not in kwargs.keys():
825
- raise ApiValueError(
826
- "Missing the required parameter `%s` when calling "
827
- "`%s`" % (key, self.settings['operation_id'])
757
+ def __deserialize_datetime(self, string):
758
+ """Deserializes string to datetime.
759
+
760
+ The string should be in iso8601 datetime format.
761
+
762
+ :param string: str.
763
+ :return: datetime.
764
+ """
765
+ try:
766
+ return parse(string)
767
+ except ImportError:
768
+ return string
769
+ except ValueError:
770
+ raise rest.ApiException(
771
+ status=0,
772
+ reason=(
773
+ "Failed to parse `{0}` as datetime object"
774
+ .format(string)
828
775
  )
776
+ )
777
+
778
+ def __deserialize_enum(self, data, klass):
779
+ """Deserializes primitive type to enum.
829
780
 
830
- self.__validate_inputs(kwargs)
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
+ )
831
795
 
832
- params = self.__gather_params(kwargs)
796
+ def __deserialize_model(self, data, klass):
797
+ """Deserializes list or dict to model.
833
798
 
834
- accept_headers_list = self.headers_map['accept']
835
- if accept_headers_list:
836
- params['header']['Accept'] = self.api_client.select_header_accept(
837
- accept_headers_list)
799
+ :param data: dict, list.
800
+ :param klass: class literal.
801
+ :return: model object.
802
+ """
838
803
 
839
- if kwargs.get('_content_type'):
840
- params['header']['Content-Type'] = kwargs['_content_type']
841
- else:
842
- content_type_headers_list = self.headers_map['content_type']
843
- if content_type_headers_list:
844
- if params['body'] != "":
845
- header_list = self.api_client.select_header_content_type(
846
- content_type_headers_list, self.settings['http_method'],
847
- params['body'])
848
- params['header']['Content-Type'] = header_list
849
-
850
- return self.api_client.call_api(
851
- self.settings['endpoint_path'], self.settings['http_method'],
852
- params['path'],
853
- params['query'],
854
- params['header'],
855
- body=params['body'],
856
- post_params=params['form'],
857
- files=params['file'],
858
- response_type=self.settings['response_type'],
859
- auth_settings=self.settings['auth'],
860
- async_req=kwargs['async_req'],
861
- _check_type=kwargs['_check_return_type'],
862
- _return_http_data_only=kwargs['_return_http_data_only'],
863
- _preload_content=kwargs['_preload_content'],
864
- _request_timeout=kwargs['_request_timeout'],
865
- _host=_host,
866
- collection_formats=params['collection_format'])
804
+ return klass.from_dict(data)