Completed
Pull Request — master (#2357)
by Manas
07:53
created

st2client.CLIConfigParser   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 47
Duplicated Lines 0 %
Metric Value
wmc 13
dl 0
loc 47
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __init__() 0 5 3
F parse() 0 40 10
1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
"""
17
Module for parsing CLI config file.
18
"""
19
20
import os
21
22
from collections import defaultdict
23
24
import six
25
from six.moves.configparser import ConfigParser
26
27
__all__ = [
28
    'CLIConfigParser',
29
30
    'ST2_CONFIG_DIRECTORY',
31
    'ST2_CONFIG_PATH',
32
33
    'CONFIG_DEFAULT_VALUES'
34
]
35
36
ST2_CONFIG_DIRECTORY = '~/.st2'
37
ST2_CONFIG_DIRECTORY = os.path.abspath(os.path.expanduser(ST2_CONFIG_DIRECTORY))
38
39
ST2_CONFIG_PATH = os.path.abspath(os.path.join(ST2_CONFIG_DIRECTORY, 'config'))
40
41
CONFIG_FILE_OPTIONS = {
42
    'general': {
43
        'base_url': {
44
            'type': 'string',
45
            'default': None
46
        },
47
        'api_version': {
48
            'type': 'string',
49
            'default': None
50
        },
51
        'cacert': {
52
            'type': 'string',
53
            'default': None
54
        },
55
        'silence_ssl_warnings': {
56
            'type': 'bool',
57
            'default': False
58
        }
59
    },
60
    'cli': {
61
        'debug': {
62
            'type': 'bool',
63
            'default': False
64
        },
65
        'cache_token': {
66
            'type': 'boolean',
67
            'default': True
68
        }
69
    },
70
    'credentials': {
71
        'username': {
72
            'type': 'string',
73
            'default': None
74
        },
75
        'password': {
76
            'type': 'string',
77
            'default': None
78
        }
79
    },
80
    'api': {
81
        'url': {
82
            'type': 'string',
83
            'default': None
84
        }
85
    },
86
    'auth': {
87
        'url': {
88
            'type': 'string',
89
            'default': None
90
        }
91
    }
92
}
93
94
CONFIG_DEFAULT_VALUES = {}
95
96
for section, keys in six.iteritems(CONFIG_FILE_OPTIONS):
97
    CONFIG_DEFAULT_VALUES[section] = {}
98
99
    for key, options in six.iteritems(keys):
100
        default_value = options['default']
101
        CONFIG_DEFAULT_VALUES[section][key] = default_value
102
103
104
class CLIConfigParser(object):
105
    def __init__(self, config_file_path, validate_config_exists=True):
106
        if validate_config_exists and not os.path.isfile(config_file_path):
107
            raise ValueError('Config file "%s" doesn\'t exist')
108
109
        self.config_file_path = config_file_path
110
111
    def parse(self):
112
        """
113
        Parse the config and return a dict with the parsed values.
114
115
        :rtype: ``dict``
116
        """
117
        result = defaultdict(dict)
118
119
        if not os.path.isfile(self.config_file_path):
120
            # Config doesn't exist, return the default values
121
            return CONFIG_DEFAULT_VALUES
122
123
        config = ConfigParser()
124
        with open(self.config_file_path, 'r') as fp:
125
            config.readfp(fp)
126
127
        for section, keys in six.iteritems(CONFIG_FILE_OPTIONS):
0 ignored issues
show
Comprehensibility Bug introduced by
section is re-defining a name which is already available in the outer-scope (previously defined on line 96).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
Comprehensibility Bug introduced by
keys is re-defining a name which is already available in the outer-scope (previously defined on line 96).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
128
            for key, options in six.iteritems(keys):
0 ignored issues
show
Comprehensibility Bug introduced by
key is re-defining a name which is already available in the outer-scope (previously defined on line 99).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
Comprehensibility Bug introduced by
options is re-defining a name which is already available in the outer-scope (previously defined on line 99).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
129
                key_type = options['type']
130
                key_default_value = options['default']
131
132
                if config.has_option(section, key):
133
                    if key_type in ['str', 'string']:
134
                        get_func = config.get
135
                    elif key_type in ['int', 'integer']:
136
                        get_func = config.getint
137
                    elif key_type in ['float']:
138
                        get_func = config.getfloat
139
                    elif key_type in ['bool', 'boolean']:
140
                        get_func = config.getboolean
141
                    else:
142
                        msg = 'Invalid type "%s" for option "%s"' % (key_type, key)
143
                        raise ValueError(msg)
144
145
                    value = get_func(section, key)
146
                    result[section][key] = value
147
                else:
148
                    result[section][key] = key_default_value
149
150
        return dict(result)
151