ibm-cloud-sdk-core 3.16.0__py3-none-any.whl → 3.20.6__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 (56) hide show
  1. ibm_cloud_sdk_core/__init__.py +1 -0
  2. ibm_cloud_sdk_core/api_exception.py +18 -4
  3. ibm_cloud_sdk_core/authenticators/__init__.py +1 -0
  4. ibm_cloud_sdk_core/authenticators/authenticator.py +2 -1
  5. ibm_cloud_sdk_core/authenticators/basic_authenticator.py +5 -6
  6. ibm_cloud_sdk_core/authenticators/bearer_token_authenticator.py +1 -1
  7. ibm_cloud_sdk_core/authenticators/container_authenticator.py +25 -16
  8. ibm_cloud_sdk_core/authenticators/cp4d_authenticator.py +33 -21
  9. ibm_cloud_sdk_core/authenticators/iam_authenticator.py +22 -13
  10. ibm_cloud_sdk_core/authenticators/iam_request_based_authenticator.py +5 -7
  11. ibm_cloud_sdk_core/authenticators/mcsp_authenticator.py +130 -0
  12. ibm_cloud_sdk_core/authenticators/vpc_instance_authenticator.py +7 -10
  13. ibm_cloud_sdk_core/base_service.py +107 -91
  14. ibm_cloud_sdk_core/detailed_response.py +21 -15
  15. ibm_cloud_sdk_core/get_authenticator.py +28 -16
  16. ibm_cloud_sdk_core/http_adapter.py +28 -0
  17. ibm_cloud_sdk_core/private_helpers.py +34 -0
  18. ibm_cloud_sdk_core/token_managers/container_token_manager.py +61 -30
  19. ibm_cloud_sdk_core/token_managers/cp4d_token_manager.py +30 -22
  20. ibm_cloud_sdk_core/token_managers/iam_request_based_token_manager.py +43 -20
  21. ibm_cloud_sdk_core/token_managers/iam_token_manager.py +24 -13
  22. ibm_cloud_sdk_core/token_managers/jwt_token_manager.py +3 -16
  23. ibm_cloud_sdk_core/token_managers/mcsp_token_manager.py +102 -0
  24. ibm_cloud_sdk_core/token_managers/token_manager.py +13 -23
  25. ibm_cloud_sdk_core/token_managers/vpc_instance_token_manager.py +33 -13
  26. ibm_cloud_sdk_core/utils.py +121 -46
  27. ibm_cloud_sdk_core/version.py +1 -1
  28. {ibm_cloud_sdk_core-3.16.0.dist-info → ibm_cloud_sdk_core-3.20.6.dist-info}/METADATA +40 -28
  29. ibm_cloud_sdk_core-3.20.6.dist-info/RECORD +34 -0
  30. {ibm_cloud_sdk_core-3.16.0.dist-info → ibm_cloud_sdk_core-3.20.6.dist-info}/WHEEL +1 -1
  31. ibm_cloud_sdk_core-3.20.6.dist-info/top_level.txt +1 -0
  32. ibm_cloud_sdk_core-3.16.0.dist-info/RECORD +0 -52
  33. ibm_cloud_sdk_core-3.16.0.dist-info/top_level.txt +0 -3
  34. ibm_cloud_sdk_core-3.16.0.dist-info/zip-safe +0 -1
  35. test/__init__.py +0 -0
  36. test/test_api_exception.py +0 -73
  37. test/test_authenticator.py +0 -21
  38. test/test_base_service.py +0 -933
  39. test/test_basic_authenticator.py +0 -36
  40. test/test_bearer_authenticator.py +0 -28
  41. test/test_container_authenticator.py +0 -105
  42. test/test_container_token_manager.py +0 -283
  43. test/test_cp4d_authenticator.py +0 -171
  44. test/test_cp4d_token_manager.py +0 -56
  45. test/test_detailed_response.py +0 -57
  46. test/test_iam_authenticator.py +0 -157
  47. test/test_iam_token_manager.py +0 -362
  48. test/test_jwt_token_manager.py +0 -109
  49. test/test_no_auth_authenticator.py +0 -15
  50. test/test_token_manager.py +0 -84
  51. test/test_utils.py +0 -634
  52. test/test_vpc_instance_authenticator.py +0 -66
  53. test/test_vpc_instance_token_manager.py +0 -266
  54. test_integration/__init__.py +0 -0
  55. test_integration/test_cp4d_authenticator_integration.py +0 -45
  56. {ibm_cloud_sdk_core-3.16.0.dist-info → ibm_cloud_sdk_core-3.20.6.dist-info}/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- # Copyright 2021 IBM All Rights Reserved.
3
+ # Copyright 2021, 2024 IBM All Rights Reserved.
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
6
6
  # you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ import json
18
18
  import logging
19
19
  from typing import Optional
20
20
 
21
+ from ..private_helpers import _build_user_agent
21
22
  from .jwt_token_manager import JWTTokenManager
22
23
 
23
24
 
@@ -52,18 +53,19 @@ class VPCInstanceTokenManager(JWTTokenManager):
52
53
  url (str, optional): The VPC Instance Metadata Service's base endpoint URL.
53
54
  """
54
55
 
55
- METADATA_SERVICE_VERSION = '2021-09-20'
56
+ METADATA_SERVICE_VERSION = '2022-03-01'
56
57
  DEFAULT_IMS_ENDPOINT = 'http://169.254.169.254'
57
58
  TOKEN_NAME = 'access_token'
59
+ IAM_EXPIRATION_WINDOW = 10
58
60
 
59
- def __init__(self,
60
- iam_profile_crn: Optional[str] = None,
61
- iam_profile_id: Optional[str] = None,
62
- url: Optional[str] = None) -> None:
61
+ def __init__(
62
+ self, iam_profile_crn: Optional[str] = None, iam_profile_id: Optional[str] = None, url: Optional[str] = None
63
+ ) -> None:
63
64
  if not url:
64
65
  url = self.DEFAULT_IMS_ENDPOINT
65
66
 
66
67
  super().__init__(url, token_name=self.TOKEN_NAME)
68
+ self._set_user_agent(_build_user_agent('vpc-instance-authenticator'))
67
69
 
68
70
  self.iam_profile_crn = iam_profile_crn
69
71
  self.iam_profile_id = iam_profile_id
@@ -91,17 +93,18 @@ class VPCInstanceTokenManager(JWTTokenManager):
91
93
  headers = {
92
94
  'Content-Type': 'application/json',
93
95
  'Accept': 'application/json',
94
- 'Authorization': 'Bearer ' + instance_identity_token
96
+ 'Authorization': 'Bearer ' + instance_identity_token,
97
+ 'User-Agent': self._get_user_agent(),
95
98
  }
96
99
 
97
- logger.debug(
98
- 'Invoking VPC \'create_iam_token\' operation: %s', url)
100
+ logger.debug('Invoking VPC \'create_iam_token\' operation: %s', url)
99
101
  response = self._request(
100
102
  method='POST',
101
103
  url=url,
102
104
  headers=headers,
103
105
  params={'version': self.METADATA_SERVICE_VERSION},
104
- data=json.dumps(request_payload) if request_payload else None)
106
+ data=json.dumps(request_payload) if request_payload else None,
107
+ )
105
108
  logger.debug('Returned from VPC \'create_iam_token\' operation."')
106
109
 
107
110
  return response
@@ -138,18 +141,35 @@ class VPCInstanceTokenManager(JWTTokenManager):
138
141
  'Content-type': 'application/json',
139
142
  'Accept': 'application/json',
140
143
  'Metadata-Flavor': 'ibm',
144
+ 'User-Agent': self._get_user_agent(),
141
145
  }
142
146
 
143
147
  request_body = {'expires_in': 300}
144
148
 
145
- logger.debug(
146
- 'Invoking VPC \'create_access_token\' operation: %s', url)
149
+ logger.debug('Invoking VPC \'create_access_token\' operation: %s', url)
147
150
  response = self._request(
148
151
  method='PUT',
149
152
  url=url,
150
153
  headers=headers,
151
154
  params={'version': self.METADATA_SERVICE_VERSION},
152
- data=json.dumps(request_body))
155
+ data=json.dumps(request_body),
156
+ )
153
157
  logger.debug('Returned from VPC \'create_access_token\' operation."')
154
158
 
155
159
  return response['access_token']
160
+
161
+ def _is_token_expired(self) -> bool:
162
+ """
163
+ Returns true iff the current cached token is expired.
164
+ We'll consider an access token as expired when we reach its IAM server-reported expiration time
165
+ minus our expiration window (10 secs).
166
+ We do this to avoid using an access token that might expire in the middle of a long-running transaction
167
+ within an IBM Cloud service.
168
+
169
+ Returns
170
+ -------
171
+ bool
172
+ True if token is expired; False otherwise
173
+ """
174
+ current_time = self._get_current_time()
175
+ return current_time >= (self.expire_time - self.IAM_EXPIRATION_WINDOW)
@@ -15,32 +15,101 @@
15
15
  # limitations under the License.
16
16
  # from ibm_cloud_sdk_core.authenticators import Authenticator
17
17
  import datetime
18
+ import gzip
19
+ import io
18
20
  import json as json_import
19
- import ssl
21
+ import re
20
22
  from os import getenv, environ, getcwd
21
23
  from os.path import isfile, join, expanduser
22
24
  from typing import List, Union
23
25
  from urllib.parse import urlparse, parse_qs
24
26
 
25
- from requests.adapters import HTTPAdapter
26
- from urllib3.util.ssl_ import create_urllib3_context
27
-
28
27
  import dateutil.parser as date_parser
29
28
 
30
29
 
31
- class SSLHTTPAdapter(HTTPAdapter):
32
- """Wraps the original HTTP adapter and adds additional SSL context.
30
+ class GzipStream(io.RawIOBase):
31
+ """Compress files on the fly.
32
+
33
+ GzipStream is a helper class around the gzip library. It helps to
34
+ compress already opened files (file-like objects) on the fly, so
35
+ there is no need to read everything into the memory and call the
36
+ `compress` function on it.
37
+ The GzipFile is opened on the instance itself so it needs to act
38
+ as a file-like object.
39
+
40
+ Args:
41
+ input: the source of the data to be compressed.
42
+ It can be a file-like object, bytes or string.
33
43
  """
34
- def __init__(self, *args, **kwargs):
35
- super().__init__(*args, **kwargs)
36
44
 
37
- #pylint: disable=arguments-differ
38
- def init_poolmanager(self, connections, maxsize, block):
39
- """Extends the parent's method by adding minimum SSL version to the args.
45
+ def __init__(self, source: Union[io.IOBase, bytes, str]):
46
+ self.buffer = b''
47
+
48
+ if isinstance(source, io.IOBase):
49
+ # The input is already a file-like object, use it as-is.
50
+ self.uncompressed = source
51
+ elif isinstance(source, str):
52
+ # Strings must be handled with StringIO.
53
+ self.uncompressed = io.StringIO(source)
54
+ else:
55
+ # Handle the rest as raw bytes.
56
+ self.uncompressed = io.BytesIO(source)
57
+
58
+ self.compressor = gzip.GzipFile(fileobj=self, mode='wb')
59
+
60
+ def read(self, size: int = -1) -> bytes:
61
+ """Compresses and returns the requested size of data.
62
+
63
+ Args:
64
+ size: how many bytes to return. -1 to read and compress the whole file
40
65
  """
41
- ssl_context = create_urllib3_context()
42
- ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
43
- super().init_poolmanager(connections, maxsize, block, ssl_context=ssl_context)
66
+ compressed = b''
67
+
68
+ if (size < 0) or (len(self.buffer) < size):
69
+ for raw in self.uncompressed:
70
+ # We need to encode text like streams (e.g. TextIOWrapper) to bytes.
71
+ if isinstance(raw, str):
72
+ raw = raw.encode()
73
+
74
+ self.compressor.write(raw)
75
+
76
+ # Stop compressing if we reached the max allowed size.
77
+ if 0 < size < len(self.buffer):
78
+ self.compressor.flush()
79
+ break
80
+ else:
81
+ self.compressor.close()
82
+
83
+ if size < 0:
84
+ # Return all data from the buffer.
85
+ compressed = self.buffer
86
+ self.buffer = b''
87
+ else:
88
+ # If we already have enough data in our buffer
89
+ # return the desired chunk of bytes
90
+ compressed = self.buffer[:size]
91
+ # then remove them from the buffer.
92
+ self.buffer = self.buffer[size:]
93
+
94
+ return compressed
95
+
96
+ def flush(self) -> None:
97
+ """Not implemented."""
98
+ # Since this "pipe" sits between 2 other stream (source/read -> target/write)
99
+ # it wouldn't be worth to implemet flushing.
100
+ pass
101
+
102
+ def write(self, compressed: bytes) -> None:
103
+ """Append the compressed data to the buffer
104
+
105
+ This happens when the target stream calls the `read` method and
106
+ that triggers the gzip "compressor".
107
+ """
108
+ self.buffer += compressed
109
+
110
+ def close(self) -> None:
111
+ """Closes the underlying file-like object."""
112
+ self.uncompressed.close()
44
113
 
45
114
 
46
115
  def has_bad_first_or_last_char(val: str) -> bool:
@@ -52,8 +121,7 @@ def has_bad_first_or_last_char(val: str) -> bool:
52
121
  Returns:
53
122
  Whether or not the string starts or ends with bad characters.
54
123
  """
55
- return val is not None and (val.startswith('{') or val.startswith('"')
56
- or val.endswith('}') or val.endswith('"'))
124
+ return val is not None and (val.startswith('{') or val.startswith('"') or val.endswith('}') or val.endswith('"'))
57
125
 
58
126
 
59
127
  def remove_null_values(dictionary: dict) -> dict:
@@ -146,8 +214,9 @@ def string_to_datetime_list(string_list: List[str]) -> List[datetime.datetime]:
146
214
  the de-serialized list of strings as a list of datetime objects.
147
215
  """
148
216
  if not isinstance(string_list, list):
149
- raise ValueError("Invalid argument type: " + str(type(string_list))
150
- + ". Argument string_list must be of type List[str]")
217
+ raise ValueError(
218
+ "Invalid argument type: " + str(type(string_list)) + ". Argument string_list must be of type List[str]"
219
+ )
151
220
  datetime_list = []
152
221
  for string_val in string_list:
153
222
  datetime_list.append(string_to_datetime(string_val))
@@ -164,8 +233,11 @@ def datetime_to_string_list(datetime_list: List[datetime.datetime]) -> List[str]
164
233
  list of datetimes serialized as strings in iso8601 format.
165
234
  """
166
235
  if not isinstance(datetime_list, list):
167
- raise ValueError("Invalid argument type: " + str(type(datetime_list))
168
- + ". Argument datetime_list must be of type List[datetime.datetime]")
236
+ raise ValueError(
237
+ "Invalid argument type: "
238
+ + str(type(datetime_list))
239
+ + ". Argument datetime_list must be of type List[datetime.datetime]"
240
+ )
169
241
  string_list = []
170
242
  for datetime_val in datetime_list:
171
243
  string_list.append(datetime_to_string(datetime_val))
@@ -299,9 +371,7 @@ def __read_from_env_variables(service_name: str) -> dict:
299
371
  return config
300
372
 
301
373
 
302
- def __read_from_credential_file(service_name: str,
303
- *,
304
- separator: str = '=') -> dict:
374
+ def __read_from_credential_file(service_name: str, *, separator: str = '=') -> dict:
305
375
  """Return a config object based on credentials file for a service.
306
376
 
307
377
  Args:
@@ -339,8 +409,7 @@ def __read_from_credential_file(service_name: str,
339
409
  if len(key_val) == 2:
340
410
  key = key_val[0]
341
411
  value = key_val[1]
342
- _parse_key_and_update_config(config, service_name, key,
343
- value)
412
+ _parse_key_and_update_config(config, service_name, key, value)
344
413
  except OSError:
345
414
  # just absorb the exception and make sure we return an empty response
346
415
  config = {}
@@ -348,11 +417,10 @@ def __read_from_credential_file(service_name: str,
348
417
  return config
349
418
 
350
419
 
351
- def _parse_key_and_update_config(config: dict, service_name: str, key: str,
352
- value: str) -> None:
420
+ def _parse_key_and_update_config(config: dict, service_name: str, key: str, value: str) -> None:
353
421
  service_name = service_name.replace(' ', '_').replace('-', '_').upper()
354
422
  if key.startswith(service_name):
355
- config[key[len(service_name) + 1:]] = value
423
+ config[key[len(service_name) + 1 :]] = value
356
424
 
357
425
 
358
426
  def __read_from_vcap_services(service_name: str) -> dict:
@@ -370,39 +438,46 @@ def __read_from_vcap_services(service_name: str) -> dict:
370
438
  services = json_import.loads(vcap_services)
371
439
  for key in services.keys():
372
440
  for i in range(len(services[key])):
373
- if vcap_service_credentials and isinstance(
374
- vcap_service_credentials, dict):
441
+ if vcap_service_credentials and isinstance(vcap_service_credentials, dict):
375
442
  break
376
443
  if services[key][i].get('name') == service_name:
377
- vcap_service_credentials = services[key][i].get(
378
- 'credentials', {})
444
+ vcap_service_credentials = services[key][i].get('credentials', {})
379
445
  if not vcap_service_credentials:
380
446
  if service_name in services.keys():
381
447
  service = services.get(service_name)
382
448
  if service:
383
- vcap_service_credentials = service[0].get(
384
- 'credentials', {})
449
+ vcap_service_credentials = service[0].get('credentials', {})
385
450
 
386
- if vcap_service_credentials and isinstance(vcap_service_credentials,
387
- dict):
451
+ if vcap_service_credentials and isinstance(vcap_service_credentials, dict):
388
452
  new_vcap_creds = {}
389
453
  # cf
390
- if vcap_service_credentials.get(
391
- 'username') and vcap_service_credentials.get('password'):
454
+ if vcap_service_credentials.get('username') and vcap_service_credentials.get('password'):
392
455
  new_vcap_creds['AUTH_TYPE'] = 'basic'
393
- new_vcap_creds['USERNAME'] = vcap_service_credentials.get(
394
- 'username')
395
- new_vcap_creds['PASSWORD'] = vcap_service_credentials.get(
396
- 'password')
456
+ new_vcap_creds['USERNAME'] = vcap_service_credentials.get('username')
457
+ new_vcap_creds['PASSWORD'] = vcap_service_credentials.get('password')
397
458
  vcap_service_credentials = new_vcap_creds
398
459
  elif vcap_service_credentials.get('iam_apikey'):
399
460
  new_vcap_creds['AUTH_TYPE'] = 'iam'
400
- new_vcap_creds['APIKEY'] = vcap_service_credentials.get(
401
- 'iam_apikey')
461
+ new_vcap_creds['APIKEY'] = vcap_service_credentials.get('iam_apikey')
402
462
  vcap_service_credentials = new_vcap_creds
403
463
  elif vcap_service_credentials.get('apikey'):
404
464
  new_vcap_creds['AUTH_TYPE'] = 'iam'
405
- new_vcap_creds['APIKEY'] = vcap_service_credentials.get(
406
- 'apikey')
465
+ new_vcap_creds['APIKEY'] = vcap_service_credentials.get('apikey')
407
466
  vcap_service_credentials = new_vcap_creds
408
467
  return vcap_service_credentials
468
+
469
+
470
+ # A regex that matches an "application/json" mimetype.
471
+ json_mimetype_pattern = re.compile('^application/json(\\s*;.*)?$')
472
+
473
+
474
+ def is_json_mimetype(mimetype: str) -> bool:
475
+ """Returns true if 'mimetype' is a JSON-like mimetype, false otherwise.
476
+
477
+ Args:
478
+ mimetype: The mimetype to check.
479
+
480
+ Returns:
481
+ true if mimetype is a JSON-line mimetype, false otherwise.
482
+ """
483
+ return mimetype is not None and json_mimetype_pattern.match(mimetype) is not None
@@ -1 +1 @@
1
- __version__ = '3.16.0'
1
+ __version__ = '3.20.6'
@@ -1,30 +1,47 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ibm-cloud-sdk-core
3
- Version: 3.16.0
3
+ Version: 3.20.6
4
4
  Summary: Core library used by SDKs for IBM Cloud Services
5
- Home-page: https://github.com/IBM/python-sdk-core
6
- Author: IBM
7
- Author-email: devxsdk@us.ibm.com
8
- License: Apache 2.0
9
- Keywords: watson,ibm,cloud,ibm cloud services
5
+ Author-email: IBM <devxsdk@us.ibm.com>
6
+ Project-URL: Repository, https://github.com/IBM/python-sdk-core
7
+ Project-URL: Documentation, https://github.com/IBM/python-sdk-core/blob/main/README.md
8
+ Project-URL: Issues, https://github.com/IBM/python-sdk-core/issues
9
+ Project-URL: Changelog, https://github.com/IBM/python-sdk-core/blob/main/CHANGELOG.md
10
+ Project-URL: Contributing, https://github.com/IBM/python-sdk-core/blob/main/CONTRIBUTING.md
11
+ Project-URL: License, https://github.com/IBM/python-sdk-core/blob/main/LICENSE
12
+ Keywords: ibm,cloud,ibm cloud services
10
13
  Classifier: Programming Language :: Python
11
14
  Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.7
13
15
  Classifier: Programming Language :: Python :: 3.8
14
16
  Classifier: Programming Language :: Python :: 3.9
15
17
  Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
16
20
  Classifier: Development Status :: 5 - Production/Stable
21
+ Classifier: Environment :: Console
17
22
  Classifier: Intended Audience :: Developers
18
23
  Classifier: License :: OSI Approved :: Apache Software License
19
24
  Classifier: Operating System :: OS Independent
25
+ Classifier: Topic :: Software Development :: Libraries
20
26
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
27
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
28
+ Requires-Python: >=3.8
22
29
  Description-Content-Type: text/markdown
23
30
  License-File: LICENSE
24
- Requires-Dist: requests (<3.0.0,>=2.26.0)
25
- Requires-Dist: urllib3 (<2.0.0,>=1.26.0)
26
- Requires-Dist: python-dateutil (<3.0.0,>=2.5.3)
27
- Requires-Dist: PyJWT (<3.0.0,>=2.4.0)
31
+ Requires-Dist: requests <3.0.0,>=2.31.0
32
+ Requires-Dist: urllib3 <3.0.0,>=2.1.0
33
+ Requires-Dist: python-dateutil <3.0.0,>=2.8.2
34
+ Requires-Dist: PyJWT <3.0.0,>=2.8.0
35
+ Provides-Extra: dev
36
+ Requires-Dist: coverage <8.0.0,>=7.3.2 ; extra == 'dev'
37
+ Requires-Dist: pylint <4.0.0,>=3.0.0 ; extra == 'dev'
38
+ Requires-Dist: pytest <8.0.0,>=7.4.2 ; extra == 'dev'
39
+ Requires-Dist: pytest-cov <5.0.0,>=4.1.0 ; extra == 'dev'
40
+ Requires-Dist: responses <1.0.0,>=0.23.3 ; extra == 'dev'
41
+ Requires-Dist: black <25.0.0,>=24.0.0 ; extra == 'dev'
42
+ Provides-Extra: publish
43
+ Requires-Dist: build ; extra == 'publish'
44
+ Requires-Dist: twine ; extra == 'publish'
28
45
 
29
46
  [![Build Status](https://app.travis-ci.com/IBM/python-sdk-core.svg?branch=main)](https://app.travis-ci.com/IBM/python-sdk-core)
30
47
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ibm-cloud-sdk-core)](https://pypi.org/project/ibm-cloud-sdk-core/)
@@ -32,37 +49,32 @@ Requires-Dist: PyJWT (<3.0.0,>=2.4.0)
32
49
  [![CLA assistant](https://cla-assistant.io/readme/badge/ibm/python-sdk-core)](https://cla-assistant.io/ibm/python-sdk-core)
33
50
  [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
34
51
 
35
- # IBM Python SDK Core Version 3.16.0
52
+ # IBM Python SDK Core Version 3.20.6
36
53
  This project contains core functionality required by Python code generated by the IBM Cloud OpenAPI SDK Generator
37
54
  (openapi-sdkgen).
38
55
 
39
56
  # Python Version
40
- The current minimum Python version supported is 3.7.
57
+ The current minimum Python version supported is 3.8.
41
58
 
42
59
  ## Installation
43
60
 
44
- To install, use `pip` or `easy_install`:
61
+ To install, use `pip`:
45
62
 
46
63
  ```bash
47
- pip install --upgrade ibm-cloud-sdk-core
48
- ```
49
-
50
- or
51
-
52
- ```bash
53
- easy_install --upgrade ibm-cloud-sdk-core
64
+ python -m pip install --upgrade ibm-cloud-sdk-core
54
65
  ```
55
66
 
56
67
  ## Authentication
57
68
  The python-sdk-core project supports the following types of authentication:
58
69
  - Basic Authentication
59
- - Bearer Token
60
- - Identity and Access Management (IAM)
61
- - Cloud Pak for Data
62
- - Container
63
- - No Authentication
64
-
65
- For more information about the various authentication types and how to use them with your services, click [here](Authentication.md)
70
+ - Bearer Token Authentication
71
+ - Identity and Access Management (IAM) Authentication
72
+ - Container Authentication
73
+ - VPC Instance Authentication
74
+ - Cloud Pak for Data Authentication
75
+ - No Authentication (for testing)
76
+
77
+ For more information about the various authentication types and how to use them with your services, click [here](Authentication.md).
66
78
 
67
79
  ## Issues
68
80
 
@@ -0,0 +1,34 @@
1
+ ibm_cloud_sdk_core/__init__.py,sha256=Ef7P3r-KmVwoYQV9bP0zvaDSlgJtjaTcDYQXmVvm0Zs,2853
2
+ ibm_cloud_sdk_core/api_exception.py,sha256=YNd7Dg_yiwcHk-AA-suNlivgyrA9A32Do1qtYeKzuWc,3654
3
+ ibm_cloud_sdk_core/base_service.py,sha256=GmvE4yCGHP1LXLsOnj1Q_GoizIsLrHU2YJPShZNbMRM,21056
4
+ ibm_cloud_sdk_core/detailed_response.py,sha256=agLMQ-Mh3bU_lLnSnSO1SwjuNBPQj8plO8ew2xXWL6I,3101
5
+ ibm_cloud_sdk_core/get_authenticator.py,sha256=GcKk8LI1xX1AC0S5x3SQxoaQJne4K0ae_KPf8bNgi50,4577
6
+ ibm_cloud_sdk_core/http_adapter.py,sha256=nRUvt7hbSC8Vyhqe_oA5k_NKoRMM-S4VCSAZVQ-AHQU,1075
7
+ ibm_cloud_sdk_core/private_helpers.py,sha256=5ei9gNwuN-inNJ2WqMXcXEPfLM1NALOLi4ucLMcYohY,1181
8
+ ibm_cloud_sdk_core/utils.py,sha256=caUFQWS06nzVW9ooU7ZG2pEJol-jjZ53JiLnLkQT_6k,15636
9
+ ibm_cloud_sdk_core/version.py,sha256=rHqvR40CBAKEsUqfGKCi0eEi3aO5lGioNtRWEfFuylY,23
10
+ ibm_cloud_sdk_core/authenticators/__init__.py,sha256=Ze_ArDqMWk1Xr311dXpHTtJUJYN2u8jCphoGTLBow9M,2133
11
+ ibm_cloud_sdk_core/authenticators/authenticator.py,sha256=dyTQDEAhlcN4y-wybTgMycSO5dC2pLntx3KCJTJGHdQ,1979
12
+ ibm_cloud_sdk_core/authenticators/basic_authenticator.py,sha256=moHfqmI0Lekgsrl0kjLvhyUbcMhh7tPPZArKn9OW_gQ,3129
13
+ ibm_cloud_sdk_core/authenticators/bearer_token_authenticator.py,sha256=KtoN4lgEIIbRiWLJHftPjK_CLQj_sx5lmrc2xm1E7mk,2623
14
+ ibm_cloud_sdk_core/authenticators/container_authenticator.py,sha256=GKYHTflLiKhm9xF5KZAcjYXPN3yE2PztdEr2bOZUwKE,7042
15
+ ibm_cloud_sdk_core/authenticators/cp4d_authenticator.py,sha256=9xaoEbqQqFVO1DdYDPMTMyIlrAAS8TrTSKxqOh4hHfI,6752
16
+ ibm_cloud_sdk_core/authenticators/iam_authenticator.py,sha256=ozrFBdVah1y8gcLL68fmReXCFEAltOGLCIuA6PuWLSY,4597
17
+ ibm_cloud_sdk_core/authenticators/iam_request_based_authenticator.py,sha256=JUUZF_UgWQmA9U6WxsdSHzuL3R6fxEDdC0VgHHt1Ygk,4515
18
+ ibm_cloud_sdk_core/authenticators/mcsp_authenticator.py,sha256=F6b4s7QXkqWP_5ls21jZPquxIz7HfFm7MTotVtVY3fA,5179
19
+ ibm_cloud_sdk_core/authenticators/no_auth_authenticator.py,sha256=dzuU6IJC19SocVHy7Fyln6xrfGvlqnXGeUNR9llspYo,979
20
+ ibm_cloud_sdk_core/authenticators/vpc_instance_authenticator.py,sha256=xdWHjGWFoSzf0bB0fnnT9fTs-N708cnUxRJ2I-kUQME,5243
21
+ ibm_cloud_sdk_core/token_managers/__init__.py,sha256=NEiims6qB8doxq6wtlTBYCIdwf2wRiMTrV0bgfv7WAg,606
22
+ ibm_cloud_sdk_core/token_managers/container_token_manager.py,sha256=jkOJoy9SutIvYrwoQfm9OQ4lfn0lI4jJNfcIFiAqh9M,9505
23
+ ibm_cloud_sdk_core/token_managers/cp4d_token_manager.py,sha256=EeE7EZtwAIVYCcnlTdbWU1U77PFbmZLgHL9LuCDJy_Q,4948
24
+ ibm_cloud_sdk_core/token_managers/iam_request_based_token_manager.py,sha256=KOz5aXjHfYWCQWqSpvf7vNLEzZq0ZKLAHVtHzcnQKfY,8314
25
+ ibm_cloud_sdk_core/token_managers/iam_token_manager.py,sha256=bG94h0Io6XaneLUcSuJzLlKSpFLdKH49TieRNAY7fvA,4358
26
+ ibm_cloud_sdk_core/token_managers/jwt_token_manager.py,sha256=FDBdvirmUcJu5vIb5pdhqoQeFS6j0GBSDsF0HtLjg48,3785
27
+ ibm_cloud_sdk_core/token_managers/mcsp_token_manager.py,sha256=qo2slOLUfxZ296iO6flQEbJZtYKTD9XXhuHKCvBesJM,3992
28
+ ibm_cloud_sdk_core/token_managers/token_manager.py,sha256=ve83zlER6TiflGha6qo_DXyku6b2xoeMT4PBpENBeco,7715
29
+ ibm_cloud_sdk_core/token_managers/vpc_instance_token_manager.py,sha256=hZP-0H9YPoB6R4mTJZ0zZBxMCJhMUSrvVfzVZXVdti8,6998
30
+ ibm_cloud_sdk_core-3.20.6.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
31
+ ibm_cloud_sdk_core-3.20.6.dist-info/METADATA,sha256=tK0mVDJDcPS37D1ILTH-qH5kSdRDqh7ZqTLwDyfGFH4,5509
32
+ ibm_cloud_sdk_core-3.20.6.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
33
+ ibm_cloud_sdk_core-3.20.6.dist-info/top_level.txt,sha256=otLtvxe-8ugPRmPqeSnbaOjnAl0qjDRZ1HSkC3aeLpI,19
34
+ ibm_cloud_sdk_core-3.20.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: setuptools (72.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1 @@
1
+ ibm_cloud_sdk_core
@@ -1,52 +0,0 @@
1
- ibm_cloud_sdk_core/__init__.py,sha256=uVj5a2fM1X6OQ1ivAMf1BNUViJGex8RBOAMF4bhOUeA,2789
2
- ibm_cloud_sdk_core/api_exception.py,sha256=OvY5-ACudE04O6heN8WwiTpEvNPEMjHx8iifC09IqjI,3180
3
- ibm_cloud_sdk_core/base_service.py,sha256=XA1rPZczIEwvF41KXQlXFkOMmk3MPv7mYk1U1MdmhQk,20326
4
- ibm_cloud_sdk_core/detailed_response.py,sha256=JJ0QErbtQn0IWBfqclHhsugktgDQ6m26D6uMIH9jxhw,2739
5
- ibm_cloud_sdk_core/get_authenticator.py,sha256=jQV2PJGUzPCgVh15t9LG_Towkm7rPwAmIVJhfmoQUUk,4416
6
- ibm_cloud_sdk_core/utils.py,sha256=NxYaU45OoIbiBmI0NUcHH7bI5PEiVgx_FMTbchTFE1c,13267
7
- ibm_cloud_sdk_core/version.py,sha256=QvIdF5iFXpxlDqlLo7VlyHafPD55za59ZtMi1jF2kSo,23
8
- ibm_cloud_sdk_core/authenticators/__init__.py,sha256=HLrbQMlA15-SKSgB2rW0qAjWDjnWNKWcqv2-Aet6iuQ,2083
9
- ibm_cloud_sdk_core/authenticators/authenticator.py,sha256=WVVojlEPA8WMxWUSvFx7tCamU6fpDx5EwvZ0WYRqAJg,1946
10
- ibm_cloud_sdk_core/authenticators/basic_authenticator.py,sha256=l-q55Xdv5ULhT_tF3lJgQPaFt_N0psAMolPzcERF-FE,3147
11
- ibm_cloud_sdk_core/authenticators/bearer_token_authenticator.py,sha256=fHRSCGb8OQa6Rt6UIwO3fWmQMfNCGQDeq7ZBa_CPgIk,2624
12
- ibm_cloud_sdk_core/authenticators/container_authenticator.py,sha256=jIssE6O0XoghQySqJUAC_Z5E-pM3umvrEHbo0Poh7R0,7040
13
- ibm_cloud_sdk_core/authenticators/cp4d_authenticator.py,sha256=iUnmkmP8DAjX8LCm-eB6d-S_IPRlzoYonIR7zdj0yn8,6719
14
- ibm_cloud_sdk_core/authenticators/iam_authenticator.py,sha256=E62Lzl8TJ448RzI8Iz7kz0t2iysuaY9S1T0Q95H3b2A,4580
15
- ibm_cloud_sdk_core/authenticators/iam_request_based_authenticator.py,sha256=USEid25ZZc4dw8syjN0dXynIlBsOhoxx_u7tDTok9Mc,4568
16
- ibm_cloud_sdk_core/authenticators/no_auth_authenticator.py,sha256=dzuU6IJC19SocVHy7Fyln6xrfGvlqnXGeUNR9llspYo,979
17
- ibm_cloud_sdk_core/authenticators/vpc_instance_authenticator.py,sha256=p5jfxR1Vwau7alnJ-mGYOZbqPJmp6mp0c1NviZtSpvs,5291
18
- ibm_cloud_sdk_core/token_managers/__init__.py,sha256=NEiims6qB8doxq6wtlTBYCIdwf2wRiMTrV0bgfv7WAg,606
19
- ibm_cloud_sdk_core/token_managers/container_token_manager.py,sha256=fz0FRk-vQQcDehUXwPFgI0eSXWPn41Xtb2dNsQP8uOE,8441
20
- ibm_cloud_sdk_core/token_managers/cp4d_token_manager.py,sha256=cjC24U8kud_j_DKec1vFZO-eP2qZbsV70VOdd9pvXZ4,4690
21
- ibm_cloud_sdk_core/token_managers/iam_request_based_token_manager.py,sha256=f8DVYksQWHuJp_OAstaAFO1xvDO2ufMZvq7ikC6zk1E,7516
22
- ibm_cloud_sdk_core/token_managers/iam_token_manager.py,sha256=RNGLAFW5z-9zarR6g_Ry7FKU4LxxzTESux3cBICZh3s,4230
23
- ibm_cloud_sdk_core/token_managers/jwt_token_manager.py,sha256=OaqICSRrnJ0C322IqlhkjyT_cOEy3ZmH_DKWVXkHoCU,3984
24
- ibm_cloud_sdk_core/token_managers/token_manager.py,sha256=_DULCGRmerMEkW4Tgi8HntXs0bu8-mgNQoSKLstpJQc,7660
25
- ibm_cloud_sdk_core/token_managers/vpc_instance_token_manager.py,sha256=J-wJWh95MXsNjbTnY-VAY5dRJ4W79yJ0e3y4ZhbvHjU,6122
26
- test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- test/test_api_exception.py,sha256=zBdMGwXHlM4LBRgipadPPcmKb8TIDnZIsE07iH49tGk,2850
28
- test/test_authenticator.py,sha256=yL4ZM5aPS5WDcekq28IxPeaxAgc_ujz64XUVwUhVv1o,592
29
- test/test_base_service.py,sha256=l-7LDCBjBJW4-Vs459NsNpTcumCBMDikqbvphFVRHsQ,34363
30
- test/test_basic_authenticator.py,sha256=FeGXWiY8xj8i6J2X5Q--qb6B-SAOvQzjg5eExpYVzPE,1605
31
- test/test_bearer_authenticator.py,sha256=KFssfBZM109_1jWlYzPlZr3oo3vVYUkLVfIWfZZI9Us,1069
32
- test/test_container_authenticator.py,sha256=a2iZO5qc0oMl7i6Y0KJiE-IYnTuAuRFe_r-ht1d4XVc,4422
33
- test/test_container_token_manager.py,sha256=oZqmlVYF1HtkzOp0Ti1qS9CeGAoADhwqoO-FZW3D8rM,10644
34
- test/test_cp4d_authenticator.py,sha256=GJVYRVwkPsyfWku8btjnrQCH-D3JHX8PBMA_3DdwYrM,6844
35
- test/test_cp4d_token_manager.py,sha256=AJAB3fiu-3D1N3e28T7eYVCLd5G6xwx6ts8nc_gw7Hk,1735
36
- test/test_detailed_response.py,sha256=iJWPzl-ZjghHc08O3BK3-bgLHfq8B8drotvxY68B0tw,2329
37
- test/test_iam_authenticator.py,sha256=BbrnZAM2B9FZFxsfddsqQ8dJKuiMbEkrs6svdCdGCx4,5729
38
- test/test_iam_token_manager.py,sha256=b6xsOaJCYDQ8FYqqqyTB4tWI4lSGsQ6Jqz5iuWCEjHE,12569
39
- test/test_jwt_token_manager.py,sha256=b692b6Nnw_w0kBy7mslwVdhcImXg2uhSf9e7iaXfBkg,3820
40
- test/test_no_auth_authenticator.py,sha256=LVytWa77ilm7Yhcc9qtG0WhsvYJpAUgPulbnwpvsLJc,448
41
- test/test_token_manager.py,sha256=33OqwucCce9uoQWRHIjWFVH4EdBYmp1Y9gPJ2gueGvI,3031
42
- test/test_utils.py,sha256=-6_D6N14ljUNUs-HzTTy5DgjGIaYirgwK8OZI-acnl8,28577
43
- test/test_vpc_instance_authenticator.py,sha256=bdxWF6FTKR-GxJKo0vV8MhdBYAbsmD9OxHD0iooXTfo,2629
44
- test/test_vpc_instance_token_manager.py,sha256=zhoL0MFcm3xFs-rbYiBLbOAfH8N_ZNj_t1o74oNaD8A,10103
45
- test_integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
- test_integration/test_cp4d_authenticator_integration.py,sha256=1CDn5Hi5_mYTzPOGH0AN5thyN4PfbG6pR3XRgs2gsZA,1650
47
- ibm_cloud_sdk_core-3.16.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
48
- ibm_cloud_sdk_core-3.16.0.dist-info/METADATA,sha256=z9H_fTF0lvP2h7hw3UM1P39cet0dbR_WQXn7y_XhIds,4460
49
- ibm_cloud_sdk_core-3.16.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
50
- ibm_cloud_sdk_core-3.16.0.dist-info/top_level.txt,sha256=16lTiCOoJ5PUYTGw9ROgE93YWrwqgR1sRU6fJcU7h0U,41
51
- ibm_cloud_sdk_core-3.16.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
52
- ibm_cloud_sdk_core-3.16.0.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- ibm_cloud_sdk_core
2
- test
3
- test_integration
@@ -1 +0,0 @@
1
-
test/__init__.py DELETED
File without changes
@@ -1,73 +0,0 @@
1
- # coding=utf-8
2
- import json
3
-
4
- import requests
5
- import responses
6
-
7
- from ibm_cloud_sdk_core import ApiException
8
-
9
-
10
- @responses.activate
11
- def test_api_exception():
12
- """Test APIException class"""
13
- responses.add(responses.GET,
14
- 'https://test.com',
15
- status=500,
16
- body=json.dumps({'error': 'sorry', 'msg': 'serious error'}),
17
- content_type='application/json')
18
-
19
- mock_response = requests.get('https://test.com')
20
- exception = ApiException(500, http_response=mock_response)
21
- assert exception is not None
22
- assert exception.message == 'sorry'
23
-
24
- responses.add(responses.GET,
25
- 'https://test-again.com',
26
- status=500,
27
- body=json.dumps({
28
- "errors": [
29
- {
30
- "message": "sorry again",
31
- }],
32
- }),
33
- content_type='application/json')
34
- mock_response = requests.get('https://test-again.com')
35
- exception = ApiException(500, http_response=mock_response)
36
- assert exception.message == 'sorry again'
37
-
38
- responses.add(responses.GET,
39
- 'https://test-once-more.com',
40
- status=500,
41
- body=json.dumps({'message': 'sorry once more'}),
42
- content_type='application/json')
43
- mock_response = requests.get('https://test-once-more.com')
44
- exception = ApiException(500, http_response=mock_response)
45
- assert exception.message == 'sorry once more'
46
-
47
- responses.add(responses.GET,
48
- 'https://test-msg.com',
49
- status=500,
50
- body=json.dumps({'msg': 'serious error'}),
51
- content_type='application/json')
52
- mock_response = requests.get('https://test-msg.com')
53
- exception = ApiException(500, http_response=mock_response)
54
- assert exception.message == 'Internal Server Error'
55
-
56
- responses.add(responses.GET,
57
- 'https://test-errormessage.com',
58
- status=500,
59
- body=json.dumps({'errorMessage': 'IAM error message'}),
60
- content_type='application/json')
61
- mock_response = requests.get('https://test-errormessage.com')
62
- exception = ApiException(500, http_response=mock_response)
63
- assert exception.message == 'IAM error message'
64
-
65
- responses.add(responses.GET,
66
- 'https://test-for-text.com',
67
- status=500,
68
- headers={'X-Global-Transaction-ID': 'xx'},
69
- body="plain text error")
70
- mock_response = requests.get('https://test-for-text.com')
71
- exception = ApiException(500, http_response=mock_response)
72
- assert exception.message == 'plain text error'
73
- assert str(exception) == 'Error: plain text error, Code: 500 , X-global-transaction-id: xx'