frogml 1.2.49__py3-none-any.whl → 2.0.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 (62) hide show
  1. frogml/__init__.py +1 -1
  2. frogml/core/clients/batch_job_management/client.py +269 -257
  3. frogml/core/clients/batch_job_management/executions_config.py +10 -3
  4. frogml/core/clients/build_orchestrator/build_model_request_getter.py +7 -1
  5. frogml/core/clients/build_orchestrator/client.py +108 -67
  6. frogml/core/clients/build_orchestrator/internal_client.py +42 -38
  7. frogml/core/clients/feature_store/management_client.py +58 -39
  8. frogml/core/clients/feature_store/operator_client.py +6 -4
  9. frogml/core/clients/model_group_management/client.py +5 -2
  10. frogml/core/clients/model_management/client.py +25 -8
  11. frogml/core/clients/model_version_manager/build_model_version_dto.py +4 -1
  12. frogml/core/clients/model_version_manager/client.py +67 -68
  13. frogml/core/exceptions/__init__.py +20 -2
  14. frogml/core/exceptions/frogml_exception.py +35 -5
  15. frogml/core/exceptions/frogml_general_build_exception.py +19 -11
  16. frogml/core/exceptions/frogml_grpc_address_exception.py +15 -4
  17. frogml/core/exceptions/frogml_http_exception.py +3 -1
  18. frogml/core/exceptions/frogml_login_exception.py +16 -5
  19. frogml/core/exceptions/frogml_not_found_exception.py +16 -3
  20. frogml/core/exceptions/frogml_remote_build_failed.py +1 -1
  21. frogml/core/exceptions/frogml_token_exception.py +17 -5
  22. frogml/core/exceptions/grpc_status_mapping.py +43 -0
  23. frogml/core/inner/build_logic/phases/phase_010_fetch_model/fetch_strategy_manager/strategy/git/git_strategy.py +10 -2
  24. frogml/core/inner/build_logic/phases/phase_010_fetch_model/pre_fetch_validation_step.py +3 -2
  25. frogml/core/inner/build_logic/phases/phase_020_remote_register_frogml_build/upload_step.py +13 -10
  26. frogml/core/inner/build_logic/run_handlers/programmatic_phase_run_handler.py +8 -3
  27. frogml/core/inner/build_logic/tools/files.py +1 -2
  28. frogml/core/inner/model_loggers_utils.py +21 -8
  29. frogml/core/inner/tool/auth/auth_client.py +1 -1
  30. frogml/core/inner/tool/grpc/grpc_try_wrapping.py +51 -72
  31. frogml/core/inner/tool/protobuf_factory.py +8 -2
  32. frogml/sdk/frogml_client/client.py +29 -10
  33. frogml/sdk/model/adapters/input_adapters/numpy_input_adapter.py +6 -1
  34. frogml/sdk/model/adapters/output_adapters/numpy_output_adapter.py +4 -1
  35. frogml/sdk/model/decorators/api.py +6 -1
  36. frogml/sdk/model/tools/adapters/output.py +6 -2
  37. frogml/sdk/model_version/catboost/__init__.py +4 -1
  38. frogml/sdk/model_version/huggingface/__init__.py +4 -1
  39. frogml/sdk/model_version/model_loggers/catboost_model_version_manager.py +4 -1
  40. frogml/sdk/model_version/model_loggers/huggingface_model_version_manager.py +10 -2
  41. frogml/sdk/model_version/model_loggers/onnx_model_version_manager.py +4 -1
  42. frogml/sdk/model_version/model_loggers/pytorch_model_version_manager.py +4 -1
  43. frogml/sdk/model_version/model_loggers/scikit_learn_model_version_manager.py +4 -1
  44. frogml/sdk/model_version/onnx/__init__.py +4 -1
  45. frogml/sdk/model_version/pytorch/__init__.py +4 -1
  46. frogml/sdk/model_version/scikit_learn/__init__.py +4 -1
  47. frogml/sdk/model_version/utils/jml/customer_client.py +1 -1
  48. frogml/sdk/model_version/utils/storage.py +4 -1
  49. frogml/sdk/model_version/utils/validations.py +10 -2
  50. {frogml-1.2.49.dist-info → frogml-2.0.0.dist-info}/METADATA +1 -1
  51. {frogml-1.2.49.dist-info → frogml-2.0.0.dist-info}/RECORD +58 -61
  52. frogml_services_mock/mocks/batch_job_manager_service.py +11 -9
  53. frogml_services_mock/mocks/build_orchestrator_service_api.py +4 -0
  54. frogml_services_mock/mocks/ecosystem_service_api.py +1 -2
  55. frogml_services_mock/mocks/model_group_management_service.py +20 -9
  56. frogml_services_mock/mocks/model_version_manager_service.py +3 -1
  57. frogml_services_mock/mocks/project_manager_service.py +6 -2
  58. frogml/core/exceptions/frogml_decode_exception.py +0 -7
  59. frogml/core/exceptions/frogml_external_exception.py +0 -11
  60. frogml/core/exceptions/frogml_load_model_failed_exception.py +0 -10
  61. frogml/core/exceptions/quiet_error.py +0 -22
  62. {frogml-1.2.49.dist-info → frogml-2.0.0.dist-info}/WHEEL +0 -0
@@ -1,7 +1,37 @@
1
- from .quiet_error import QuietError
1
+ from http import HTTPStatus
2
2
 
3
3
 
4
- class FrogmlException(QuietError):
5
- def __init__(self, message, status_code=None):
6
- self.message = message
7
- self.status_code = status_code
4
+ class FrogmlException(Exception):
5
+ """
6
+ Base exception for FrogML SDK errors.
7
+
8
+ Displays errors in JF CLI format without tracebacks:
9
+ Error: {operation}
10
+ -----------------------------
11
+ Status: {status_code} {status_phrase}
12
+ Message: {error_message}
13
+ """
14
+
15
+ def __init__(
16
+ self,
17
+ error_message: str,
18
+ status_code: int = HTTPStatus.INTERNAL_SERVER_ERROR,
19
+ operation: str = "FrogML Operation",
20
+ ) -> None:
21
+ super().__init__(error_message)
22
+ self.error_message: str = error_message
23
+ self.status_code: int = status_code
24
+ self.operation: str = operation
25
+
26
+ def __str__(self) -> str:
27
+ try:
28
+ status_text = f"{self.status_code} {HTTPStatus(self.status_code).phrase}"
29
+ except ValueError:
30
+ status_text = str(self.status_code)
31
+ lines = [
32
+ f"Error: {self.operation.title()} Failed",
33
+ "-----------------------------",
34
+ f"Status: {status_text}",
35
+ f"Message: {self.error_message}",
36
+ ]
37
+ return "\n".join(lines)
@@ -1,13 +1,21 @@
1
- class FrogmlGeneralBuildException(Exception):
2
- def __init__(self, message: str, src_exception: Exception = None):
3
- self._message = message
4
- self._exception_msg = str(src_exception) if src_exception else ""
1
+ from http import HTTPStatus
2
+ from typing import Optional
5
3
 
6
- @property
7
- def message(self) -> str:
8
- msg = f"""Message: {self._message}
9
- Exception message: {self._exception_msg}"""
10
- return msg
4
+ from frogml.core.exceptions.frogml_exception import FrogmlException
11
5
 
12
- def __str__(self):
13
- return self.message
6
+
7
+ class FrogmlGeneralBuildException(FrogmlException):
8
+ def __init__(
9
+ self,
10
+ error_message: str,
11
+ src_exception: Optional[Exception] = None,
12
+ status_code: int = HTTPStatus.INTERNAL_SERVER_ERROR,
13
+ ) -> None:
14
+ full_message: str = error_message
15
+ if src_exception:
16
+ full_message = f"{error_message}: {src_exception}"
17
+ super().__init__(
18
+ error_message=full_message,
19
+ status_code=status_code,
20
+ operation="Build",
21
+ )
@@ -1,9 +1,20 @@
1
- from typing import Union
2
- from urllib.parse import ParseResult
1
+ from http import HTTPStatus
3
2
 
4
3
  from frogml.core.exceptions import FrogmlException
5
4
 
6
5
 
7
6
  class FrogmlGrpcAddressException(FrogmlException):
8
- def __init__(self, details: str, grpc_address: Union[str, ParseResult]):
9
- self.message = f"Not a valid gRPC address: '{grpc_address}'. Details: {details}"
7
+ """Exception for invalid gRPC address configuration."""
8
+
9
+ def __init__(
10
+ self,
11
+ details: str,
12
+ grpc_address: str,
13
+ status_code: int = HTTPStatus.BAD_REQUEST,
14
+ operation: str = "Configure gRPC Address",
15
+ ) -> None:
16
+ super().__init__(
17
+ error_message=f"Not a valid gRPC address: '{grpc_address}'. Details: {details}",
18
+ status_code=status_code,
19
+ operation=operation,
20
+ )
@@ -3,7 +3,9 @@ from typing import Dict, Optional, Union
3
3
  try:
4
4
  from bentoml.exceptions import InferenceException
5
5
  except ImportError:
6
- from .frogml_mock_http_exception import MockHttpException as InferenceException
6
+ from frogml.core.exceptions.frogml_mock_http_exception import (
7
+ MockHttpException as InferenceException,
8
+ )
7
9
 
8
10
 
9
11
  class FrogmlHTTPException(InferenceException):
@@ -1,8 +1,19 @@
1
- from .quiet_error import QuietError
1
+ from http import HTTPStatus
2
2
 
3
+ from frogml.core.exceptions.frogml_exception import FrogmlException
4
+
5
+
6
+ class FrogmlLoginException(FrogmlException):
7
+ """Exception for login failures."""
3
8
 
4
- class FrogmlLoginException(QuietError):
5
9
  def __init__(
6
- self, message="Failed to login to Frogml. Please check your credentials"
7
- ):
8
- self.message = message
10
+ self,
11
+ error_message: str = "Failed to login to FrogML. Please check your credentials",
12
+ status_code: int = HTTPStatus.UNAUTHORIZED,
13
+ operation: str = "Login",
14
+ ) -> None:
15
+ super().__init__(
16
+ error_message=error_message,
17
+ status_code=status_code,
18
+ operation=operation,
19
+ )
@@ -1,6 +1,19 @@
1
- from .frogml_exception import FrogmlException
1
+ from http import HTTPStatus
2
+
3
+ from frogml.core.exceptions.frogml_exception import FrogmlException
2
4
 
3
5
 
4
6
  class FrogmlNotFoundException(FrogmlException):
5
- def __init__(self, message):
6
- self.message = message
7
+ """Exception for resource not found errors."""
8
+
9
+ def __init__(
10
+ self,
11
+ error_message: str,
12
+ status_code: int = HTTPStatus.NOT_FOUND,
13
+ operation: str = "FrogML Operation",
14
+ ) -> None:
15
+ super().__init__(
16
+ error_message=error_message,
17
+ status_code=status_code,
18
+ operation=operation,
19
+ )
@@ -1,4 +1,4 @@
1
- from .frogml_suggestion_exception import FrogmlSuggestionException
1
+ from frogml.core.exceptions.frogml_suggestion_exception import FrogmlSuggestionException
2
2
 
3
3
 
4
4
  class FrogmlRemoteBuildFailedException(FrogmlSuggestionException):
@@ -1,7 +1,19 @@
1
- from .quiet_error import QuietError
1
+ from http import HTTPStatus
2
2
 
3
+ from frogml.core.exceptions.frogml_exception import FrogmlException
3
4
 
4
- class FrogMLTokenException(QuietError):
5
- def __init__(self, message: str):
6
- super().__init__(message)
7
- self.message: str = message
5
+
6
+ class FrogMLTokenException(FrogmlException):
7
+ """Exception for token-related errors."""
8
+
9
+ def __init__(
10
+ self,
11
+ error_message: str,
12
+ status_code: int = HTTPStatus.UNAUTHORIZED,
13
+ operation: str = "Authenticate",
14
+ ) -> None:
15
+ super().__init__(
16
+ error_message=error_message,
17
+ status_code=status_code,
18
+ operation=operation,
19
+ )
@@ -0,0 +1,43 @@
1
+ """Mapping between gRPC status codes and HTTP status codes."""
2
+
3
+ from http import HTTPStatus
4
+ from typing import Final, Optional
5
+
6
+ import grpc
7
+
8
+ # Standard gRPC to HTTP status code mapping
9
+ # Reference: https://cloud.google.com/apis/design/errors#handling_errors
10
+ GRPC_TO_HTTP_STATUS: Final[dict[grpc.StatusCode, int]] = {
11
+ grpc.StatusCode.OK: HTTPStatus.OK,
12
+ grpc.StatusCode.CANCELLED: 499, # Client Closed Request (non-standard)
13
+ grpc.StatusCode.UNKNOWN: HTTPStatus.INTERNAL_SERVER_ERROR,
14
+ grpc.StatusCode.INVALID_ARGUMENT: HTTPStatus.BAD_REQUEST,
15
+ grpc.StatusCode.DEADLINE_EXCEEDED: HTTPStatus.GATEWAY_TIMEOUT,
16
+ grpc.StatusCode.NOT_FOUND: HTTPStatus.NOT_FOUND,
17
+ grpc.StatusCode.ALREADY_EXISTS: HTTPStatus.CONFLICT,
18
+ grpc.StatusCode.PERMISSION_DENIED: HTTPStatus.FORBIDDEN,
19
+ grpc.StatusCode.RESOURCE_EXHAUSTED: HTTPStatus.TOO_MANY_REQUESTS,
20
+ grpc.StatusCode.FAILED_PRECONDITION: HTTPStatus.BAD_REQUEST,
21
+ grpc.StatusCode.ABORTED: HTTPStatus.CONFLICT,
22
+ grpc.StatusCode.OUT_OF_RANGE: HTTPStatus.BAD_REQUEST,
23
+ grpc.StatusCode.UNIMPLEMENTED: HTTPStatus.NOT_IMPLEMENTED,
24
+ grpc.StatusCode.INTERNAL: HTTPStatus.INTERNAL_SERVER_ERROR,
25
+ grpc.StatusCode.UNAVAILABLE: HTTPStatus.SERVICE_UNAVAILABLE,
26
+ grpc.StatusCode.DATA_LOSS: HTTPStatus.INTERNAL_SERVER_ERROR,
27
+ grpc.StatusCode.UNAUTHENTICATED: HTTPStatus.UNAUTHORIZED,
28
+ }
29
+
30
+
31
+ def grpc_to_http_status(grpc_code: Optional[grpc.StatusCode]) -> int:
32
+ """
33
+ Convert gRPC status code to HTTP status code.
34
+
35
+ Args:
36
+ grpc_code: The gRPC status code to convert.
37
+
38
+ Returns:
39
+ The corresponding HTTP status code. Defaults to 500 if grpc_code is None or unknown.
40
+ """
41
+ if grpc_code is None:
42
+ return HTTPStatus.INTERNAL_SERVER_ERROR
43
+ return GRPC_TO_HTTP_STATUS.get(grpc_code, HTTPStatus.INTERNAL_SERVER_ERROR)
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+ from http import HTTPStatus
2
3
 
3
4
  import os
4
5
  import shutil
@@ -119,7 +120,11 @@ def split_git_url_and_subdirectory(uri):
119
120
  subdirectory = uri[uri.find("#") + 1 :]
120
121
  parsed_uri = uri[: uri.find("#")]
121
122
  if subdirectory and "." in subdirectory:
122
- raise FrogmlException("'.' is not allowed in project subdirectory paths.")
123
+ raise FrogmlException(
124
+ error_message="'.' is not allowed in project subdirectory paths",
125
+ status_code=HTTPStatus.BAD_REQUEST,
126
+ operation="Validate Build Git Path",
127
+ )
123
128
  return parsed_uri, subdirectory
124
129
 
125
130
 
@@ -148,7 +153,10 @@ def ssh_key_context(git_ssh_key: str):
148
153
  try:
149
154
  os.remove(ssh_key_path)
150
155
  except OSError as e:
151
- FrogmlException(f"Failed to delete ssh key temp key file: {e}")
156
+ FrogmlException(
157
+ error_message=f"Failed to delete ssh key temp key file: {e}",
158
+ operation="Build Cleanup",
159
+ )
152
160
 
153
161
 
154
162
  def make_ssh_key_file(git_ssh_key: str) -> str:
@@ -241,10 +241,11 @@ class PreFetchValidationStep(Step):
241
241
  )
242
242
  if not isinstance(self.config.pre_built_model, base_model_class):
243
243
  raise FrogmlException(
244
- self.INVALID_FROGML_MODEL_MSG_FORMAT.format(
244
+ error_message=self.INVALID_FROGML_MODEL_MSG_FORMAT.format(
245
245
  expected_class=base_model_class.__name__,
246
246
  passed_class=self.config.pre_built_model.__class__,
247
- )
247
+ ),
248
+ operation="Validate Model",
248
249
  )
249
250
 
250
251
  def validate_gcp_service_account_secret(self):
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import re
4
+ from http import HTTPStatus
4
5
  from pathlib import Path
5
6
  from typing import Optional
6
7
 
@@ -44,7 +45,7 @@ _MAX_FILE_SIZE_BYTES = 10000000
44
45
 
45
46
  def should_retry(frogml_exception: FrogmlException) -> bool:
46
47
  # when Got 403 from Jfrog it means that the reposity doesn't exist. It may happen when in the first build in the project
47
- return "403" in str(frogml_exception.message)
48
+ return "403" in str(frogml_exception.error_message)
48
49
 
49
50
 
50
51
  class UploadStep(Step):
@@ -67,7 +68,9 @@ class UploadStep(Step):
67
68
  for tag, upload_info in upload_urls_response.upload_url_infos.items():
68
69
  file: Optional[Path] = files_by_tags.get(tag, None)
69
70
  if file is None:
70
- raise FrogmlGeneralBuildException(f"No file found for tag {tag}")
71
+ raise FrogmlGeneralBuildException(
72
+ error_message=f"No file found for tag {tag}"
73
+ )
71
74
 
72
75
  self.upload_file(
73
76
  file=file,
@@ -111,7 +114,7 @@ class UploadStep(Step):
111
114
 
112
115
  if tags_with_no_url:
113
116
  raise FrogmlGeneralBuildException(
114
- f"Missing upload url for tags: {tags_with_no_url!r}"
117
+ error_message=f"Missing upload url for tags: {tags_with_no_url!r}"
115
118
  )
116
119
 
117
120
  expected_keys: set[str] = set(files_by_tags.keys())
@@ -119,7 +122,7 @@ class UploadStep(Step):
119
122
 
120
123
  if expected_keys != actual_keys:
121
124
  raise FrogmlGeneralBuildException(
122
- f"Mismatch between requested tags {expected_keys} and response tags {actual_keys}"
125
+ error_message=f"Mismatch between requested tags {expected_keys} and response tags {actual_keys}"
123
126
  )
124
127
 
125
128
  return upload_urls_response
@@ -246,7 +249,7 @@ class UploadStep(Step):
246
249
  return pre_signed_url_response
247
250
  except FrogmlException as e:
248
251
  raise FrogmlGeneralBuildException(
249
- message="Unable to get pre-signed url for uploading model",
252
+ error_message="Unable to get pre-signed url for uploading model",
250
253
  src_exception=e,
251
254
  )
252
255
 
@@ -272,7 +275,7 @@ class UploadStep(Step):
272
275
  )
273
276
  except Exception as e:
274
277
  raise FrogmlGeneralBuildException(
275
- message="Fail uploading model to remote storage.",
278
+ error_message="Failed uploading model to remote storage",
276
279
  src_exception=e,
277
280
  )
278
281
 
@@ -303,8 +306,8 @@ class UploadStep(Step):
303
306
  headers=headers,
304
307
  )
305
308
 
306
- if http_response.status_code not in [200, 201]:
307
- raise FrogmlException(
308
- f"Status: [{http_response.status_code}], "
309
- f"reason: [{http_response.reason}]"
309
+ if http_response.status_code not in {HTTPStatus.OK, HTTPStatus.CREATED}:
310
+ raise FrogmlGeneralBuildException(
311
+ error_message=f"Failed to upload file to remote storage: {http_response.reason}",
312
+ status_code=http_response.status_code,
310
313
  )
@@ -1,5 +1,6 @@
1
1
  from contextlib import contextmanager
2
2
  from logging import Logger
3
+ from http import HTTPStatus
3
4
 
4
5
  from frogml.core.exceptions import FrogmlException
5
6
  from frogml.core.inner.build_logic.build_loggers.trigger_build_logger import (
@@ -64,13 +65,17 @@ class ProgrammaticPhaseRunHandler(PhaseRunHandler):
64
65
  )
65
66
  )
66
67
  self._report_failure(build_phase, duration_in_seconds)
67
- raise FrogmlException(str(ex))
68
+ raise FrogmlException(error_message=str(ex))
68
69
 
69
70
  def handle_keyboard_interrupt(
70
71
  self, build_id: str, build_phase: BuildPhase, duration_in_seconds: int
71
72
  ):
72
73
  self._report_failure(build_phase, duration_in_seconds)
73
- raise FrogmlException("KeyboardInterrupt")
74
+ raise FrogmlException(
75
+ error_message="Build interrupted by user",
76
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
77
+ operation="Run Build Phase",
78
+ )
74
79
 
75
80
  def handle_pipeline_exception(
76
81
  self,
@@ -80,7 +85,7 @@ class ProgrammaticPhaseRunHandler(PhaseRunHandler):
80
85
  duration_in_seconds: int,
81
86
  ):
82
87
  self._report_failure(build_phase, duration_in_seconds)
83
- raise FrogmlException(str(ex))
88
+ raise FrogmlException(error_message=str(ex))
84
89
 
85
90
  def handle_pipeline_quiet_exception(
86
91
  self,
@@ -185,8 +185,7 @@ def zip_model(
185
185
 
186
186
  except Exception as e:
187
187
  raise FrogmlGeneralBuildException(
188
- message="Unable to zip model before upload",
189
- src_exception=e,
188
+ error_message="Unable to zip model before upload", src_exception=e
190
189
  )
191
190
 
192
191
 
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  import re
3
3
  from typing import Optional
4
+ from http import HTTPStatus
4
5
 
5
6
  import requests
6
7
 
@@ -42,12 +43,20 @@ def validate_model(model_id: str) -> str:
42
43
  if not model_id:
43
44
  model_id = fetch_model_id()
44
45
  if not model_id:
45
- raise FrogmlException("Failed to determined model ID.")
46
+ raise FrogmlException(
47
+ error_message="Failed to determine model ID",
48
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
49
+ operation="Get Model ID",
50
+ )
46
51
 
47
52
  try:
48
53
  ModelsManagementClient().get_model(model_id=model_id)
49
54
  except Exception:
50
- raise FrogmlException("Failed to find model.")
55
+ raise FrogmlException(
56
+ error_message="Failed to find model",
57
+ status_code=HTTPStatus.NOT_FOUND,
58
+ operation="Find Model",
59
+ )
51
60
 
52
61
  return model_id
53
62
 
@@ -80,17 +89,21 @@ def upload_data(
80
89
  """
81
90
  try:
82
91
  headers["Content-Type"] = content_type
83
- http_response = requests.put( # nosec B113
92
+ http_response: requests.Response = requests.put( # nosec B113
84
93
  upload_url,
85
94
  data=data,
86
95
  headers=headers,
87
96
  )
88
97
 
89
- if http_response.status_code not in [200, 201]:
98
+ if http_response.status_code not in {HTTPStatus.OK, HTTPStatus.CREATED}:
90
99
  raise FrogmlException(
91
- f"Failed to upload data. "
92
- f"Status: [{http_response.status_code}], "
93
- f"reason: [{http_response.reason}]"
100
+ error_message=f"Failed to upload data: {http_response.reason}",
101
+ status_code=http_response.status_code,
102
+ operation="Upload Model Data",
94
103
  )
95
104
  except Exception as e:
96
- raise FrogmlException(f"Failed to upload data. Error is {e}")
105
+ raise FrogmlException(
106
+ error_message=f"Failed to upload data: {e}",
107
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
108
+ operation="Upload Model Data",
109
+ )
@@ -104,7 +104,7 @@ class FrogMLAuthClient:
104
104
 
105
105
  else:
106
106
  raise FrogMLTokenException(
107
- message="Token not found in the authentication configurations."
107
+ error_message="Token not found in the authentication configurations."
108
108
  )
109
109
 
110
110
  return self.__token