1
1
#!/usr/bin/env python
2
2
# -*- coding: utf-8; -*-
3
3
4
- # Copyright (c) 2022 Oracle and/or its affiliates.
4
+ # Copyright (c) 2022, 2023 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 os
8
8
from collections import defaultdict
9
9
from configparser import ConfigParser
10
10
from copy import copy
11
11
from enum import Enum
12
- from typing import Callable , Dict , List , Optional , Tuple , Union , Any
12
+ from typing import Any , Callable , Dict , List , Optional , Tuple , Union
13
+ from urllib .parse import urlparse
13
14
14
15
import fsspec
15
16
import yaml
17
+
16
18
from ads .common import auth as authutil
17
19
from ads .common .decorator .argument_to_case import ArgumentCase , argument_to_case
18
20
@@ -287,6 +289,7 @@ def __init__(
287
289
self ._config_parser = ExtendedConfigParser (uri = self .uri , auth = self .auth )
288
290
289
291
def _on_change (self ):
292
+ """This method will be called when config modified."""
290
293
pass
291
294
292
295
def default (self ) -> ConfigSection :
@@ -345,7 +348,7 @@ def section_set(
345
348
The new config section will be added in case if it doesn't exist.
346
349
Otherwise the existing config section will be merged with the new fields.
347
350
348
- Paramaters
351
+ Parameters
349
352
----------
350
353
key: str
351
354
A key of a config section.
@@ -362,7 +365,7 @@ def section_set(
362
365
Raises
363
366
------
364
367
ValueError
365
- If section with goven key is already exist and `replace` flag set to False.
368
+ If section with given key is already exist and `replace` flag set to False.
366
369
TypeError
367
370
If input `info` has a wrong format.
368
371
"""
@@ -389,7 +392,7 @@ def section_set(
389
392
return self ._config [key ]
390
393
391
394
@argument_to_case (case = ArgumentCase .UPPER , arguments = ["key" ])
392
- def section_remove (self , key : str ) -> None :
395
+ def section_remove (self , key : str ) -> "Config" :
393
396
"""Removes config section form config.
394
397
395
398
Parameters
@@ -404,26 +407,62 @@ def section_remove(self, key: str) -> None:
404
407
"""
405
408
self ._config .pop (key , None )
406
409
self ._on_change ()
410
+ return self
411
+
412
+ def save (
413
+ self ,
414
+ uri : Optional [str ] = None ,
415
+ auth : Optional [Dict ] = None ,
416
+ force_overwrite : Optional [bool ] = False ,
417
+ ) -> "Config" :
418
+ """Saves config to a config file.
407
419
408
- def save (self ) -> None :
409
- """Saves config data to a config file.
420
+ Parameters
421
+ ----------
422
+ uri: (str, optional). Defaults to `~/.ads/config`.
423
+ The path to the config file. Can be local or Object Storage file.
424
+ auth: (Dict, optional). Defaults to None.
425
+ The default authentication is set using `ads.set_auth` API. If you need to override the
426
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
427
+ authentication signer and kwargs required to instantiate IdentityClient object.
428
+ force_overwrite: (bool, optional). Defaults to `False`.
429
+ Overwrites the config if exists.
410
430
411
431
Returns
412
432
-------
413
433
None
414
434
Nothing
415
435
"""
416
- self ._config_parser .with_dict (self .to_dict ()).save ()
436
+ uri = uri or self .uri
437
+ auth = auth or self .auth or authutil .default_signer ()
438
+ self ._config_parser .with_dict (self .to_dict ()).save (
439
+ uri = uri , auth = auth , force_overwrite = force_overwrite
440
+ )
441
+ return self
442
+
443
+ def load (self , uri : Optional [str ] = None , auth : Optional [Dict ] = None ) -> "Config" :
444
+ """Loads config from a config file.
417
445
418
- def load (self ) -> "Config" :
419
- """Loads config data from a config file.
446
+ Parameters
447
+ ----------
448
+ uri: (str, optional). Defaults to `~/.ads/config`.
449
+ The path where the config file needs to be saved. Can be local or Object Storage file.
450
+ auth: (Dict, optional). Defaults to None.
451
+ The default authentication is set using `ads.set_auth` API. If you need to override the
452
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
453
+ authentication signer and kwargs required to instantiate IdentityClient object.
420
454
421
455
Returns
422
456
-------
423
457
Config
424
458
A config object.
425
459
"""
426
- return self .with_dict (self ._config_parser .read ().to_dict ())
460
+ uri = uri or self .uri
461
+ auth = auth or self .auth or authutil .default_signer ()
462
+
463
+ return self .with_dict (
464
+ self ._config_parser .read (uri = uri , auth = auth ).to_dict (), replace = True
465
+ )
427
466
428
467
def with_dict (
429
468
self ,
@@ -507,23 +546,54 @@ def __init__(
507
546
uri: (str, optional). Defaults to `~/.ads/config`.
508
547
The path to the config file. Can be local or Object Storage file.
509
548
auth: (Dict, optional). Defaults to None.
510
- The default authetication is set using `ads.set_auth` API. If you need to override the
549
+ The default authentication is set using `ads.set_auth` API. If you need to override the
511
550
default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
512
551
authentication signer and kwargs required to instantiate IdentityClient object.
513
552
"""
514
553
super ().__init__ (default_section = "EXCLUDE_DEFAULT_SECTION" )
515
554
self .auth = auth or authutil .default_signer ()
516
555
self .uri = uri
517
556
518
- def save (self ) -> None :
557
+ def save (
558
+ self ,
559
+ uri : Optional [str ] = None ,
560
+ auth : Optional [Dict ] = None ,
561
+ force_overwrite : Optional [bool ] = False ,
562
+ ) -> None :
519
563
"""Saves the config to the file.
520
564
565
+ Parameters
566
+ ----------
567
+ uri: (str, optional). Defaults to `~/.ads/config`.
568
+ The path to the config file. Can be local or Object Storage file.
569
+ auth: (Dict, optional). Defaults to None.
570
+ The default authentication is set using `ads.set_auth` API. If you need to override the
571
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
572
+ authentication signer and kwargs required to instantiate IdentityClient object.
573
+ force_overwrite: (bool, optional). Defaults to `False`.
574
+ Overwrites the config if exists.
575
+
521
576
Returns
522
577
-------
523
578
None
524
- nothing
579
+
580
+ Raise
581
+ -----
582
+ FileExistsError
583
+ In case if file exists and force_overwrite is false.
525
584
"""
526
- with fsspec .open (self .uri , mode = "w" , ** self .auth ) as f :
585
+ uri = uri or self .uri
586
+ auth = auth or self .auth or authutil .default_signer ()
587
+
588
+ if not force_overwrite :
589
+ dst_path_scheme = urlparse (uri ).scheme or "file"
590
+ if fsspec .filesystem (dst_path_scheme , ** auth ).exists (uri ):
591
+ raise FileExistsError (
592
+ f"The `{ uri } ` exists. Set `force_overwrite` to True "
593
+ "if you wish to overwrite."
594
+ )
595
+
596
+ with fsspec .open (uri , mode = "w" , ** auth ) as f :
527
597
self .write (f )
528
598
529
599
def to_dict (self ) -> Dict [str , Any ]:
@@ -532,19 +602,31 @@ def to_dict(self) -> Dict[str, Any]:
532
602
Returns
533
603
-------
534
604
Dict[str, Any]
535
- Cofig in a dictionary format.
605
+ Config in a dictionary format.
536
606
"""
537
607
return {s : dict (self [s ]) for s in self .keys () if self [s ]}
538
608
539
- def read (self ) -> "ExtendedConfigParser" :
609
+ def read (
610
+ self , uri : Optional [str ] = None , auth : Optional [Dict ] = None
611
+ ) -> "ExtendedConfigParser" :
540
612
"""Reads config file.
541
613
614
+ uri: (str, optional). Defaults to `~/.ads/config`.
615
+ The path to the config file. Can be local or Object Storage file.
616
+ auth: (Dict, optional). Defaults to None.
617
+ The default authentication is set using `ads.set_auth` API. If you need to override the
618
+ default, use the `ads.common.auth.api_keys` or `ads.common.auth.resource_principal` to create appropriate
619
+ authentication signer and kwargs required to instantiate IdentityClient object.
620
+
542
621
Returns
543
622
-------
544
623
ExtendedConfigParser
545
624
Config parser object.
546
625
"""
547
- with fsspec .open (self .uri , "r" , ** self .auth ) as f :
626
+ uri = uri or self .uri
627
+ auth = auth or self .auth or authutil .default_signer ()
628
+
629
+ with fsspec .open (uri , "r" , ** auth ) as f :
548
630
self .read_string (f .read ())
549
631
return self
550
632
0 commit comments