44# Copyright (c) 2021, 2023 Oracle and/or its affiliates.
55# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
66
7+ import dataclasses
78import json
89from abc import ABC , abstractmethod
9- import dataclasses
10- from typing import Dict , Union , Optional , List
1110from enum import Enum
11+ from typing import Dict , Optional , Union
12+ from urllib .parse import urlparse
1213
1314import fsspec
1415import yaml
16+
1517from ads .common import logger
1618
1719try :
@@ -53,15 +55,19 @@ class Serializable(ABC):
5355 """
5456
5557 @abstractmethod
56- def to_dict (self , ** kwargs ) -> dict :
57- """Serializes instance of class into a dictionary.
58+ def to_dict (self , ** kwargs : Dict ) -> Dict :
59+ """Serializes an instance of class into a dictionary.
60+
61+ Parameters
62+ ----------
63+ **kwargs: Dict
64+ Additional arguments.
5865
5966 Returns
6067 -------
6168 Dict
62- A dictionary.
69+ The result dictionary.
6370 """
64- pass
6571
6672 @classmethod
6773 @abstractmethod
@@ -90,17 +96,25 @@ def _write_to_file(s: str, uri: str, **kwargs) -> None:
9096 content
9197 uri: (string)
9298 URI location to save string s
93-
94- kwargs
95- ------
96- keyword arguments to be passed into fsspec.open(). For OCI object storage, this should be config="path/to/.oci/config".
97- For other storage connections consider e.g. host, port, username, password, etc.
99+ kwargs : dict
100+ keyword arguments to be passed into fsspec.open().
101+ For OCI object storage, this can be config="path/to/.oci/config".
98102
99103 Returns
100104 -------
101105 None
102- Nothing.
106+ Nothing
103107 """
108+
109+ overwrite = kwargs .pop ("overwrite" , True )
110+ if not overwrite :
111+ dst_path_scheme = urlparse (uri ).scheme or "file"
112+ if fsspec .filesystem (dst_path_scheme , ** kwargs ).exists (uri ):
113+ raise FileExistsError (
114+ f"The `{ uri } ` is already exists. Set `overwrite` to True "
115+ "if you wish to overwrite."
116+ )
117+
104118 with fsspec .open (uri , "w" , ** kwargs ) as f :
105119 f .write (s )
106120
@@ -112,15 +126,13 @@ def _read_from_file(uri: str, **kwargs) -> str:
112126 ----------
113127 uri: (string)
114128 URI location
115-
116- kwargs
117- ------
118- keyword arguments to be passed into fsspec.open(). For OCI object storage, this should be config="path/to/.oci/config".
119- For other storage connections consider e.g. host, port, username, password, etc.
129+ kwargs : dict
130+ keyword arguments to be passed into fsspec.open().
131+ For OCI object storage, this can be config="path/to/.oci/config".
120132
121133 Returns
122134 -------
123- string: Contents in file specified by URI
135+ string: Contents in file specified by URI
124136 """
125137 with fsspec .open (uri , "r" , ** kwargs ) as f :
126138 return f .read ()
@@ -139,15 +151,23 @@ def to_json(
139151
140152 kwargs
141153 ------
142- keyword arguments to be passed into fsspec.open( ). For OCI object storage, this should be config="path/to/.oci/config" .
143- For other storage connections consider e.g. host, port, username, password, etc .
154+ overwrite: (bool, optional ). Defaults to True .
155+ Whether to overwrite existing file or not .
144156
145- Returns:
146- string: Serialized version of object
157+ keyword arguments to be passed into fsspec.open().
158+ For OCI object storage, this could be config="path/to/.oci/config".
159+ For other storage connections consider e.g. host, port, username, password, etc.
160+
161+ Returns
162+ -------
163+ Union[str, None]
164+ Serialized version of object.
165+ `None` in case when `uri` provided.
147166 """
148167 json_string = json .dumps (self .to_dict (** kwargs ), cls = encoder )
149168 if uri :
150169 self ._write_to_file (s = json_string , uri = uri , ** kwargs )
170+ return None
151171 return json_string
152172
153173 @classmethod
@@ -190,31 +210,40 @@ def from_json(
190210 return cls .from_dict (json_dict )
191211 raise ValueError ("Must provide either JSON string or URI location" )
192212
193- def to_yaml (self , uri : str = None , dumper : callable = dumper , ** kwargs ) -> str :
213+ def to_yaml (
214+ self , uri : str = None , dumper : callable = yaml .SafeDumper , ** kwargs
215+ ) -> Union [str , None ]:
194216 """Returns object serialized as a YAML string
195217
196218 Parameters
197219 ----------
198- uri: (string, optional)
199- URI location to save the YAML string. Defaults to None.
200- dumper: (callable, optional)
201- Custom YAML Dumper. Defaults to CDumper/SafeDumper.
202-
203- kwargs
204- ------
205- side_effect: Optional[SideEffect]
206- side effect to take on the dictionary. The side effect can be either
207- convert the dictionary keys to "lower" (SideEffect.CONVERT_KEYS_TO_LOWER.value)
208- or "upper"(SideEffect.CONVERT_KEYS_TO_UPPER.value) cases.
209- keyword arguments to be passed into fsspec.open(). For OCI object storage, this should be config="path/to/.oci/config".
210- For other storage connections consider e.g. host, port, username, password, etc.
220+ uri : str, optional
221+ URI location to save the YAML string, by default None
222+ dumper : callable, optional
223+ Custom YAML Dumper, by default yaml.SafeDumper
224+ kwargs : dict
225+ overwrite: (bool, optional). Defaults to True.
226+ Whether to overwrite existing file or not.
227+ note: (str, optional)
228+ The note that needs to be added in the beginning of the YAML.
229+ It will be added as is without any formatting.
230+ side_effect: Optional[SideEffect]
231+ side effect to take on the dictionary. The side effect can be either
232+ convert the dictionary keys to "lower" (SideEffect.CONVERT_KEYS_TO_LOWER.value)
233+ or "upper"(SideEffect.CONVERT_KEYS_TO_UPPER.value) cases.
234+
235+ The other keyword arguments to be passed into fsspec.open().
236+ For OCI object storage, this could be config="path/to/.oci/config".
211237
212- Returns:
213- Union[str, None]
214- Serialized version of object.
215- None in case when `uri` provided.
238+ Returns
239+ -------
240+ Union[str, None]
241+ Serialized version of object.
242+ `None` in case when `uri` provided.
216243 """
217- yaml_string = yaml .dump (self .to_dict (** kwargs ), Dumper = dumper )
244+ note = kwargs .pop ("note" , "" )
245+
246+ yaml_string = f"{ note } \n " + yaml .dump (self .to_dict (** kwargs ), Dumper = dumper )
218247 if uri :
219248 self ._write_to_file (s = yaml_string , uri = uri , ** kwargs )
220249 return None
0 commit comments