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,34 +1,32 @@
1
1
  import functools
2
2
  import inspect
3
+ from http import HTTPStatus
3
4
  from inspect import BoundArguments, Signature
4
5
  from typing import Any, Callable, Optional
5
6
 
6
7
  import grpc
7
8
  from frogml.core.exceptions import FrogmlException
9
+ from frogml.core.exceptions.grpc_status_mapping import grpc_to_http_status
8
10
  from frogml.storage.logging import logger
9
11
 
10
12
 
11
13
  def grpc_try_catch_wrapper(
12
- exception_message: str,
13
- reraise_non_grpc_error_original_exception: Optional[bool] = False,
14
+ error_message: str, operation: str = "FrogML Operation"
14
15
  ) -> Callable:
15
16
  """A decorator for handling exceptions in client methods.
16
17
 
17
18
  This decorator wraps a function, catching any `grpc.RpcError` or other
18
- `Exception`. it re-raises them as a `FrogmlException`. The error message can be a
19
- static string or a template formatted with the decorated function's
20
- runtime arguments.
19
+ `Exception` and re-raises them as a `FrogmlException` with consistent formatting.
21
20
 
22
21
  Parameters
23
22
  ----------
24
- exception_message : str
23
+ error_message : str
25
24
  The error message template. This can be a static string or a format
26
25
  string using placeholders that match the decorated function's
27
26
  parameter names (e.g., "Failed on item {item_id}").
28
- reraise_non_grpc_error_original_exception : bool, optional
29
- If `True`, any exception that is *not* a `grpc.RpcError` will be
30
- re-raised in its original form. If `False` (the default), all
31
- exceptions are wrapped in `FrogmlException`.
27
+ operation : str, optional
28
+ The operation name for error display (e.g., "Delete Model").
29
+ Defaults to "FrogML Operation".
32
30
 
33
31
  Returns
34
32
  -------
@@ -38,40 +36,16 @@ def grpc_try_catch_wrapper(
38
36
  Raises
39
37
  ------
40
38
  FrogmlException
41
- Raised when the decorated function encounters any exception, unless
42
- `reraise_non_grpc_error_original_exception` is `True` and the error
43
- is not a `grpc.RpcError`. The new exception's message is formatted
44
- and includes details from the original error.
45
- Exception
46
- The original non-gRPC exception is re-raised if
47
- `reraise_non_grpc_error_original_exception` is set to `True`.
39
+ Raised when the decorated function encounters any exception.
48
40
 
49
41
  Usage
50
42
  -----
51
- The decorator can be used with static strings and formatted strings
52
-
53
- **1. Formatted Error Messages**
54
-
55
- Use placeholders matching the function's parameter names to create
56
- context-specific error messages.
57
-
58
- @grpc_try_catch_wrapper("Failed to delete version {version_number} for FeatureSet {featureset_name}")
43
+ @grpc_try_catch_wrapper(
44
+ error_message="Failed to delete version {version_number} for FeatureSet {featureset_name}",
45
+ operation="Delete FeatureSet Version"
46
+ )
59
47
  def delete_featureset_version(self, featureset_name: str, version_number: int):
60
48
  # ... gRPC call ...
61
-
62
- If this function fails with a gRPC error, a `FrogmlException` is raised with a message like:
63
- `"Failed to delete version 2 for FeatureSet customer_churn - <original gRPC error code> - <original gRPC error details>."`
64
-
65
- **2. Static Error Messages**
66
-
67
- When no dynamic context is needed, a simple string is sufficient.
68
-
69
- @grpc_try_catch_wrapper("Failed to retrieve featuresets mapping")
70
- def get_featuresets_mapping(self):
71
- # ... gRPC call ...
72
-
73
- If this fails, the `FrogmlException` message will be:
74
- `"Failed to retrieve featuresets mapping - <original gRPC error code> - <original gRPC error details>."`
75
49
  """
76
50
 
77
51
  def decorator(function: Callable):
@@ -79,51 +53,56 @@ def grpc_try_catch_wrapper(
79
53
  def _inner_wrapper(*args, **kwargs):
80
54
  try:
81
55
  return function(*args, **kwargs)
82
- except grpc.RpcError as e:
83
- error_message: str = __get_error_msg(
84
- exception_message=exception_message, e=e
85
- )
86
-
87
- formatted_message: str = __get_formatted_error_message(
88
- exception_message=error_message,
89
- function=function,
90
- args=args,
91
- kwargs=kwargs,
92
- )
93
-
94
- raise FrogmlException(formatted_message) from e
95
-
96
56
  except Exception as e:
97
- if reraise_non_grpc_error_original_exception:
98
- raise e
99
-
100
- formatted_message = __get_formatted_error_message(
101
- exception_message=exception_message,
102
- function=function,
103
- args=args,
104
- kwargs=kwargs,
105
- )
106
- raise FrogmlException(f"{formatted_message}. Error is: {e}.") from e
57
+ raise _build_exception(
58
+ e, error_message, operation, function, args, kwargs
59
+ ) from e
107
60
 
108
61
  return _inner_wrapper
109
62
 
110
63
  return decorator
111
64
 
112
65
 
113
- def __get_error_msg(exception_message: str, e: grpc.RpcError) -> str:
114
- err_msg: str = (
115
- f"{exception_message} - {e.code() if hasattr(e, 'code') else 'UNKNOWN'}"
66
+ def _build_exception(
67
+ e: Exception,
68
+ error_message: str,
69
+ operation: str,
70
+ function: Callable,
71
+ args: tuple,
72
+ kwargs: dict,
73
+ ) -> FrogmlException:
74
+ """Build a FrogmlException from the caught exception."""
75
+ if isinstance(e, grpc.RpcError):
76
+ message: str = __get_error_msg(error_message, e)
77
+ grpc_code: Optional[grpc.StatusCode] = e.code() if hasattr(e, "code") else None
78
+ status_code: int = grpc_to_http_status(grpc_code)
79
+ else:
80
+ exception_type: str = type(e).__name__ # e.g., "ValueError", "TypeError"
81
+ message = f"{error_message}: {exception_type}: {e}"
82
+ status_code = HTTPStatus.INTERNAL_SERVER_ERROR
83
+
84
+ formatted_message: str = __get_formatted_error_message(
85
+ message, function, args, kwargs
86
+ )
87
+ return FrogmlException(
88
+ error_message=formatted_message,
89
+ status_code=status_code,
90
+ operation=operation,
116
91
  )
92
+
93
+
94
+ def __get_error_msg(error_message: str, e: grpc.RpcError) -> str:
95
+ err_msg: str = error_message
117
96
  if hasattr(e, "details") and e.details() is not None:
118
- err_msg: str = f"{err_msg} - {e.details()}"
97
+ err_msg = f"{err_msg}: {e.details()}"
119
98
  elif hasattr(e, "debug_error_string"):
120
- err_msg: str = f"{err_msg} - {e.debug_error_string()}"
99
+ err_msg = f"{err_msg}: {e.debug_error_string()}"
121
100
  logger.debug(f"{err_msg}: {e}")
122
101
  return err_msg
123
102
 
124
103
 
125
104
  def __get_formatted_error_message(
126
- exception_message: str, function: Callable, args: tuple[Any], kwargs: dict[str, Any]
105
+ error_message: str, function: Callable, args: tuple[Any], kwargs: dict[str, Any]
127
106
  ) -> str:
128
107
  """Formats an error message string with the runtime arguments of a function.
129
108
 
@@ -131,7 +110,7 @@ def __get_formatted_error_message(
131
110
  to their parameter names, then uses them to format the message string.
132
111
 
133
112
  Args:
134
- exception_message (str): The error message template with placeholders.
113
+ error_message (str): The error message template with placeholders.
135
114
  function (Callable): The decorated function.
136
115
  args (tuple[Any]): The positional arguments passed to the function.
137
116
  kwargs (dict[str, Any]): The keyword arguments passed to the function.
@@ -144,7 +123,7 @@ def __get_formatted_error_message(
144
123
  bound_args: BoundArguments = sig.bind(*args, **kwargs)
145
124
  bound_args.apply_defaults()
146
125
 
147
- return exception_message.format(**bound_args.arguments)
126
+ return error_message.format(**bound_args.arguments)
148
127
  except (ValueError, KeyError, TypeError):
149
128
  # Fallback if formatting fails (e.g., missing key in template)
150
- return exception_message
129
+ return error_message
@@ -1,4 +1,5 @@
1
1
  from frogml.core.exceptions import FrogmlException
2
+ from http import HTTPStatus
2
3
 
3
4
 
4
5
  def protobuf_factory(
@@ -12,13 +13,18 @@ def protobuf_factory(
12
13
  unrecognized_fields = included_fields.difference(all_field_names)
13
14
  if unrecognized_fields:
14
15
  raise FrogmlException(
15
- f"Unknown fields were included: {list(unrecognized_fields)}"
16
+ error_message=f"Unknown fields were included: {list(unrecognized_fields)}",
17
+ operation="Convert to Protobuf",
16
18
  )
17
19
  return included_fields.difference(excluded_fields)
18
20
 
19
21
  def protofy_decorator(cls):
20
22
  if not hasattr(cls, "__dataclass_fields__"):
21
- raise FrogmlException("Protofy must receive a dataclass")
23
+ raise FrogmlException(
24
+ error_message="Protofy must receive a dataclass",
25
+ status_code=HTTPStatus.BAD_REQUEST,
26
+ operation="Convert to Protobuf",
27
+ )
22
28
 
23
29
  fields_mapping = mapping if mapping else {}
24
30
  final_field_names = get_final_field_names(cls)
@@ -3,6 +3,7 @@ from functools import lru_cache
3
3
  from pathlib import Path
4
4
  from tempfile import TemporaryDirectory
5
5
  from typing import TYPE_CHECKING, Dict, List, Optional, Union, Iterable
6
+ from http import HTTPStatus
6
7
 
7
8
  import requests
8
9
  from requests import Response
@@ -146,12 +147,14 @@ class FrogMLClient:
146
147
  str: The build ID of the latest build according to the build status. None if no builds match the filter.
147
148
 
148
149
  """
149
- if (
150
- build_status
151
- not in DESCRIPTOR.enum_types_by_name["BuildStatus"].values_by_name
152
- ):
150
+ valid_statuses = set(
151
+ DESCRIPTOR.enum_types_by_name["BuildStatus"].values_by_name.keys()
152
+ )
153
+ if build_status not in valid_statuses:
153
154
  raise FrogmlException(
154
- f"Invalid build status {build_status}. Valid options are 'SUCCESSFUL', 'IN_PROGRESS', 'FAILED'"
155
+ error_message=f"Invalid build status '{build_status}'. Valid options are: {valid_statuses}",
156
+ status_code=HTTPStatus.BAD_REQUEST,
157
+ operation="Get Latest Build",
155
158
  )
156
159
 
157
160
  model = self._get_model_management().get_model(model_id=model_id)
@@ -601,7 +604,9 @@ class FrogMLClient:
601
604
  import pandas as pd
602
605
  except ImportError:
603
606
  raise FrogmlException(
604
- "Missing Pandas dependency required for running an analytics query."
607
+ error_message="Missing Pandas dependency required for running an analytics query",
608
+ status_code=HTTPStatus.BAD_REQUEST,
609
+ operation="Run Analytics Query",
605
610
  )
606
611
  client = self._get_analytics_engine()
607
612
  url = client.get_analytics_data(query=query, timeout=timeout)
@@ -640,7 +645,11 @@ class FrogMLClient:
640
645
  feature_set_def.feature_set.feature_set_definition.feature_set_id
641
646
  )
642
647
  else:
643
- raise FrogmlException(f"Feature set named '{feature_set_name}' not found")
648
+ raise FrogmlException(
649
+ error_message=f"Feature set '{feature_set_name}' not found",
650
+ status_code=HTTPStatus.NOT_FOUND,
651
+ operation="Delete Feature Set",
652
+ )
644
653
 
645
654
  def delete_featureset_version(self, featureset_name: str, version_number: int):
646
655
  """
@@ -686,7 +695,11 @@ class FrogMLClient:
686
695
  data_source_def.data_source.data_source_definition.data_source_id
687
696
  )
688
697
  else:
689
- raise FrogmlException(f"Data source named '{data_source_name}' not found")
698
+ raise FrogmlException(
699
+ error_message=f"Data source '{data_source_name}' not found",
700
+ status_code=HTTPStatus.NOT_FOUND,
701
+ operation="Delete Feature Store Data Source",
702
+ )
690
703
 
691
704
  def delete_entity(self, entity_name: str):
692
705
  """
@@ -700,7 +713,11 @@ class FrogMLClient:
700
713
  if entity_def:
701
714
  client.delete_entity(entity_def.entity.entity_definition.entity_id)
702
715
  else:
703
- raise FrogmlException(f"Entity named '{entity_name}' not found")
716
+ raise FrogmlException(
717
+ error_message=f"Entity '{entity_name}' not found",
718
+ status_code=HTTPStatus.NOT_FOUND,
719
+ operation="Delete Feature Store Entity",
720
+ )
704
721
 
705
722
  def trigger_batch_feature_set(self, feature_set_name):
706
723
  """
@@ -723,7 +740,9 @@ class FrogMLClient:
723
740
  automation = client.get_automation_by_name(automation_name=automation_name)
724
741
  if not automation:
725
742
  raise FrogmlException(
726
- f"Could not find automation with given name '{automation_name}'"
743
+ error_message=f"Could not find automation with given name '{automation_name}'",
744
+ status_code=HTTPStatus.NOT_FOUND,
745
+ operation="Trigger Automation",
727
746
  )
728
747
  client.run_automation(automation_id=automation.id)
729
748
 
@@ -1,5 +1,6 @@
1
1
  import json
2
2
  import typing as t
3
+ from http import HTTPStatus
3
4
 
4
5
  from frogml.core.exceptions import FrogmlException
5
6
 
@@ -47,7 +48,11 @@ class NumpyInputAdapter(BaseInputAdapter):
47
48
  try:
48
49
  dtype = np.dtype(dtype)
49
50
  except TypeError as e:
50
- raise FrogmlException(f'NumpyNdarray: Invalid dtype "{dtype}": {e}')
51
+ raise FrogmlException(
52
+ error_message=f'NumpyNdarray: Invalid dtype "{dtype}": {e}',
53
+ status_code=HTTPStatus.BAD_REQUEST,
54
+ operation="Initialize Model Input Adapter",
55
+ )
51
56
 
52
57
  self._dtype = dtype
53
58
  self._shape = shape
@@ -1,4 +1,5 @@
1
1
  import io
2
+ from http import HTTPStatus
2
3
 
3
4
  from frogml.core.exceptions import FrogmlException
4
5
 
@@ -21,7 +22,9 @@ class NumpyOutputAdapter(BaseOutputAdapter):
21
22
  def pack_user_func_return_value(return_result) -> bytes:
22
23
  if not isinstance(return_result, np.ndarray):
23
24
  raise FrogmlException(
24
- "XNpyOutputAdapter can only work with numpy.ndarray type"
25
+ error_message="NumpyOutputAdapter can only work with numpy.ndarray type",
26
+ status_code=HTTPStatus.BAD_REQUEST,
27
+ operation="Pack Model Output",
25
28
  )
26
29
  try:
27
30
  results_buffer = io.BytesIO()
@@ -1,4 +1,5 @@
1
1
  from typing import Callable
2
+ from http import HTTPStatus
2
3
 
3
4
  from dependency_injector.wiring import Provide, inject
4
5
 
@@ -63,4 +64,8 @@ def api_decorator(
63
64
  )
64
65
  except TypeError as e:
65
66
  if "__call__() takes 1" in str(e):
66
- raise FrogmlException(API_NOT_CONFIGURED_ERROR_MESSAGE)
67
+ raise FrogmlException(
68
+ error_message=API_NOT_CONFIGURED_ERROR_MESSAGE,
69
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
70
+ operation="Configure API",
71
+ )
@@ -1,4 +1,5 @@
1
1
  from typing import Any
2
+ from http import HTTPStatus
2
3
 
3
4
  from frogml.core.exceptions import FrogmlException, FrogmlHTTPException
4
5
  from frogml.sdk.model.adapters import (
@@ -71,5 +72,8 @@ def get_output_adapter(
71
72
  ):
72
73
  return runtime_impl(output_orient=adapter.output_orient)
73
74
  return runtime_impl()
74
-
75
- raise FrogmlException("No Adapter selected for output")
75
+ raise FrogmlException(
76
+ error_message="No output adapter selected",
77
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
78
+ operation="Get Output Adapter",
79
+ )
@@ -113,4 +113,7 @@ def load_model(repository: str, model_name: str, version: str):
113
113
  logging.error(
114
114
  f"Failed to load Model. Model was serialized with Catboost version: {framework_runtime_version}"
115
115
  )
116
- raise FrogmlException(f"Failed to deserialized model: {e}")
116
+ raise FrogmlException(
117
+ error_message=f"Failed to deserialize model: {e}",
118
+ operation="Load Model Version",
119
+ )
@@ -214,4 +214,7 @@ def load_model(repository: str, model_name: str, version: str):
214
214
  logging.error(
215
215
  f"Failed to load Model. Model was serialized with transformers using DistilBert version: {framework_runtime_version}"
216
216
  )
217
- raise FrogmlException(f"Failed to deserialized model: {e}")
217
+ raise FrogmlException(
218
+ error_message=f"Failed to deserialize model: {e}",
219
+ operation="Load Model Version",
220
+ )
@@ -28,7 +28,10 @@ class CatboostModelVersionManager(BaseModelVersionManager):
28
28
 
29
29
  return catboost.__version__
30
30
  except Exception as e:
31
- raise FrogmlException(f"Failed to get catboost version: {e}")
31
+ raise FrogmlException(
32
+ error_message=f"Failed to get catboost version: {e}",
33
+ operation="Get Model Version Framework Version",
34
+ )
32
35
 
33
36
  @override
34
37
  def _save_model(self: Self, model: Any, config: ModelLogConfig):
@@ -1,3 +1,4 @@
1
+ from http import HTTPStatus
1
2
  from typing import Any
2
3
 
3
4
  from typing_extensions import Self, override
@@ -31,12 +32,19 @@ class HuggingfaceModelVersionManager(BaseModelVersionManager):
31
32
 
32
33
  return transformers.__version__
33
34
  except Exception as e:
34
- raise FrogmlException(f"Failed to get transformers version: {e}")
35
+ raise FrogmlException(
36
+ error_message=f"Failed to get transformers version: {e}",
37
+ operation="Get Model Version Framework Version",
38
+ )
35
39
 
36
40
  @override
37
41
  def _save_model(self: Self, model: Any, config: ModelLogConfig):
38
42
  if not isinstance(model, tuple):
39
- raise FrogmlException("Model must be a tuple containing (model, tokenizer)")
43
+ raise FrogmlException(
44
+ error_message="Model must be a tuple containing (model, tokenizer)",
45
+ status_code=HTTPStatus.BAD_REQUEST,
46
+ operation="Save Model Version",
47
+ )
40
48
 
41
49
  model_obj, tokenizer = model # Assuming model is a tuple of (model, tokenizer)
42
50
  model_obj.save_pretrained(config.full_model_path)
@@ -28,7 +28,10 @@ class OnnxModelVersionManager(BaseModelVersionManager):
28
28
 
29
29
  return onnx.__version__
30
30
  except Exception as e:
31
- raise FrogmlException(f"Failed to get onnx version: {e}")
31
+ raise FrogmlException(
32
+ error_message=f"Failed to get onnx version: {e}",
33
+ operation="Get Model Version Framework Version",
34
+ )
32
35
 
33
36
  @override
34
37
  def _save_model(self: Self, model: Any, config: ModelLogConfig):
@@ -28,7 +28,10 @@ class PytorchModelVersionManager(BaseModelVersionManager):
28
28
 
29
29
  return torch.__version__
30
30
  except Exception as e:
31
- raise FrogmlException(f"Failed to get torch version: {e}")
31
+ raise FrogmlException(
32
+ error_message=f"Failed to get torch version: {e}",
33
+ operation="Get Model Version Framework Version",
34
+ )
32
35
 
33
36
  @override
34
37
  def _save_model(self: Self, model: Any, config: ModelLogConfig):
@@ -32,7 +32,10 @@ class ScikitLearnModelVersionManager(BaseModelVersionManager):
32
32
 
33
33
  return sklearn.__version__
34
34
  except Exception as e:
35
- raise FrogmlException(f"Failed to get sklearn version: {e}")
35
+ raise FrogmlException(
36
+ error_message=f"Failed to get sklearn version: {e}",
37
+ operation="Get Model Version Framework Version",
38
+ )
36
39
 
37
40
  @override
38
41
  def _save_model(self: Self, model: Any, config: ModelLogConfig):
@@ -121,4 +121,7 @@ def load_model(repository: str, model_name: str, version: str):
121
121
  logging.error(
122
122
  f"Failed to load Model. Model was serialized with onnx version: {framework_runtime_version}"
123
123
  )
124
- raise FrogmlException(f"Failed to deserialized model: {e}")
124
+ raise FrogmlException(
125
+ error_message=f"Failed to deserialize model: {e}",
126
+ operation="Load Model Version",
127
+ )
@@ -113,4 +113,7 @@ def load_model(repository: str, model_name: str, version: str):
113
113
  logging.error(
114
114
  f"Failed to load Model. Model was serialized with Pytorch version: {framework_runtime_version}"
115
115
  )
116
- raise FrogmlException(f"Failed to deserialized model: {e}")
116
+ raise FrogmlException(
117
+ error_message=f"Failed to deserialize model: {e}",
118
+ operation="Load Model Version",
119
+ )
@@ -126,4 +126,7 @@ def load_model(repository: str, model_name: str, version: str):
126
126
  logging.error(
127
127
  f"Failed to load Model. Model was serialized with scikit-learn version: {framework_runtime_version}"
128
128
  )
129
- raise FrogmlException(f"Failed to deserialized model: {e}")
129
+ raise FrogmlException(
130
+ error_message=f"Failed to deserialize model: {e}",
131
+ operation="Load Model Version",
132
+ )
@@ -130,6 +130,6 @@ class JmlCustomerClient:
130
130
  "Failed to create model version %s in JFML due to this following error: '%s'\n\n"
131
131
  "Before retrying, please delete the uploaded artifact from Artifactory",
132
132
  model_version_name,
133
- e.message,
133
+ e.error_message,
134
134
  )
135
135
  raise e
@@ -214,7 +214,10 @@ def build_zip_code_path(
214
214
  root_dir=parent_dir_path, dir_to_zip=filtered_copied_dir_path
215
215
  )
216
216
  except Exception as e:
217
- raise FrogmlException(f"Failed to zip code directory: {e}") from e
217
+ raise FrogmlException(
218
+ error_message=f"Failed to zip code directory: {e}",
219
+ operation="Prepare Model Version Code Package",
220
+ ) from e
218
221
  finally:
219
222
  _remove_dir(filtered_copied_dir_path)
220
223
  _remove_dir(template_file_dir)
@@ -1,3 +1,5 @@
1
+ from http import HTTPStatus
2
+
1
3
  from frogml.core.exceptions import FrogmlException
2
4
  from frogml.sdk.model_version.constants import ModelFramework
3
5
 
@@ -9,7 +11,11 @@ def _validate_string(s: str) -> None:
9
11
  :return: None if validation pass successfully else raise error
10
12
  """
11
13
  if not s:
12
- raise FrogmlException("String is empty")
14
+ raise FrogmlException(
15
+ error_message="String cannot be empty",
16
+ status_code=HTTPStatus.BAD_REQUEST,
17
+ operation="Validate Model Version Input",
18
+ )
13
19
 
14
20
 
15
21
  def _validate_load_model(
@@ -35,5 +41,7 @@ def _validate_load_model(
35
41
  _validate_string(version)
36
42
  if model_framework_stored != model_framework.value:
37
43
  raise FrogmlException(
38
- f"The Model: {model_name} in Repository: {repository} - is not a {model_framework} model"
44
+ error_message=f"Model '{model_name}' in repository '{repository}' is not a {model_framework} model",
45
+ status_code=HTTPStatus.BAD_REQUEST,
46
+ operation="Load Model Version",
39
47
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: frogml
3
- Version: 1.2.49
3
+ Version: 2.0.0
4
4
  Summary: frogml contains the necessary objects and communication tools for using the JFrog ml Platform
5
5
  License: Apache-2.0
6
6
  Keywords: mlops,ml,deployment,serving,model