Newer
Older
Valerio Mariani
committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# This file is part of cfelpyutils.
#
# cfelpyutils is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# cfelpyutils is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with cfelpyutils. If not, see <http://www.gnu.org/licenses/>.
"""
Utilities for parsing command line options and configuration files.
This module contains utilities for parsing of command line options and
configuration files.
"""
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import ast
def _parsing_error(section, option):
# Raise an exception after a parsing error.
raise RuntimeError(
'Error parsing parameter {0} in section [{1}]. Make sure that the '
'syntax is correct: list elements must be separated by commas and '
'dict entries must contain the colon symbol. Strings must be quoted, '
'even in lists and dicts.'.format(
option,
section
)
)
def convert_parameters(config_dict):
"""Convert strings in parameter dictionaries to the corrent data type.
Read a parameter dictionary returned by the ConfigParser python module,
and assign correct types to the parameters, without changing the structure
of the dictionary.
Try to interpret each entry in the dictionary according to the following
rules. The first rule that returns an valid result determines the type in
which the entry will be converted.
- If the entry starts and ends with a single quote or double quote, it is
interpreted as a string.
- If the entry starts and ends with a square bracket, it is interpreted as
a list.
- If the entry starts and ends with a brace, it is interpreted as a
dictionary.
- If the entry is the word None, without quotes, then the entry is
interpreted as NoneType.
- If the entry is the word False, without quotes, then the entry is
interpreted as a boolean False.
- If the entry is the word True, without quotes, then the entry is
interpreted as a boolean True.
- If none of the previous options match the content of the entry,
the parser tries to interpret the entry in order as:
- An integer number.
- A float number.
- A string.
Args:
config (dict): a dictionary containing the parameters as strings
(the dictionary as returned by COnfig Parser).
Returns:
dict: dictionary with the same structure as the input
dictionary, but with correct types assigned to each entry.
"""
# Create the dictionary that will be returned.
monitor_params = {}
# Iterate over the first level of the configuration dictionary.
for section in config_dict.keys():
# Add the section to the dictionary that will be returned.
monitor_params[section] = {}
# Iterate over the content of each section (the second level in the
# configuration dictonary).
for option in config_dict['section'].keys():
# Get the option from the dictionary (None is returned if the
# dictionary does not contain the option).
recovered_option = config_dict['section'].get(option)
# Check if the option is a string delimited by single quotes.
if (
recovered_option.startswith("'") and
recovered_option.endswith("'")
):
monitor_params[section][option] = recovered_option[1:-1]
continue
# Check if the option is a string delimited by double quotes.
if (
recovered_option.startswith('"') and
recovered_option.endswith('"')
):
monitor_params[section][option] = recovered_option[1:-1]
continue
# Check if the option is a list. If it is, interpret it using the
# literal_eval function.
if (
recovered_option.startswith("[") and
recovered_option.endswith("]")
):
try:
monitor_params[section][option] = ast.literal_eval(
recovered_option
)
continue
except (SyntaxError, ValueError):
_parsing_error(section, option)
# Check if the option is a dictionary or a set. If it is,
# interpret it using the literal_eval function.
if (
recovered_option.startswith("{") and
recovered_option.endswith("}")
):
try:
monitor_params[section][option] = ast.literal_eval(
recovered_option
)
continue
except (SyntaxError, ValueError):
_parsing_error(section, option)
# Check if the option is the special string 'None' (without
# quotes).
if recovered_option == 'None':
monitor_params[section][option] = None
continue
# Check if the option is the special string 'False' (without
# quotes).
if recovered_option == 'False':
monitor_params[section][option] = False
continue
# Check if the option is the special string 'True' (without
# quotes).
if recovered_option == 'True':
monitor_params[section][option] = True
continue
# Check if the option is an int by trying to convert it to an int.
try:
monitor_params[section][option] = int(recovered_option)
continue
except ValueError:
# If the conversion to int falied, try to conver it to a float.
try:
monitor_params[section][option] = float(
recovered_option
)
continue
except ValueError:
# If the conversion to float also failed, return a parsing
# error.
_parsing_error(section, option)
# Returned the converted dictionary.
return monitor_params