7
7
# See the LICENSE file in the source distribution for further information.
8
8
9
9
from argparse import Action
10
- from configparser import ConfigParser , ParsingError , Error
10
+ from configparser import (ConfigParser , ParsingError , Error ,
11
+ DuplicateOptionError )
11
12
12
13
13
14
def _is_seq (val ):
@@ -106,15 +107,15 @@ def __init__(self, arg_defaults={}, **kwargs):
106
107
setattr (self , arg , kwargs [arg ])
107
108
108
109
@classmethod
109
- def from_args (cls , args ):
110
+ def from_args (cls , args , arg_defaults = {} ):
110
111
"""Initialise a new SoSOptions object from a ``Namespace``
111
112
obtained by parsing command line arguments.
112
113
113
114
:param args: parsed command line arguments
114
115
:returns: an initialised SoSOptions object
115
116
:returntype: SoSOptions
116
117
"""
117
- opts = SoSOptions (** vars (args ))
118
+ opts = SoSOptions (** vars (args ), arg_defaults = arg_defaults )
118
119
opts ._merge_opts (args , True )
119
120
return opts
120
121
@@ -169,58 +170,59 @@ def _convert_to_type(self, key, val, conf):
169
170
% (key , conf ))
170
171
return val
171
172
172
- def update_from_conf (self , config_file ):
173
+ def update_from_conf (self , config_file , component ):
174
+ """Read the provided config_file and update options from that.
175
+
176
+ Positional arguments:
177
+
178
+ :param config_file: Filepath to the config file
179
+ :param component: Which component (section) to load
180
+ """
181
+
182
+ def _update_from_section (section , config ):
183
+ if config .has_section (section ):
184
+ odict = dict (config .items (section ))
185
+ # handle verbose explicitly
186
+ if 'verbose' in odict .keys ():
187
+ odict ['verbosity' ] = int (odict .pop ('verbose' ))
188
+ # convert options names
189
+ for key in odict .keys ():
190
+ if '-' in key :
191
+ odict [key .replace ('-' , '_' )] = odict .pop (key )
192
+ # set the values according to the config file
193
+ for key , val in odict .items ():
194
+ if isinstance (val , str ):
195
+ val = val .replace (' ' , '' )
196
+ if key not in self .arg_defaults :
197
+ # read an option that is not loaded by the current
198
+ # SoSComponent
199
+ print ("Unknown option '%s' in section '%s'"
200
+ % (key , section ))
201
+ continue
202
+ val = self ._convert_to_type (key , val , config_file )
203
+ setattr (self , key , val )
204
+
173
205
config = ConfigParser ()
174
206
try :
175
207
try :
176
208
with open (config_file ) as f :
177
209
config .readfp (f )
178
- except (ParsingError , Error ) as e :
210
+ except DuplicateOptionError as err :
211
+ raise exit ("Duplicate option '%s' in section '%s' in file %s"
212
+ % (err .option , err .section , config_file ))
213
+ except (ParsingError , Error ):
179
214
raise exit ('Failed to parse configuration file %s'
180
215
% config_file )
181
216
except (OSError , IOError ) as e :
182
217
raise exit ('Unable to read configuration file %s : %s'
183
218
% (config_file , e .args [1 ]))
184
219
185
- if config .has_section ("general" ):
186
- odict = dict (config .items ("general" ))
187
- # handle verbose explicitly
188
- if 'verbose' in odict .keys ():
189
- odict ['verbosity' ] = int (odict .pop ('verbose' ))
190
- # convert options names
191
- for key in odict .keys ():
192
- if '-' in key :
193
- odict [key .replace ('-' , '_' )] = odict .pop (key )
194
- # set the values according to the config file
195
- for key , val in odict .items ():
196
- if key not in self .arg_defaults :
197
- # read an option that is not loaded by the current
198
- # SoSComponent
199
- continue
200
- val = self ._convert_to_type (key , val , config_file )
201
- setattr (self , key , val )
202
-
203
- # report specific checks
204
-
205
- if hasattr (self , 'noplugins' ):
206
- if config .has_option ("plugins" , "disable" ):
207
- self .noplugins .extend ([
208
- plugin .strip () for plugin in
209
- config .get ("plugins" , "disable" ).split (',' )
210
- ])
211
-
212
- if hasattr (self , 'enableplugins' ):
213
- if config .has_option ("plugins" , "enable" ):
214
- self .enableplugins .extend ([
215
- plugin .strip () for plugin in
216
- config .get ("plugins" , "enable" ).split (',' )
217
- ])
218
-
219
- if hasattr (self , 'plugopts' ):
220
- if config .has_section ("tunables" ):
221
- for opt , val in config .items ("tunables" ):
222
- if not opt .split ('.' )[0 ] in opts .noplugins :
223
- self .plugopts .append (opt + "=" + val )
220
+ _update_from_section ("global" , config )
221
+ _update_from_section (component , config )
222
+ if config .has_section ("plugin_options" ) and hasattr (self , 'plugopts' ):
223
+ for key , val in config .items ("plugin_options" ):
224
+ if not key .split ('.' )[0 ] in self .skip_plugins :
225
+ self .plugopts .append (key + '=' + val )
224
226
225
227
def merge (self , src , skip_default = True ):
226
228
"""Merge another set of ``SoSOptions`` into this object.
@@ -237,7 +239,7 @@ def merge(self, src, skip_default=True):
237
239
if getattr (src , arg ) is not None or not skip_default :
238
240
self ._merge_opt (arg , src , False )
239
241
240
- def dict (self ):
242
+ def dict (self , preset_filter = True ):
241
243
"""Return this ``SoSOptions`` option values as a dictionary of
242
244
argument name to value mappings.
243
245
@@ -247,8 +249,9 @@ def dict(self):
247
249
for arg in self .arg_names :
248
250
value = getattr (self , arg )
249
251
# Do not attempt to store preset option values in presets
250
- if arg in ('add_preset' , 'del_preset' , 'desc' , 'note' ):
251
- value = None
252
+ if preset_filter :
253
+ if arg in ('add_preset' , 'del_preset' , 'desc' , 'note' ):
254
+ value = None
252
255
odict [arg ] = value
253
256
return odict
254
257
0 commit comments