util.py 3.79 KB
Newer Older
1
"""netdb_client helper functions for configuration and response-parsing"""
Janis Streib's avatar
Janis Streib committed
2
import argparse
3
4
import configparser
import os
5
import stat
Janis Streib's avatar
Janis Streib committed
6
7
8
9
10


class ArgumentParser(argparse.ArgumentParser):
    """Argument parser with default common arguments for NetDB-api cli
    tools. Includes default values."""
11
12
13
14
15
16
17
18
19
20
21
22
23

    def __init__(
            self,
            epilog="The Variables BASE_URL, VERSION and TOKEN can be loaded from config file,"
                   "environment or from command line arguments.\n"
                   "Variable precendence is as followed (from greatest to least,"
                   "means the first listed variable overwrites all other variables):\n"
                   "  1. cli-arguments\n"
                   "  2. environment variables\n"
                   "  3. config-file\n",
            formatter_class=argparse.RawTextHelpFormatter,
            **kwargs
    ):
Dominik Rimpf's avatar
Dominik Rimpf committed
24
25
        super().__init__(formatter_class=formatter_class, epilog=epilog, **kwargs)
        self.add_argument('--auth-config',
26
27
28
29
30
31
32
33
34
35
                          default=os.path.expanduser('~/.config/netdb_client.ini'),
                          help='config file path (default: %(default)s)')
        self.add_argument('--base-url', '-b',
                          help='webapi server.\n'
                               'Environment: "NETDB_BASE_URL"\n'
                               'Config: [DEFAULT]: endpoint')
        self.add_argument('--version',
                          help='webapi version.\n'
                               'Environment: "NETDB_VERSION"\n'
                               'Config: [$endpoint]: version')
Janis Streib's avatar
Janis Streib committed
36
        self.add_argument('--token', '-t',
37
38
39
                          help='user API token.\n'
                               'Environment: "NETDB_TOKEN"\n'
                               'Config: [$endpoint]: token')
Janis Streib's avatar
Janis Streib committed
40

Dominik Rimpf's avatar
Dominik Rimpf committed
41
    def parse_args(self, args=None, namespace=None):
42
43
        args = super().parse_args(args, namespace)
        config = configparser.ConfigParser()
44
45
46
47
48
        configpath = os.path.expanduser(args.auth_config)
        if os.path.isfile(configpath):
            if os.stat(configpath).st_mode & stat.S_IRWXO:
                self.error(f"Config file is readable by others. Please set it at least to 660.")
            config.read(configpath)
49
50
51
52
53
54
55
56
57
58
59
60

        def load_configoption(option):
            if getattr(args, option) is None:
                setattr(args, option, os.getenv(f'NETDB_{option.upper()}', None))
                if getattr(args, option) is None:
                    if option == 'base_url':
                        setattr(args, option, config.get('DEFAULT', 'endpoint', fallback=None))
                    else:
                        setattr(args, option, config.get(args.base_url, option, fallback=None))
                    if getattr(args, option) is None:
                        self.error(
                            f'No {option} specified (looked in args, environment variable '
61
                            f'"NETDB_{option.upper()}", config-file in "{args.auth_config}")'
62
63
64
65
66
67
                        )

        # load base_url first!
        for configoption in ['base_url', 'token', 'version']:
            load_configoption(configoption)

Janis Streib's avatar
Janis Streib committed
68
69
        return args

Dominik Rimpf's avatar
Dominik Rimpf committed
70

71
72
73
74
def list_to_generator_map_one2one(array, key_name):
    """Mapping function to convert list of dicts to an mapping with value as key for each dict
    (1 to 1 Mapping). Returns an generator object."""
    return ((item[key_name], item) for item in array)
Dominik Rimpf's avatar
Dominik Rimpf committed
75
76


77
78
79
def list_to_generator_map_one2many(array, key_name):
    """Mapping function to convert list of dicts to an mapping with values as key for each lists
     (1 to n Mapping). Returns an generator object."""
Dominik Rimpf's avatar
Dominik Rimpf committed
80
81
    res = {}
    for item in array:
82
83
84
        if not item[key_name] in res:
            res[item[key_name]] = []
        res[item[key_name]].append(item)
85
86
    for key, value in res.items():
        yield key, value