oracle-ads 2.10.1__py3-none-any.whl → 2.11.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 (71) hide show
  1. ads/aqua/__init__.py +12 -0
  2. ads/aqua/base.py +324 -0
  3. ads/aqua/cli.py +19 -0
  4. ads/aqua/config/deployment_config_defaults.json +9 -0
  5. ads/aqua/config/resource_limit_names.json +7 -0
  6. ads/aqua/constants.py +45 -0
  7. ads/aqua/data.py +40 -0
  8. ads/aqua/decorator.py +101 -0
  9. ads/aqua/deployment.py +643 -0
  10. ads/aqua/dummy_data/icon.txt +1 -0
  11. ads/aqua/dummy_data/oci_model_deployments.json +56 -0
  12. ads/aqua/dummy_data/oci_models.json +1 -0
  13. ads/aqua/dummy_data/readme.md +26 -0
  14. ads/aqua/evaluation.py +1751 -0
  15. ads/aqua/exception.py +82 -0
  16. ads/aqua/extension/__init__.py +40 -0
  17. ads/aqua/extension/base_handler.py +138 -0
  18. ads/aqua/extension/common_handler.py +21 -0
  19. ads/aqua/extension/deployment_handler.py +202 -0
  20. ads/aqua/extension/evaluation_handler.py +135 -0
  21. ads/aqua/extension/finetune_handler.py +66 -0
  22. ads/aqua/extension/model_handler.py +59 -0
  23. ads/aqua/extension/ui_handler.py +201 -0
  24. ads/aqua/extension/utils.py +23 -0
  25. ads/aqua/finetune.py +579 -0
  26. ads/aqua/job.py +29 -0
  27. ads/aqua/model.py +819 -0
  28. ads/aqua/training/__init__.py +4 -0
  29. ads/aqua/training/exceptions.py +459 -0
  30. ads/aqua/ui.py +453 -0
  31. ads/aqua/utils.py +715 -0
  32. ads/cli.py +37 -6
  33. ads/common/decorator/__init__.py +7 -3
  34. ads/common/decorator/require_nonempty_arg.py +65 -0
  35. ads/common/object_storage_details.py +166 -7
  36. ads/common/oci_client.py +18 -1
  37. ads/common/oci_logging.py +2 -2
  38. ads/common/oci_mixin.py +4 -5
  39. ads/common/serializer.py +34 -5
  40. ads/common/utils.py +75 -10
  41. ads/config.py +40 -1
  42. ads/jobs/ads_job.py +43 -25
  43. ads/jobs/builders/infrastructure/base.py +4 -2
  44. ads/jobs/builders/infrastructure/dsc_job.py +49 -39
  45. ads/jobs/builders/runtimes/base.py +71 -1
  46. ads/jobs/builders/runtimes/container_runtime.py +4 -4
  47. ads/jobs/builders/runtimes/pytorch_runtime.py +10 -63
  48. ads/jobs/templates/driver_pytorch.py +27 -10
  49. ads/model/artifact_downloader.py +84 -14
  50. ads/model/artifact_uploader.py +25 -23
  51. ads/model/datascience_model.py +388 -38
  52. ads/model/deployment/model_deployment.py +10 -2
  53. ads/model/generic_model.py +8 -0
  54. ads/model/model_file_description_schema.json +68 -0
  55. ads/model/model_metadata.py +1 -1
  56. ads/model/service/oci_datascience_model.py +34 -5
  57. ads/opctl/operator/lowcode/anomaly/README.md +2 -1
  58. ads/opctl/operator/lowcode/anomaly/__main__.py +10 -4
  59. ads/opctl/operator/lowcode/anomaly/environment.yaml +2 -1
  60. ads/opctl/operator/lowcode/anomaly/model/automlx.py +12 -6
  61. ads/opctl/operator/lowcode/forecast/README.md +3 -2
  62. ads/opctl/operator/lowcode/forecast/environment.yaml +3 -2
  63. ads/opctl/operator/lowcode/forecast/model/automlx.py +12 -23
  64. ads/telemetry/base.py +62 -0
  65. ads/telemetry/client.py +105 -0
  66. ads/telemetry/telemetry.py +6 -3
  67. {oracle_ads-2.10.1.dist-info → oracle_ads-2.11.0.dist-info}/METADATA +37 -7
  68. {oracle_ads-2.10.1.dist-info → oracle_ads-2.11.0.dist-info}/RECORD +71 -36
  69. {oracle_ads-2.10.1.dist-info → oracle_ads-2.11.0.dist-info}/LICENSE.txt +0 -0
  70. {oracle_ads-2.10.1.dist-info → oracle_ads-2.11.0.dist-info}/WHEEL +0 -0
  71. {oracle_ads-2.10.1.dist-info → oracle_ads-2.11.0.dist-info}/entry_points.txt +0 -0
ads/cli.py CHANGED
@@ -1,13 +1,15 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8 -*--
3
3
 
4
- # Copyright (c) 2021, 2023 Oracle and/or its affiliates.
4
+ # Copyright (c) 2021, 2024 Oracle and/or its affiliates.
5
5
  # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
6
6
 
7
7
  import traceback
8
8
  import sys
9
9
 
10
+ import fire
10
11
  from ads.common import logger
12
+ from ads.aqua.cli import AquaCommand
11
13
 
12
14
  try:
13
15
  import click
@@ -37,14 +39,43 @@ ADS_VERSION = metadata.version("oracle_ads")
37
39
  @click.group()
38
40
  @click.version_option(version=ADS_VERSION, prog_name="ads")
39
41
  @click.help_option("--help", "-h")
40
- def cli():
42
+ def click_cli():
41
43
  pass
42
44
 
43
45
 
44
- cli.add_command(ads.opctl.cli.commands)
45
- cli.add_command(ads.jobs.cli.commands)
46
- cli.add_command(ads.pipeline.cli.commands)
47
- cli.add_command(ads.opctl.operator.cli.commands)
46
+ @click.command
47
+ def aqua_cli():
48
+ """CLI for AQUA."""
49
+ # This is a dummy entry for click.
50
+ # The `ads aqua` commands are handled by AquaCommand
51
+
52
+
53
+ click_cli.add_command(ads.opctl.cli.commands)
54
+ click_cli.add_command(ads.jobs.cli.commands)
55
+ click_cli.add_command(ads.pipeline.cli.commands)
56
+ click_cli.add_command(ads.opctl.operator.cli.commands)
57
+ click_cli.add_command(aqua_cli, name="aqua")
58
+
59
+
60
+ # fix for fire issue with --help
61
+ # https://github.com/google/python-fire/issues/258
62
+ def _SeparateFlagArgs(args):
63
+ try:
64
+ index = args.index("--help")
65
+ args = args[:index]
66
+ return args, ["--help"]
67
+ except ValueError:
68
+ return args, []
69
+
70
+
71
+ fire.core.parser.SeparateFlagArgs = _SeparateFlagArgs
72
+
73
+
74
+ def cli():
75
+ if len(sys.argv) > 1 and sys.argv[1] == "aqua":
76
+ fire.Fire(AquaCommand, command=sys.argv[2:], name="ads aqua")
77
+ else:
78
+ click_cli()
48
79
 
49
80
 
50
81
  if __name__ == "__main__":
@@ -1,5 +1,9 @@
1
1
  #!/usr/bin/env python
2
- # -*- coding: utf-8; -*-
3
-
4
- # Copyright (c) 2020, 2022 Oracle and its affiliates.
2
+ # -*- coding: utf-8 -*--
3
+ # Copyright (c) 2024 Oracle and/or its affiliates.
5
4
  # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
5
+
6
+ from ads.common.decorator.require_nonempty_arg import require_nonempty_arg
7
+ from ads.common.decorator.argument_to_case import argument_to_case
8
+ from ads.common.decorator.deprecate import deprecated
9
+ from ads.common.decorator.runtime_dependency import runtime_dependency
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*--
3
+ # Copyright (c) 2024 Oracle and/or its affiliates.
4
+ # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
5
+
6
+ import inspect
7
+ from functools import wraps
8
+ from typing import Any, Callable, List, Union
9
+
10
+ from ads.common.decorator.utils import _get_original_func
11
+
12
+
13
+ def require_nonempty_arg(
14
+ arg_name: Union[str, List[str]], error_msg: str = "A required argument is empty"
15
+ ) -> Callable:
16
+ """
17
+ A decorator to ensure that a specific argument of a function is not empty.
18
+
19
+ Parameters
20
+ ----------
21
+ arg_name (Union[str, List[str]]): The name of the argument or the list of the arguments to check.
22
+ error_msg (str, optional)
23
+ The error message to raise if the check fails.
24
+
25
+ Returns
26
+ -------
27
+ Callable
28
+ A wrapped function that includes the check.
29
+
30
+ Raises
31
+ ------
32
+ ValueError
33
+ If the specified argument is empty.
34
+ """
35
+
36
+ def decorator(func: Callable) -> Callable:
37
+ @wraps(func)
38
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
39
+ # Retrieving the original function from the decorated one.
40
+ # This is necessary when the chain of decorators is used.
41
+ # The only original function arguments should be processed.
42
+ original_func = _get_original_func(func)
43
+
44
+ # Get the signature of the function
45
+ sig = inspect.signature(original_func)
46
+ bound_args = sig.bind(*args, **kwargs)
47
+ bound_args.apply_defaults()
48
+
49
+ # Check if the argument is present and not empty
50
+ if isinstance(arg_name, str):
51
+ arguments_to_check = [arg_name]
52
+ else:
53
+ arguments_to_check = arg_name
54
+
55
+ if not any(
56
+ check_name in bound_args.arguments and bound_args.arguments[check_name]
57
+ for check_name in arguments_to_check
58
+ ):
59
+ raise ValueError(error_msg)
60
+
61
+ return func(*args, **kwargs)
62
+
63
+ return wrapper
64
+
65
+ return decorator
@@ -1,18 +1,24 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8 -*--
3
3
 
4
- # Copyright (c) 2021, 2023 Oracle and/or its affiliates.
4
+ # Copyright (c) 2021, 2024 Oracle and/or its affiliates.
5
5
  # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
6
6
 
7
7
  import json
8
8
  import os
9
9
  import re
10
10
  from dataclasses import dataclass
11
- from typing import Dict
11
+ from typing import Dict, List
12
12
  from urllib.parse import urlparse
13
13
 
14
+
15
+ import oci
14
16
  from ads.common import auth as authutil
15
17
  from ads.common import oci_client
18
+ from ads.dataset.progress import TqdmProgressBar
19
+ from concurrent.futures import ThreadPoolExecutor, as_completed
20
+
21
+ THREAD_POOL_MAX_WORKERS = 10
16
22
 
17
23
 
18
24
  class InvalidObjectStoragePath(Exception): # pragma: no cover
@@ -33,6 +39,8 @@ class ObjectStorageDetails:
33
39
  The Object Storage namespace. Will be extracted automatically if not provided.
34
40
  filepath: (str, optional). Defaults to empty string.
35
41
  The path to the object.
42
+ version: (str, optional). Defaults to None.
43
+ The version of the object.
36
44
  auth: (Dict, optional). Defaults to None.
37
45
  ADS auth dictionary for OCI authentication.
38
46
  This can be generated by calling ads.common.auth.api_keys() or ads.common.auth.resource_principal()
@@ -42,6 +50,7 @@ class ObjectStorageDetails:
42
50
  bucket: str
43
51
  namespace: str = ""
44
52
  filepath: str = ""
53
+ version: str = None
45
54
  auth: Dict = None
46
55
 
47
56
  def __post_init__(self):
@@ -49,8 +58,16 @@ class ObjectStorageDetails:
49
58
  self.auth = authutil.default_signer()
50
59
  # Extract OS namespace if not provided.
51
60
  if not self.namespace:
52
- os_client = oci_client.OCIClientFactory(**self.auth).object_storage
53
- self.namespace = os_client.get_namespace().data
61
+ self.namespace = self.os_client.get_namespace().data
62
+
63
+ @property
64
+ def os_client(self):
65
+ if not hasattr(self, "__client"):
66
+ self.__client = self.create_os_client()
67
+ return self.__client
68
+
69
+ def create_os_client(self):
70
+ return oci_client.OCIClientFactory(**self.auth).object_storage
54
71
 
55
72
  def __repr__(self):
56
73
  return self.path
@@ -86,7 +103,7 @@ class ObjectStorageDetails:
86
103
  url_parse = urlparse(env_path)
87
104
  bucket_name = url_parse.username
88
105
  namespace = url_parse.hostname
89
- object_name = url_parse.path.strip("/")
106
+ object_name = url_parse.path.lstrip("/")
90
107
  return cls(bucket=bucket_name, namespace=namespace, filepath=object_name)
91
108
  except:
92
109
  raise Exception(
@@ -106,8 +123,7 @@ class ObjectStorageDetails:
106
123
  Dict
107
124
  The metadata in dictionary format.
108
125
  """
109
- os_client = oci_client.OCIClientFactory(**self.auth).object_storage
110
- res = os_client.get_object(self.namespace, self.bucket, self.filepath)
126
+ res = self.os_client.get_object(self.namespace, self.bucket, self.filepath)
111
127
  metadata = res.data.headers["opc-meta-manifest"]
112
128
  metadata_json = json.loads(metadata)
113
129
  return metadata_json
@@ -138,3 +154,146 @@ class ObjectStorageDetails:
138
154
  if not uri:
139
155
  return False
140
156
  return uri.lower().startswith("oci://")
157
+
158
+ def is_bucket_versioned(self) -> bool:
159
+ """Check if the given bucket is versioned.
160
+ Returns
161
+ -------
162
+ bool: return True if the bucket is versioned.
163
+
164
+ """
165
+ res = self.os_client.get_bucket(
166
+ namespace_name=self.namespace, bucket_name=self.bucket
167
+ ).data
168
+ return res.versioning == "Enabled"
169
+
170
+ def list_objects(self, **kwargs):
171
+ """Lists objects in a given oss path
172
+
173
+ Parameters
174
+ -------
175
+ **kwargs:
176
+ namespace, bucket, filepath are set by the class. By default, fields gets all values. For other supported
177
+ parameters, check https://docs.oracle.com/iaas/api/#/en/objectstorage/20160918/Object/ListObjects
178
+
179
+ Returns
180
+ -------
181
+ Object of type oci.object_storage.models.ListObjects
182
+ """
183
+ fields = kwargs.pop(
184
+ "fields",
185
+ "name,etag,size,timeCreated,md5,timeModified,storageTier,archivalState",
186
+ )
187
+
188
+ objects = oci.pagination.list_call_get_all_results(
189
+ self.os_client.list_objects,
190
+ namespace_name=self.namespace,
191
+ bucket_name=self.bucket,
192
+ prefix=self.filepath,
193
+ fields=fields,
194
+ **kwargs,
195
+ ).data
196
+ return objects
197
+
198
+ def list_object_versions(
199
+ self,
200
+ **kwargs,
201
+ ):
202
+ """Lists object versions in a given oss path
203
+
204
+ Parameters
205
+ -------
206
+ **kwargs:
207
+ namespace, bucket, filepath are set by the class. By default, fields gets all values. For other supported
208
+ parameters, check https://docs.oracle.com/iaas/api/#/en/objectstorage/20160918/Object/ListObjectVersions
209
+
210
+ Returns
211
+ -------
212
+ Object of type oci.object_storage.models.ObjectVersionCollection
213
+ """
214
+ fields = kwargs.pop(
215
+ "fields",
216
+ "name,etag,size,timeCreated,md5,timeModified,storageTier,archivalState",
217
+ )
218
+
219
+ objects = oci.pagination.list_call_get_all_results(
220
+ self.os_client.list_object_versions,
221
+ namespace_name=self.namespace,
222
+ bucket_name=self.bucket,
223
+ prefix=self.filepath,
224
+ fields=fields,
225
+ **kwargs,
226
+ ).data
227
+ return objects
228
+
229
+ def download_from_object_storage(
230
+ self,
231
+ path: "ObjectStorageDetails",
232
+ target_dir: str,
233
+ progress_bar: TqdmProgressBar = None,
234
+ ):
235
+ """Downloads the files with object versions set in the paths dict.
236
+
237
+ Parameters
238
+ ----------
239
+ path:
240
+ OSS path along with a value of file version id.
241
+ If version_id is not available, download the latest version.
242
+ target_dir:
243
+ Local directory to save the files
244
+ progress_bar:
245
+ an instance of the TqdmProgressBar, can update description in the calling progress bar
246
+
247
+ Returns
248
+ -------
249
+ None
250
+ """
251
+ if progress_bar:
252
+ progress_bar.update(
253
+ description=f"Copying model artifacts by reference from {path.path} to {target_dir}",
254
+ n=0,
255
+ )
256
+ res = self.os_client.get_object(
257
+ namespace_name=path.namespace,
258
+ bucket_name=path.bucket,
259
+ object_name=path.filepath,
260
+ version_id=path.version,
261
+ )
262
+ local_filepath = os.path.join(target_dir, path.bucket, path.filepath)
263
+ os.makedirs(os.path.dirname(local_filepath), exist_ok=True)
264
+
265
+ with open(local_filepath, "wb") as _file:
266
+ for chunk in res.data.iter_content(chunk_size=4096):
267
+ _file.write(chunk)
268
+
269
+ def bulk_download_from_object_storage(
270
+ self,
271
+ paths: List["ObjectStorageDetails"],
272
+ target_dir: str,
273
+ progress_bar: TqdmProgressBar = None,
274
+ ):
275
+ """Downloads the files with object versions set in the paths dict parallely.
276
+
277
+ Parameters
278
+ ----------
279
+ paths:
280
+ Contains a list of OSS paths along with a value of file version id.
281
+ If version_id is not available, download the latest version.
282
+ target_dir:
283
+ Local directory to save the files
284
+ progress_bar:
285
+ an instance of the TqdmProgressBar, can update description in the calling progress bar
286
+
287
+ Returns
288
+ -------
289
+ None
290
+ """
291
+ with ThreadPoolExecutor(max_workers=THREAD_POOL_MAX_WORKERS) as pool:
292
+ futures = {
293
+ pool.submit(
294
+ self.download_from_object_storage, path, target_dir, progress_bar
295
+ ): path
296
+ for path in paths
297
+ }
298
+ for future in as_completed(futures):
299
+ future.result()
ads/common/oci_client.py CHANGED
@@ -20,12 +20,14 @@ from oci.object_storage import ObjectStorageClient
20
20
  from oci.resource_search import ResourceSearchClient
21
21
  from oci.secrets import SecretsClient
22
22
  from oci.vault import VaultsClient
23
+ from oci.logging import LoggingManagementClient
24
+ from oci.core import VirtualNetworkClient
25
+ from oci.limits import LimitsClient
23
26
 
24
27
  logger = logging.getLogger(__name__)
25
28
 
26
29
 
27
30
  class OCIClientFactory:
28
-
29
31
  """
30
32
  A factory class to create OCI client objects. The constructor takes in config, signer and client_kwargs. `client_kwargs` is passed
31
33
  to the client constructor as key word arguments.
@@ -72,6 +74,9 @@ class OCIClientFactory:
72
74
  "data_labeling_cp": DataLabelingManagementClient,
73
75
  "resource_search": ResourceSearchClient,
74
76
  "data_catalog": DataCatalogClient,
77
+ "logging_management": LoggingManagementClient,
78
+ "virtual_network": VirtualNetworkClient,
79
+ "limits": LimitsClient,
75
80
  "marketplace": MarketplaceClient,
76
81
  "artifacts": ArtifactsClient,
77
82
  }
@@ -149,6 +154,18 @@ class OCIClientFactory:
149
154
  def data_catalog(self):
150
155
  return self.create_client("data_catalog")
151
156
 
157
+ @property
158
+ def logging_management(self):
159
+ return self.create_client("logging_management")
160
+
161
+ @property
162
+ def virtual_network(self):
163
+ return self.create_client("virtual_network")
164
+
165
+ @property
166
+ def limits(self):
167
+ return self.create_client("limits")
168
+
152
169
  @property
153
170
  def marketplace(self):
154
171
  return self.create_client("marketplace")
ads/common/oci_logging.py CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8; -*-
3
3
 
4
- # Copyright (c) 2021, 2022 Oracle and/or its affiliates.
4
+ # Copyright (c) 2021, 2024 Oracle and/or its affiliates.
5
5
  # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
6
6
 
7
7
  import datetime
@@ -384,7 +384,7 @@ class OCILog(OCILoggingModelMixin, oci.logging.models.Log):
384
384
  records = []
385
385
  result_too_large = True
386
386
  else:
387
- raise oci.exceptions.ServiceError from ex
387
+ raise ex
388
388
  if result_too_large or len(records) >= LIMIT_PER_REQUEST:
389
389
  mid = time_start + (time_end - time_start) / 2
390
390
  # The log search API used RFC3339 time format.
ads/common/oci_mixin.py CHANGED
@@ -798,14 +798,13 @@ class OCIModelMixin(OCISerializableMixin):
798
798
  logger.error(
799
799
  "Failed to synchronize the properties of %s due to service error:\n%s",
800
800
  self.__class__,
801
- str(ex),
801
+ traceback.format_exc(),
802
802
  )
803
- except Exception as ex:
803
+ except Exception:
804
804
  logger.error(
805
- "Failed to synchronize the properties of %s: %s\n%s",
805
+ "Failed to synchronize the properties of %s.\n%s",
806
806
  self.__class__,
807
- type(ex),
808
- str(ex),
807
+ traceback.format_exc(),
809
808
  )
810
809
  return super().__getattribute__(name)
811
810
 
ads/common/serializer.py CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8; -*-
3
3
 
4
- # Copyright (c) 2021, 2023 Oracle and/or its affiliates.
4
+ # Copyright (c) 2021, 2024 Oracle and/or its affiliates.
5
5
  # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
6
6
 
7
7
  """
@@ -13,6 +13,7 @@ writing serialized objects to and from files.
13
13
  import dataclasses
14
14
  import json
15
15
  from abc import ABC, abstractmethod
16
+ from datetime import datetime
16
17
  from enum import Enum
17
18
  from typing import Dict, Optional, Union
18
19
  from urllib.parse import urlparse
@@ -93,6 +94,13 @@ class Serializable(ABC):
93
94
  """
94
95
  pass
95
96
 
97
+ @staticmethod
98
+ def serialize(obj):
99
+ """JSON serializer for objects not serializable by default json code."""
100
+ if isinstance(obj, datetime):
101
+ return obj.isoformat()
102
+ raise TypeError(f"Type {type(obj)} not serializable.")
103
+
96
104
  @staticmethod
97
105
  def _write_to_file(s: str, uri: str, **kwargs) -> None:
98
106
  """Write string s into location specified by uri.
@@ -153,7 +161,11 @@ class Serializable(ABC):
153
161
  return f.read()
154
162
 
155
163
  def to_json(
156
- self, uri: str = None, encoder: callable = json.JSONEncoder, **kwargs
164
+ self,
165
+ uri: str = None,
166
+ encoder: callable = json.JSONEncoder,
167
+ default: callable = None,
168
+ **kwargs,
157
169
  ) -> str:
158
170
  """Returns object serialized as a JSON string
159
171
 
@@ -163,6 +175,9 @@ class Serializable(ABC):
163
175
  URI location to save the JSON string. Defaults to None.
164
176
  encoder: (callable, optional)
165
177
  Encoder for custom data structures. Defaults to JSONEncoder.
178
+ default: (callable, optional)
179
+ A function that gets called for objects that can't otherwise be serialized.
180
+ It should return JSON-serializable version of the object or original object.
166
181
 
167
182
  kwargs
168
183
  ------
@@ -179,7 +194,9 @@ class Serializable(ABC):
179
194
  Serialized version of object.
180
195
  `None` in case when `uri` provided.
181
196
  """
182
- json_string = json.dumps(self.to_dict(**kwargs), cls=encoder)
197
+ json_string = json.dumps(
198
+ self.to_dict(**kwargs), cls=encoder, default=default or self.serialize
199
+ )
183
200
  if uri:
184
201
  self._write_to_file(s=json_string, uri=uri, **kwargs)
185
202
  return None
@@ -337,13 +354,23 @@ class Serializable(ABC):
337
354
  def __repr__(self):
338
355
  """Returns printable version of object.
339
356
 
340
- Parameters
357
+ Returns
341
358
  ----------
342
359
  string
343
360
  Serialized version of object as a YAML string
344
361
  """
345
362
  return self.to_yaml()
346
363
 
364
+ def __str__(self):
365
+ """Returns printable version of object.
366
+
367
+ Returns
368
+ ----------
369
+ string
370
+ Serialized version of object as a YAML string
371
+ """
372
+ return self.to_json()
373
+
347
374
 
348
375
  class DataClassSerializable(Serializable):
349
376
  """Wrapper class that inherit from Serializable class.
@@ -436,7 +463,9 @@ class DataClassSerializable(Serializable):
436
463
  "These fields will be ignored."
437
464
  )
438
465
 
439
- obj = cls(**{key: obj_dict.get(key) for key in allowed_fields})
466
+ obj = cls(
467
+ **{key: obj_dict.get(key) for key in allowed_fields if key in obj_dict}
468
+ )
440
469
 
441
470
  for key, value in obj_dict.items():
442
471
  if (
ads/common/utils.py CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8; -*-
3
3
 
4
- # Copyright (c) 2020, 2023 Oracle and/or its affiliates.
4
+ # Copyright (c) 2020, 2024 Oracle and/or its affiliates.
5
5
  # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
6
6
 
7
7
  from __future__ import absolute_import, print_function
@@ -33,29 +33,25 @@ import fsspec
33
33
  import matplotlib as mpl
34
34
  import numpy as np
35
35
  import pandas as pd
36
- from ads.common import logger
37
- from ads.common.decorator.deprecate import deprecated
38
- from ads.common.word_lists import adjectives, animals
39
- from ads.dataset.progress import TqdmProgressBar
40
36
  from cycler import cycler
37
+ from oci import object_storage
41
38
  from pandas.core.dtypes.common import is_datetime64_dtype, is_numeric_dtype
42
39
  from sklearn.model_selection import train_test_split
43
40
  from tqdm import tqdm
44
41
 
42
+ from ads import config
45
43
  from ads.common import logger
46
44
  from ads.common.decorator.deprecate import deprecated
47
45
  from ads.common.decorator.runtime_dependency import (
48
46
  OptionalDependency,
49
47
  runtime_dependency,
50
48
  )
49
+ from ads.common.object_storage_details import ObjectStorageDetails
50
+ from ads.common.oci_client import OCIClientFactory
51
51
  from ads.common.word_lists import adjectives, animals
52
- from ads import config
53
- from ads.dataset.progress import DummyProgressBar, TqdmProgressBar
52
+ from ads.dataset.progress import TqdmProgressBar
54
53
 
55
54
  from . import auth as authutil
56
- from oci import object_storage
57
- from ads.common.oci_client import OCIClientFactory
58
- from ads.common.object_storage_details import ObjectStorageDetails
59
55
 
60
56
  # For Model / Model Artifact libraries
61
57
  lib_translator = {"sklearn": "scikit-learn"}
@@ -1717,3 +1713,72 @@ def upload_to_os(
1717
1713
  )
1718
1714
 
1719
1715
  return response
1716
+
1717
+
1718
+ def get_console_link(
1719
+ resource: str,
1720
+ ocid: str,
1721
+ region: str,
1722
+ ) -> str:
1723
+ """
1724
+ This method returns the web console link for the given resource.
1725
+ Parameters
1726
+ ----------
1727
+ resource: str
1728
+ identify the type of OCI resource. {model, model-deployments, notebook-sessions, jobs} is supported.
1729
+ ocid: str
1730
+ OCID of the resource
1731
+ region: str
1732
+ The Region Identifier that the client should connect to.
1733
+
1734
+ Returns
1735
+ -------
1736
+ console_link_url: str
1737
+ a valid link to the console for the given resource
1738
+ """
1739
+ console_link_url = (
1740
+ f"https://cloud.oracle.com/data-science/{resource}/{ocid}?region={region}"
1741
+ )
1742
+ return console_link_url
1743
+
1744
+
1745
+ def get_log_links(
1746
+ region: str,
1747
+ log_group_id: str,
1748
+ compartment_id: str = None,
1749
+ log_id: str = None,
1750
+ source_id: str = None,
1751
+ ) -> str:
1752
+ """
1753
+ This method returns the web console link for the given log ids.
1754
+
1755
+ Parameters
1756
+ ----------
1757
+ log_group_id: str, required
1758
+ OCID of the resource
1759
+ log_id: str, optional
1760
+ OCID of the resource
1761
+ region: str
1762
+ The Region Identifier that the client should connect to.
1763
+ compartment_id: str, optional
1764
+ The compartment OCID of the resource.
1765
+ source_id: str, optional
1766
+ The OCID of the resource.
1767
+
1768
+ Returns
1769
+ -------
1770
+ console_link_url: str
1771
+ a valid link to the console for the given resource.
1772
+ """
1773
+ console_link_url = ""
1774
+ if log_group_id and log_id:
1775
+ # format: https://cloud.oracle.com/logging/search?searchQuery=search "<compartment>/<log_group>/<log>" | source='<source>' | sort by datetime desc&regions=<region>
1776
+ query_range = f'''search "{compartment_id}/{log_group_id}/{log_id}"'''
1777
+ query_source = f"source='{source_id}'"
1778
+ sort_condition = f"sort by datetime desc&regions={region}"
1779
+ search_query = f"search?searchQuery={query_range} | {query_source} | {sort_condition}"
1780
+ console_link_url = f"https://cloud.oracle.com/logging/{search_query}"
1781
+ elif log_group_id:
1782
+ console_link_url = f"https://cloud.oracle.com/logging/log-groups/{log_group_id}?region={region}"
1783
+
1784
+ return console_link_url