9
9
from pathlib import Path
10
10
from shutil import rmtree
11
11
from typing import Any , Callable , Dict , List , NamedTuple , Tuple , Union , cast , no_type_check
12
+ from warnings import warn
12
13
from xml .etree import ElementTree as ET
13
14
14
15
import yaml
16
+ from cattrs import structure
17
+ from cattrs .errors import ClassValidationError
15
18
from gooddata_api_client import ApiAttributeError
16
19
from gooddata_api_client .model_utils import OpenApiModel
17
20
18
21
from gooddata_sdk .compute .model .base import ObjId
22
+ from gooddata_sdk .config import AacConfig , Profile
19
23
20
24
# Use typing collection types to support python < py3.9
21
25
IdObjType = Union [str , ObjId , Dict [str , Dict [str , str ]], Dict [str , str ]]
@@ -241,6 +245,43 @@ def mandatory_profile_content_check(profile: str, profile_content_keys: KeysView
241
245
raise ValueError (f"Profile { profile } is missing mandatory parameter or parameters { missing_str } ." )
242
246
243
247
248
+ def _create_profile_legacy (content : Dict ) -> Dict :
249
+ try :
250
+ return structure (content , Profile ).to_dict ()
251
+ except ClassValidationError as e :
252
+ errors = []
253
+ for error in e .exceptions :
254
+ if isinstance (error , KeyError ):
255
+ errors .append (f"Profile file does not contain mandatory parameter: { e } " )
256
+ msg = "\n " .join (errors )
257
+ if not msg :
258
+ msg = "An error occurred while parsing the profile file."
259
+ raise ValueError (msg )
260
+
261
+
262
+ def _create_profile_aac (profile : str , content : Dict ) -> Dict :
263
+ aac_config = AacConfig .from_dict (content )
264
+ selected_profile = aac_config .default_profile if profile == "default" else profile
265
+ if selected_profile not in aac_config .profiles :
266
+ raise ValueError (f"Profile file does not contain the specified profile: { profile } " )
267
+ return aac_config .profiles [selected_profile ].to_dict (use_env = True )
268
+
269
+
270
+ def _get_profile (profile : str , content : Dict ) -> Dict [str , Any ]:
271
+ is_aac_config = AacConfig .can_structure (content )
272
+ if not is_aac_config and profile not in content :
273
+ raise ValueError ("Configuration is invalid. Please check the documentation for the valid configuration." )
274
+ if is_aac_config :
275
+ return _create_profile_aac (profile , content )
276
+ else :
277
+ warn (
278
+ "Used configuration is deprecated and will be removed in the future. Please use the new configuration." ,
279
+ DeprecationWarning ,
280
+ stacklevel = 2 ,
281
+ )
282
+ return _create_profile_legacy (content [profile ])
283
+
284
+
244
285
def profile_content (profile : str = "default" , profiles_path : Path = PROFILES_FILE_PATH ) -> dict [str , Any ]:
245
286
"""Get the profile content from a given file.
246
287
@@ -263,10 +304,9 @@ def profile_content(profile: str = "default", profiles_path: Path = PROFILES_FIL
263
304
if not profiles_path .exists ():
264
305
raise ValueError (f"There is no profiles file located for path { profiles_path } ." )
265
306
content = read_layout_from_file (profiles_path )
266
- if not content .get (profile ):
267
- raise ValueError (f"Profiles file does not contain profile { profile } ." )
268
- mandatory_profile_content_check (profile , content [profile ].keys ())
269
- return {key : content [profile ][key ] for key in content [profile ] if key in SDK_PROFILE_KEYS }
307
+ if content is None :
308
+ raise ValueError (f"The config file is empty { profiles_path } ." )
309
+ return _get_profile (profile , content )
270
310
271
311
272
312
def good_pandas_profile_content (
@@ -288,7 +328,7 @@ def good_pandas_profile_content(
288
328
The content and custom Headers.
289
329
"""
290
330
content = profile_content (profile , profiles_path )
291
- custom_headers = content .pop ("custom_headers" , {})
331
+ custom_headers = content .pop ("custom_headers" , {}) or {}
292
332
content .pop ("extra_user_agent" , None )
293
333
return content , custom_headers
294
334
0 commit comments