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