frogml 1.2.50__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.50.dist-info → frogml-2.0.0.dist-info}/METADATA +1 -1
  51. {frogml-1.2.50.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.50.dist-info → frogml-2.0.0.dist-info}/WHEEL +0 -0
@@ -1,3 +1,5 @@
1
+ from typing import Any, Callable
2
+
1
3
  from dependency_injector.wiring import Provide
2
4
  from frogml._proto.qwak.feature_store.entities.entity_pb2 import EntitySpec
3
5
  from frogml._proto.qwak.feature_store.entities.entity_service_pb2 import (
@@ -93,7 +95,8 @@ class FeatureRegistryClient:
93
95
  )
94
96
 
95
97
  @grpc_try_catch_wrapper(
96
- "Failed to get a presigned url", reraise_non_grpc_error_original_exception=True
98
+ error_message="Failed to get a presigned url",
99
+ operation="Get Feature Store Presigned URL",
97
100
  )
98
101
  def get_datasource_source_code_presign_url(
99
102
  self, ds_name: str, repository_name: str
@@ -105,7 +108,8 @@ class FeatureRegistryClient:
105
108
  )
106
109
 
107
110
  @grpc_try_catch_wrapper(
108
- "Failed to list features", reraise_non_grpc_error_original_exception=True
111
+ error_message="Failed to list features",
112
+ operation="List Feature Store Feature Sets",
109
113
  )
110
114
  def list_feature_sets(self) -> ListFeatureSetsResponse:
111
115
  """
@@ -130,7 +134,8 @@ class FeatureRegistryClient:
130
134
  )
131
135
 
132
136
  @grpc_try_catch_wrapper(
133
- "Failed to delete feature", reraise_non_grpc_error_original_exception=True
137
+ error_message="Failed to delete feature",
138
+ operation="Delete Feature Store Feature Set",
134
139
  )
135
140
  def delete_feature_set(self, feature_set_id: str) -> DeleteFeatureSetResponse:
136
141
  """
@@ -144,7 +149,7 @@ class FeatureRegistryClient:
144
149
  )
145
150
 
146
151
  @grpc_try_catch_wrapper(
147
- "Failed to delete entity", reraise_non_grpc_error_original_exception=True
152
+ error_message="Failed to delete entity", operation="Delete Feature Store Entity"
148
153
  )
149
154
  def delete_entity(self, entity_id: str) -> DeleteEntityResponse:
150
155
  """
@@ -158,7 +163,8 @@ class FeatureRegistryClient:
158
163
  )
159
164
 
160
165
  @grpc_try_catch_wrapper(
161
- "Failed to delete data source", reraise_non_grpc_error_original_exception=True
166
+ error_message="Failed to delete data source",
167
+ operation="Delete Feature Store Data Source",
162
168
  )
163
169
  def delete_data_source(self, data_source_id: str) -> DeleteDataSourceResponse:
164
170
  """
@@ -172,7 +178,7 @@ class FeatureRegistryClient:
172
178
  )
173
179
 
174
180
  @grpc_try_catch_wrapper(
175
- "Failed to run feature", reraise_non_grpc_error_original_exception=True
181
+ error_message="Failed to run feature", operation="Run Feature Store Feature Set"
176
182
  )
177
183
  def run_feature_set(self, feature_set_name: str) -> RunBatchFeatureSetResponse:
178
184
  """
@@ -187,7 +193,8 @@ class FeatureRegistryClient:
187
193
  )
188
194
 
189
195
  @grpc_try_catch_wrapper(
190
- "Failed to run feature", reraise_non_grpc_error_original_exception=True
196
+ error_message="Failed to run feature",
197
+ operation="Run Feature Store Parquet Batch Feature Set",
191
198
  )
192
199
  def run_parquet_batch_feature_set(
193
200
  self, feature_set_name: str, parquet_location: str, timestamp_column: str
@@ -210,7 +217,7 @@ class FeatureRegistryClient:
210
217
  )
211
218
 
212
219
  @grpc_try_catch_wrapper(
213
- "Failed to update entity", reraise_non_grpc_error_original_exception=True
220
+ error_message="Failed to update entity", operation="Update Feature Store Entity"
214
221
  )
215
222
  def update_entity(
216
223
  self, entity_id: str, proto_entity_spec: EntitySpec
@@ -227,7 +234,7 @@ class FeatureRegistryClient:
227
234
  )
228
235
 
229
236
  @grpc_try_catch_wrapper(
230
- "Failed to create entity", reraise_non_grpc_error_original_exception=True
237
+ error_message="Failed to create entity", operation="Create Feature Store Entity"
231
238
  )
232
239
  def create_entity(self, proto_entity_spec: EntitySpec) -> CreateEntityResponse:
233
240
  """
@@ -241,7 +248,7 @@ class FeatureRegistryClient:
241
248
  )
242
249
 
243
250
  @grpc_try_catch_wrapper(
244
- "Failed to list entities", reraise_non_grpc_error_original_exception=True
251
+ error_message="Failed to list entities", operation="List Feature Store Entities"
245
252
  )
246
253
  def list_entities(self) -> ListEntitiesResponse:
247
254
  """
@@ -251,7 +258,8 @@ class FeatureRegistryClient:
251
258
  return self._entity_service.ListEntities(ListEntitiesRequest())
252
259
 
253
260
  @grpc_try_catch_wrapper(
254
- "Failed to list data sources", reraise_non_grpc_error_original_exception=True
261
+ error_message="Failed to list data sources",
262
+ operation="List Feature Store Data Sources",
255
263
  )
256
264
  def list_data_sources(self) -> ListDataSourcesResponse:
257
265
  """
@@ -278,7 +286,8 @@ class FeatureRegistryClient:
278
286
  )
279
287
 
280
288
  @grpc_try_catch_wrapper(
281
- "Failed to update data source", reraise_non_grpc_error_original_exception=True
289
+ error_message="Failed to update data source",
290
+ operation="Update Feature Store Data Source",
282
291
  )
283
292
  def update_data_source(
284
293
  self,
@@ -300,7 +309,8 @@ class FeatureRegistryClient:
300
309
  )
301
310
 
302
311
  @grpc_try_catch_wrapper(
303
- "Failed to create data source", reraise_non_grpc_error_original_exception=True
312
+ error_message="Failed to create data source",
313
+ operation="Create Feature Store Data Source",
304
314
  )
305
315
  def create_data_source(
306
316
  self, proto_data_source: FeatureSetSpec
@@ -331,7 +341,8 @@ class FeatureRegistryClient:
331
341
  )
332
342
 
333
343
  @grpc_try_catch_wrapper(
334
- "Failed to update feature set", reraise_non_grpc_error_original_exception=True
344
+ error_message="Failed to update feature set",
345
+ operation="Update Feature Store Feature Set",
335
346
  )
336
347
  def update_feature_set(
337
348
  self,
@@ -352,7 +363,8 @@ class FeatureRegistryClient:
352
363
  )
353
364
 
354
365
  @grpc_try_catch_wrapper(
355
- "Failed to create feature set", reraise_non_grpc_error_original_exception=True
366
+ error_message="Failed to create feature set",
367
+ operation="Create Feature Store Feature Set",
356
368
  )
357
369
  def create_feature_set(
358
370
  self, proto_feature_set: FeatureSetSpec
@@ -368,7 +380,9 @@ class FeatureRegistryClient:
368
380
  )
369
381
 
370
382
  @staticmethod
371
- def _fetch_by_name(extract_function, name, fs_object_type):
383
+ def _fetch_by_name(
384
+ extract_function: Callable[[str], Any], name: str, fs_object_type: str
385
+ ) -> Any:
372
386
  """
373
387
  Args:
374
388
  extract_function: function to run on name param
@@ -384,7 +398,8 @@ class FeatureRegistryClient:
384
398
  return None
385
399
  else:
386
400
  raise FrogmlException(
387
- f"Failed to fetch {fs_object_type} by name [{name}], error code: [{e.details()}]"
401
+ error_message=f"Failed to fetch {fs_object_type} by name {name}: {e.details()}",
402
+ operation=f"Get Feature Store {fs_object_type.title()}",
388
403
  )
389
404
 
390
405
  def get_presigned_url_v1(
@@ -408,13 +423,13 @@ class FeatureRegistryClient:
408
423
  ).upload_url
409
424
  except RpcError as e:
410
425
  raise FrogmlException(
411
- f"Failed to get presigned url for featureset name {feature_set_name} and transformation type "
412
- f"{type(transformation)}, error code: [{e.details()}]"
426
+ error_message=f"Failed to get presigned url for featureset name {feature_set_name}: {e.details()}",
427
+ operation="Get Feature Store Presigned URL",
413
428
  )
414
429
 
415
430
  @grpc_try_catch_wrapper(
416
- "Failed to get presigned url for data source: {data_source_name}, object name: {object_name}",
417
- reraise_non_grpc_error_original_exception=True,
431
+ error_message="Failed to get presigned url for data source: {data_source_name}, object name: {object_name}",
432
+ operation="Get Feature Store Data Source Presigned URL",
418
433
  )
419
434
  def get_data_source_presigned_url_v1(
420
435
  self, data_source_name: str, object_name: str
@@ -436,8 +451,8 @@ class FeatureRegistryClient:
436
451
  ).upload_url
437
452
 
438
453
  @grpc_try_catch_wrapper(
439
- "Failed to query scheduling state for Featureset {feature_set_name}",
440
- reraise_non_grpc_error_original_exception=True,
454
+ error_message="Failed to query scheduling state for Featureset {feature_set_name}",
455
+ operation="Get Feature Store FeatureSet Scheduling State",
441
456
  )
442
457
  def get_feature_set_scheduling_state(
443
458
  self, feature_set_name: str
@@ -447,26 +462,26 @@ class FeatureRegistryClient:
447
462
  )
448
463
 
449
464
  @grpc_try_catch_wrapper(
450
- "Failed to pause Featureset {feature_set_name}",
451
- reraise_non_grpc_error_original_exception=True,
465
+ error_message="Failed to pause Featureset {feature_set_name}",
466
+ operation="Pause Feature Store FeatureSet",
452
467
  )
453
- def pause_feature_set(self, feature_set_name: str):
468
+ def pause_feature_set(self, feature_set_name: str) -> None:
454
469
  self._features_service.PauseFeatureset(
455
470
  PauseFeaturesetRequest(featureset_name=feature_set_name)
456
471
  )
457
472
 
458
473
  @grpc_try_catch_wrapper(
459
- "Failed to resume Featureset {feature_set_name}",
460
- reraise_non_grpc_error_original_exception=True,
474
+ error_message="Failed to resume Featureset {feature_set_name}",
475
+ operation="Resume Feature Store FeatureSet",
461
476
  )
462
- def resume_feature_set(self, feature_set_name: str):
477
+ def resume_feature_set(self, feature_set_name: str) -> None:
463
478
  self._features_service.ResumeFeatureset(
464
479
  ResumeFeaturesetRequest(featureset_name=feature_set_name)
465
480
  )
466
481
 
467
482
  @grpc_try_catch_wrapper(
468
- "Failed list Featureset versions for Featureset: {featureset_name}",
469
- reraise_non_grpc_error_original_exception=True,
483
+ error_message="Failed list Featureset versions for Featureset: {featureset_name}",
484
+ operation="List Feature Store FeatureSet Versions",
470
485
  )
471
486
  def list_featureset_versions(
472
487
  self, featureset_name: str
@@ -476,10 +491,12 @@ class FeatureRegistryClient:
476
491
  )
477
492
 
478
493
  @grpc_try_catch_wrapper(
479
- "Failed to set active version: {version_number} for Featureset: {featureset_name}",
480
- reraise_non_grpc_error_original_exception=True,
494
+ error_message="Failed to set active version: {version_number} for Featureset: {featureset_name}",
495
+ operation="Set Feature Store Active FeatureSet Version",
481
496
  )
482
- def set_active_featureset_version(self, featureset_name: str, version_number: int):
497
+ def set_active_featureset_version(
498
+ self, featureset_name: str, version_number: int
499
+ ) -> None:
483
500
  self._features_service.SetActiveFeaturesetVersion(
484
501
  SetActiveFeaturesetVersionRequest(
485
502
  featureset_name=featureset_name,
@@ -488,10 +505,12 @@ class FeatureRegistryClient:
488
505
  )
489
506
 
490
507
  @grpc_try_catch_wrapper(
491
- "Failed to delete version: {version_number} for Featureset: {featureset_name}",
492
- reraise_non_grpc_error_original_exception=True,
508
+ error_message="Failed to delete version: {version_number} for Featureset: {featureset_name}",
509
+ operation="Delete Feature Store FeatureSet Version",
493
510
  )
494
- def delete_featureset_version(self, featureset_name: str, version_number: int):
511
+ def delete_featureset_version(
512
+ self, featureset_name: str, version_number: int
513
+ ) -> None:
495
514
  self._features_service.DeleteFeaturesetVersion(
496
515
  DeleteFeaturesetVersionRequest(
497
516
  featureset_name=featureset_name,
@@ -500,8 +519,8 @@ class FeatureRegistryClient:
500
519
  )
501
520
 
502
521
  @grpc_try_catch_wrapper(
503
- "Failed to get env to featuresets mapping",
504
- reraise_non_grpc_error_original_exception=True,
522
+ error_message="Failed to get env to featuresets mapping",
523
+ operation="Get Feature Store Env To FeatureSets Mapping",
505
524
  )
506
525
  def get_env_to_featuresets_mapping(self) -> GetEnvToFeatureSetsMappingResponse:
507
526
  return self._features_service.GetEnvToFeatureSetsMapping(
@@ -42,7 +42,8 @@ class FeaturesOperatorClient:
42
42
  self._v3_client = FeaturesOperatorAsyncServiceStub(grpc_channel)
43
43
 
44
44
  @grpc_try_catch_wrapper(
45
- "Failed to validate DataSource", reraise_non_grpc_error_original_exception=True
45
+ error_message="Failed to validate DataSource",
46
+ operation="Validate Feature Store DataSource",
46
47
  )
47
48
  def validate_data_source(
48
49
  self,
@@ -63,7 +64,8 @@ class FeaturesOperatorClient:
63
64
  return response.request_id
64
65
 
65
66
  @grpc_try_catch_wrapper(
66
- "Failed to validate FeatureSet", reraise_non_grpc_error_original_exception=True
67
+ error_message="Failed to validate FeatureSet",
68
+ operation="Validate Feature Store FeatureSet",
67
69
  )
68
70
  def validate_featureset(
69
71
  self,
@@ -87,8 +89,8 @@ class FeaturesOperatorClient:
87
89
  return response.request_id
88
90
 
89
91
  @grpc_try_catch_wrapper(
90
- "Failed to fetch validation result",
91
- reraise_non_grpc_error_original_exception=True,
92
+ error_message="Failed to fetch validation result",
93
+ operation="Get Feature Store Validation Result",
92
94
  )
93
95
  def get_result(self, request_handle: str) -> GetValidationResultResponse:
94
96
  """
@@ -29,7 +29,9 @@ class ModelGroupManagementClient:
29
29
  ProjectsManagementServiceStub(grpc_channel)
30
30
  )
31
31
 
32
- @grpc_try_catch_wrapper("Failed to create model")
32
+ @grpc_try_catch_wrapper(
33
+ error_message="Failed to create model group", operation="Create Model Group"
34
+ )
33
35
  def create_if_not_exists_model_group(
34
36
  self: Self, project_key: str
35
37
  ) -> ModelGroupBriefInfoResponse:
@@ -43,7 +45,8 @@ class ModelGroupManagementClient:
43
45
  )
44
46
 
45
47
  @grpc_try_catch_wrapper(
46
- "Failed to get model group with model_group_id '{model_group_id}' and model_group_name '{model_group_name}'"
48
+ error_message="Failed to get model group with model_group_id '{model_group_id}' and model_group_name '{model_group_name}'",
49
+ operation="Get Model Group",
47
50
  )
48
51
  def get_model_group(
49
52
  self, model_group_id: str = "", model_group_name: str = ""
@@ -46,7 +46,10 @@ class ModelsManagementClient:
46
46
  except grpc.RpcError as e:
47
47
  if e.code() == grpc.StatusCode.NOT_FOUND and not exception_on_missing:
48
48
  return None
49
- raise FrogmlException(f"Failed to get model, error is {e.details()}")
49
+ raise FrogmlException(
50
+ error_message=f"Failed to get model: {e.details()}",
51
+ operation="Get Model",
52
+ )
50
53
 
51
54
  def get_model_by_uuid(
52
55
  self, model_uuid, exception_on_missing: bool = True
@@ -59,13 +62,18 @@ class ModelsManagementClient:
59
62
  except grpc.RpcError as e:
60
63
  if e.code() == grpc.StatusCode.NOT_FOUND and not exception_on_missing:
61
64
  return None
62
- raise FrogmlException(f"Failed to get model, error is {e.details()}")
65
+ raise FrogmlException(
66
+ error_message=f"Failed to get model: {e.details()}",
67
+ operation="Get Model",
68
+ )
63
69
 
64
70
  def get_model_uuid(self, model_id: str) -> str:
65
71
  model: Optional[Model] = self.get_model(model_id)
66
72
  return model.uuid
67
73
 
68
- @grpc_try_catch_wrapper("Failed to create model")
74
+ @grpc_try_catch_wrapper(
75
+ error_message="Failed to create model", operation="Create Model"
76
+ )
69
77
  def create_model(
70
78
  self,
71
79
  project_id: str,
@@ -87,7 +95,9 @@ class ModelsManagementClient:
87
95
  )
88
96
  )
89
97
 
90
- @grpc_try_catch_wrapper("Failed to delete model")
98
+ @grpc_try_catch_wrapper(
99
+ error_message="Failed to delete model", operation="Delete Model"
100
+ )
91
101
  def delete_model(self, project_id: str, model_id: str) -> DeleteModelResponse:
92
102
  return self._models_management_service.DeleteModel(
93
103
  DeleteModelRequest(model_id=model_id, project_id=project_id)
@@ -111,22 +121,29 @@ class ModelsManagementClient:
111
121
  if e.code() == grpc.StatusCode.NOT_FOUND:
112
122
  return False
113
123
  raise FrogmlException(
114
- f"Failed to check if model {model_id} is exists, error is {e.details()}"
124
+ error_message=f"Failed to check if model {model_id} exists: {e.details()}",
125
+ operation="Check Model Exists",
115
126
  )
116
127
 
117
- @grpc_try_catch_wrapper("Failed to list models metadata")
128
+ @grpc_try_catch_wrapper(
129
+ error_message="Failed to list models metadata", operation="List Models Metadata"
130
+ )
118
131
  def list_models_metadata(self, project_id: str) -> ListModelsMetadataResponse:
119
132
  return self._models_management_service.ListModelsMetadata(
120
133
  ListModelsMetadataRequest(project_id=project_id)
121
134
  )
122
135
 
123
- @grpc_try_catch_wrapper("Failed to list models")
136
+ @grpc_try_catch_wrapper(
137
+ error_message="Failed to list models", operation="List Models"
138
+ )
124
139
  def list_models(self, project_id: str) -> ListModelsResponse:
125
140
  return self._models_management_service.ListModels(
126
141
  ListModelsRequest(project_id=project_id)
127
142
  )
128
143
 
129
- @grpc_try_catch_wrapper("Failed to get model metadata")
144
+ @grpc_try_catch_wrapper(
145
+ error_message="Failed to get model metadata", operation="Get Model Metadata"
146
+ )
130
147
  def get_model_metadata(self, model_id: str) -> GetModelMetadataResponse:
131
148
  return self._models_management_service.GetModelMetadata(
132
149
  GetModelMetadataRequest(model_id=model_id)
@@ -1,3 +1,4 @@
1
+ from http import HTTPStatus
1
2
  from typing import Optional, List
2
3
  from pydantic import BaseModel, model_validator
3
4
  from typing_extensions import Self
@@ -61,7 +62,9 @@ class PodResourcesDTO(BaseModel):
61
62
 
62
63
  if fields_set != 1:
63
64
  raise FrogmlException(
64
- "Exactly one of template_spec, cpu_resources, or gpu_resources must be set"
65
+ error_message="Exactly one of template_spec, cpu_resources, or gpu_resources must be set",
66
+ status_code=HTTPStatus.BAD_REQUEST,
67
+ operation="Validate Model Version Pod Resources",
65
68
  )
66
69
 
67
70
  return self
@@ -1,9 +1,9 @@
1
1
  import logging
2
+ from http import HTTPStatus
2
3
  from platform import python_version
3
4
  from typing import List, Optional, Dict, Union, Tuple
4
5
 
5
6
  from dependency_injector.wiring import Provide
6
- from grpc import RpcError
7
7
  from typing_extensions import Self
8
8
 
9
9
  from frogml._proto.jfml.model_version.v1.artifact_pb2 import Artifact as ArtifactProto
@@ -116,6 +116,10 @@ class ModelVersionManagerClient:
116
116
  ml_bom_data=MlBomData(**kwargs),
117
117
  )
118
118
 
119
+ @grpc_try_catch_wrapper(
120
+ error_message="Failed to validate model version '{model_version_name}' for model '{model_name}'",
121
+ operation="Validate Model Version",
122
+ )
119
123
  def validate_create_model_version(
120
124
  self,
121
125
  repository_key: str,
@@ -128,36 +132,30 @@ class ModelVersionManagerClient:
128
132
  parameters: Optional[Dict[str, str]] = None,
129
133
  metrics: Optional[Dict[str, str]] = None,
130
134
  ):
131
- try:
132
- (
133
- code_artifacts_proto,
134
- dependency_artifacts_proto,
135
- model_artifact_proto,
136
- ) = self.convert_artifacts(
137
- model_artifact, dependency_artifacts, code_artifacts
138
- )
139
-
140
- create_model_request = self.__build_create_model_version_request(
141
- repository_key=repository_key,
142
- model_name=model_name,
143
- model_version_name=model_version_name,
144
- model_version_framework=model_version_framework,
145
- dry_run=True,
146
- model_artifacts=model_artifact_proto,
147
- dependency_artifacts=dependency_artifacts_proto,
148
- code_artifacts=code_artifacts_proto,
149
- parameters=parameters,
150
- metrics=metrics,
151
- )
152
- self.__model_version_manager_stub.CreateModelVersion(create_model_request)
153
- except RpcError as e:
154
- message = f"Failed to validate model version, details [{e.details()}]"
155
- raise FrogmlException(message)
135
+ (
136
+ code_artifacts_proto,
137
+ dependency_artifacts_proto,
138
+ model_artifact_proto,
139
+ ) = self.convert_artifacts(model_artifact, dependency_artifacts, code_artifacts)
156
140
 
157
- except Exception as e:
158
- message = f"Failed to validate model version, details [{e}]"
159
- raise FrogmlException(message)
141
+ create_model_request = self.__build_create_model_version_request(
142
+ repository_key=repository_key,
143
+ model_name=model_name,
144
+ model_version_name=model_version_name,
145
+ model_version_framework=model_version_framework,
146
+ dry_run=True,
147
+ model_artifacts=model_artifact_proto,
148
+ dependency_artifacts=dependency_artifacts_proto,
149
+ code_artifacts=code_artifacts_proto,
150
+ parameters=parameters,
151
+ metrics=metrics,
152
+ )
153
+ self.__model_version_manager_stub.CreateModelVersion(create_model_request)
160
154
 
155
+ @grpc_try_catch_wrapper(
156
+ error_message="Failed to create model version '{model_version_name}' for model '{model_name}'",
157
+ operation="Create Model Version",
158
+ )
161
159
  def create_model_version(
162
160
  self,
163
161
  repository_key: str,
@@ -170,41 +168,27 @@ class ModelVersionManagerClient:
170
168
  parameters: Optional[Dict[str, str]] = None,
171
169
  metrics: Optional[Dict[str, str]] = None,
172
170
  ) -> CreateModelVersionResponse:
173
- try:
174
- (
175
- code_artifacts_proto,
176
- dependency_artifacts_proto,
177
- model_artifact_proto,
178
- ) = self.convert_artifacts(
179
- model_artifact, dependency_artifacts, code_artifacts
180
- )
181
-
182
- create_model_request = self.__build_create_model_version_request(
183
- repository_key=repository_key,
184
- model_name=model_name,
185
- model_version_name=model_version_name,
186
- model_version_framework=model_version_framework,
187
- dry_run=False,
188
- model_artifacts=model_artifact_proto,
189
- dependency_artifacts=dependency_artifacts_proto,
190
- code_artifacts=code_artifacts_proto,
191
- parameters=parameters,
192
- metrics=metrics,
193
- )
194
- create_model_version_response: CreateModelVersionResponse = (
195
- self.__model_version_manager_stub.CreateModelVersion(
196
- create_model_request
197
- )
198
- )
199
-
200
- return create_model_version_response
201
- except RpcError as e:
202
- message = f"Failed to validate model version, details [{e.details()}]"
203
- raise FrogmlException(message)
171
+ (
172
+ code_artifacts_proto,
173
+ dependency_artifacts_proto,
174
+ model_artifact_proto,
175
+ ) = self.convert_artifacts(model_artifact, dependency_artifacts, code_artifacts)
204
176
 
205
- except Exception as e:
206
- message = f"Failed to validate model version, details [{e}]"
207
- raise FrogmlException(message)
177
+ create_model_request = self.__build_create_model_version_request(
178
+ repository_key=repository_key,
179
+ model_name=model_name,
180
+ model_version_name=model_version_name,
181
+ model_version_framework=model_version_framework,
182
+ dry_run=False,
183
+ model_artifacts=model_artifact_proto,
184
+ dependency_artifacts=dependency_artifacts_proto,
185
+ code_artifacts=code_artifacts_proto,
186
+ parameters=parameters,
187
+ metrics=metrics,
188
+ )
189
+ return self.__model_version_manager_stub.CreateModelVersion(
190
+ create_model_request
191
+ )
208
192
 
209
193
  @staticmethod
210
194
  def convert_artifacts(
@@ -231,7 +215,6 @@ class ModelVersionManagerClient:
231
215
  )
232
216
  return code_artifacts_proto, dependency_artifacts_proto, model_artifact_proto
233
217
 
234
- @grpc_try_catch_wrapper("Failed to promote model version to build")
235
218
  def promote_to_build(
236
219
  self: Self,
237
220
  build_config: BuildConfigDTO,
@@ -248,15 +231,31 @@ class ModelVersionManagerClient:
248
231
  :return The build ID of the promoted model version
249
232
  :raises FrogmlException: If the promotion fails or parameters are invalid
250
233
  """
251
- logger.info("Promote model version to build %s", build_config)
252
- is_missing_required_model_version_params: bool = not model_version_id and (
234
+ is_missing_required_params = not model_version_id and (
253
235
  not model_id or not model_version_name
254
236
  )
255
- if is_missing_required_model_version_params:
237
+ if is_missing_required_params:
256
238
  raise FrogmlException(
257
- "Either model_version_id must be provided, or both model_id and model_version_name must be provided"
239
+ error_message="Either model_version_id must be provided, or both model_id and model_version_name must be provided",
240
+ status_code=HTTPStatus.BAD_REQUEST,
241
+ operation="Promote Model Version",
258
242
  )
243
+ return self._promote_to_build_grpc(
244
+ build_config, model_version_id, model_id, model_version_name
245
+ )
259
246
 
247
+ @grpc_try_catch_wrapper(
248
+ error_message="Failed to promote model version '{model_version_name}' (id: {model_version_id}) to build",
249
+ operation="Promote Model Version",
250
+ )
251
+ def _promote_to_build_grpc(
252
+ self: Self,
253
+ build_config: BuildConfigDTO,
254
+ model_version_id: Optional[str],
255
+ model_id: Optional[str],
256
+ model_version_name: Optional[str],
257
+ ) -> str:
258
+ logger.info("Promote model version to build %s", build_config)
260
259
  build_spec: BuildSpec = map_build_conf_to_build_spec(build_config)
261
260
  logger.debug("build_spec = %s", build_spec)
262
261
 
@@ -1,14 +1,32 @@
1
+ import sys
2
+ from types import TracebackType
3
+ from typing import Optional
4
+
1
5
  from .frogml_exception import FrogmlException
2
6
  from .frogml_general_build_exception import FrogmlGeneralBuildException
3
7
  from .frogml_grpc_address_exception import FrogmlGrpcAddressException
4
8
  from .frogml_http_exception import FrogmlHTTPException
5
9
  from .frogml_inference_exception import FrogmlInferenceException
6
10
  from .frogml_load_configuration_exception import LoadConfigurationException
7
- from .frogml_load_model_failed_exception import FrogmlLoadModelFailedException
8
11
  from .frogml_login_exception import FrogmlLoginException
9
12
  from .frogml_mock_http_exception import MockHttpException
10
13
  from .frogml_model_initialization_exception import FrogmlModelInitializationException
11
14
  from .frogml_not_found_exception import FrogmlNotFoundException
12
15
  from .frogml_remote_build_failed import FrogmlRemoteBuildFailedException
13
16
  from .frogml_suggestion_exception import FrogmlSuggestionException
14
- from .quiet_error import QuietError
17
+ from .grpc_status_mapping import grpc_to_http_status
18
+
19
+
20
+ def _quiet_hook(
21
+ kind: type[BaseException],
22
+ message: BaseException,
23
+ traceback: Optional[TracebackType],
24
+ ) -> None:
25
+ """Custom exception hook that suppresses tracebacks for FrogmlException."""
26
+ if issubclass(kind, FrogmlException):
27
+ print(f"{message}")
28
+ else:
29
+ sys.__excepthook__(kind, message, traceback)
30
+
31
+
32
+ sys.excepthook = _quiet_hook