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.
- frogml/__init__.py +1 -1
- frogml/core/clients/batch_job_management/client.py +269 -257
- frogml/core/clients/batch_job_management/executions_config.py +10 -3
- frogml/core/clients/build_orchestrator/build_model_request_getter.py +7 -1
- frogml/core/clients/build_orchestrator/client.py +108 -67
- frogml/core/clients/build_orchestrator/internal_client.py +42 -38
- frogml/core/clients/feature_store/management_client.py +58 -39
- frogml/core/clients/feature_store/operator_client.py +6 -4
- frogml/core/clients/model_group_management/client.py +5 -2
- frogml/core/clients/model_management/client.py +25 -8
- frogml/core/clients/model_version_manager/build_model_version_dto.py +4 -1
- frogml/core/clients/model_version_manager/client.py +67 -68
- frogml/core/exceptions/__init__.py +20 -2
- frogml/core/exceptions/frogml_exception.py +35 -5
- frogml/core/exceptions/frogml_general_build_exception.py +19 -11
- frogml/core/exceptions/frogml_grpc_address_exception.py +15 -4
- frogml/core/exceptions/frogml_http_exception.py +3 -1
- frogml/core/exceptions/frogml_login_exception.py +16 -5
- frogml/core/exceptions/frogml_not_found_exception.py +16 -3
- frogml/core/exceptions/frogml_remote_build_failed.py +1 -1
- frogml/core/exceptions/frogml_token_exception.py +17 -5
- frogml/core/exceptions/grpc_status_mapping.py +43 -0
- frogml/core/inner/build_logic/phases/phase_010_fetch_model/fetch_strategy_manager/strategy/git/git_strategy.py +10 -2
- frogml/core/inner/build_logic/phases/phase_010_fetch_model/pre_fetch_validation_step.py +3 -2
- frogml/core/inner/build_logic/phases/phase_020_remote_register_frogml_build/upload_step.py +13 -10
- frogml/core/inner/build_logic/run_handlers/programmatic_phase_run_handler.py +8 -3
- frogml/core/inner/build_logic/tools/files.py +1 -2
- frogml/core/inner/model_loggers_utils.py +21 -8
- frogml/core/inner/tool/auth/auth_client.py +1 -1
- frogml/core/inner/tool/grpc/grpc_try_wrapping.py +51 -72
- frogml/core/inner/tool/protobuf_factory.py +8 -2
- frogml/sdk/frogml_client/client.py +29 -10
- frogml/sdk/model/adapters/input_adapters/numpy_input_adapter.py +6 -1
- frogml/sdk/model/adapters/output_adapters/numpy_output_adapter.py +4 -1
- frogml/sdk/model/decorators/api.py +6 -1
- frogml/sdk/model/tools/adapters/output.py +6 -2
- frogml/sdk/model_version/catboost/__init__.py +4 -1
- frogml/sdk/model_version/huggingface/__init__.py +4 -1
- frogml/sdk/model_version/model_loggers/catboost_model_version_manager.py +4 -1
- frogml/sdk/model_version/model_loggers/huggingface_model_version_manager.py +10 -2
- frogml/sdk/model_version/model_loggers/onnx_model_version_manager.py +4 -1
- frogml/sdk/model_version/model_loggers/pytorch_model_version_manager.py +4 -1
- frogml/sdk/model_version/model_loggers/scikit_learn_model_version_manager.py +4 -1
- frogml/sdk/model_version/onnx/__init__.py +4 -1
- frogml/sdk/model_version/pytorch/__init__.py +4 -1
- frogml/sdk/model_version/scikit_learn/__init__.py +4 -1
- frogml/sdk/model_version/utils/jml/customer_client.py +1 -1
- frogml/sdk/model_version/utils/storage.py +4 -1
- frogml/sdk/model_version/utils/validations.py +10 -2
- {frogml-1.2.49.dist-info → frogml-2.0.0.dist-info}/METADATA +1 -1
- {frogml-1.2.49.dist-info → frogml-2.0.0.dist-info}/RECORD +58 -61
- frogml_services_mock/mocks/batch_job_manager_service.py +11 -9
- frogml_services_mock/mocks/build_orchestrator_service_api.py +4 -0
- frogml_services_mock/mocks/ecosystem_service_api.py +1 -2
- frogml_services_mock/mocks/model_group_management_service.py +20 -9
- frogml_services_mock/mocks/model_version_manager_service.py +3 -1
- frogml_services_mock/mocks/project_manager_service.py +6 -2
- frogml/core/exceptions/frogml_decode_exception.py +0 -7
- frogml/core/exceptions/frogml_external_exception.py +0 -11
- frogml/core/exceptions/frogml_load_model_failed_exception.py +0 -10
- frogml/core/exceptions/quiet_error.py +0 -22
- {frogml-1.2.49.dist-info → frogml-2.0.0.dist-info}/WHEEL +0 -0
|
@@ -1,7 +1,37 @@
|
|
|
1
|
-
from
|
|
1
|
+
from http import HTTPStatus
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class FrogmlException(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
2
|
-
|
|
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
|
-
|
|
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
|
-
|
|
13
|
-
|
|
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
|
|
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
|
-
|
|
9
|
-
|
|
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
|
|
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
|
|
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,
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
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
|
-
|
|
6
|
-
|
|
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,7 +1,19 @@
|
|
|
1
|
-
from
|
|
1
|
+
from http import HTTPStatus
|
|
2
2
|
|
|
3
|
+
from frogml.core.exceptions.frogml_exception import FrogmlException
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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(
|
|
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(
|
|
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.
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
307
|
-
raise
|
|
308
|
-
f"
|
|
309
|
-
|
|
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(
|
|
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,
|
|
@@ -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(
|
|
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(
|
|
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
|
|
98
|
+
if http_response.status_code not in {HTTPStatus.OK, HTTPStatus.CREATED}:
|
|
90
99
|
raise FrogmlException(
|
|
91
|
-
f"Failed to upload data.
|
|
92
|
-
|
|
93
|
-
|
|
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(
|
|
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
|
+
)
|