@@ -35,6 +35,9 @@ def validate_positive(num, _):
3535 raise ValueError ('%d is not positive' % (num ))
3636 return num
3737
38+ class _NotSpecified : #pylint:disable=too-few-public-methods
39+ pass
40+
3841class DeltaConfigComponent :
3942 """
4043 DELTA configuration component.
@@ -78,7 +81,7 @@ def register_component(self, component, name : str, attr_name = None):
7881 attr_name = name
7982 setattr (self , attr_name , component )
8083
81- def register_field (self , name : str , types , accessor = None , cmd_arg = None , validate_fn = None , desc = None ):
84+ def register_field (self , name : str , types , accessor = None , validate_fn = None , desc = None ):
8285 """
8386 Register a field in this component of the configuration.
8487
@@ -92,7 +95,6 @@ def register_field(self, name : str, types, accessor = None, cmd_arg = None, val
9295 self ._fields .append (name )
9396 self ._validate [name ] = validate_fn
9497 self ._types [name ] = types
95- self ._cmd_args [name ] = cmd_arg
9698 self ._descs [name ] = desc
9799 if accessor :
98100 def access (self ) -> types :
@@ -101,14 +103,44 @@ def access(self) -> types:
101103 access .__doc__ = desc
102104 setattr (self .__class__ , accessor , access )
103105
106+ def register_arg (self , field , argname , ** kwargs ):
107+ """
108+ Registers a command line argument in this component.
109+
110+ field is the (registered) field this argument modifies.
111+ argname is the name of the flag on the command line (i.e., '--flag')
112+ **kwargs are arguments to ArgumentParser.add_argument.
113+
114+ If help and type are not specified, will use the ones for the field.
115+ If default is not specified, will use the value from the config files.
116+ """
117+ assert field in self ._fields , 'Field %s not registered.' % (field )
118+ if 'help' not in kwargs :
119+ kwargs ['help' ] = self ._descs [field ]
120+ if 'type' not in kwargs :
121+ kwargs ['type' ] = self ._types [field ]
122+ elif kwargs ['type' ] is None :
123+ del kwargs ['type' ]
124+ if 'default' not in kwargs :
125+ kwargs ['default' ] = _NotSpecified
126+ self ._cmd_args [argname ] = (field , kwargs )
127+
128+ def to_dict (self ) -> dict :
129+ """
130+ Returns a dictionary representing the config object.
131+ """
132+ if isinstance (self ._config_dict , dict ):
133+ exp = self ._config_dict .copy ()
134+ for (name , c ) in self ._components .items ():
135+ exp [name ] = c .to_dict ()
136+ return exp
137+ return self ._config_dict
138+
104139 def export (self ) -> str :
105140 """
106- Returns a YAML string of all configuration options.
141+ Returns a YAML string of all configuration options, from to_dict .
107142 """
108- exp = self ._config_dict .copy ()
109- for (name , c ) in self ._components .items ():
110- exp [name ] = c .export ()
111- return yaml .dump (exp )
143+ return yaml .dump (self .to_dict ())
112144
113145 def _set_field (self , name : str , value : str , base_dir : str ):
114146 if name not in self ._fields :
@@ -139,12 +171,9 @@ def setup_arg_parser(self, parser, components = None) -> None:
139171 """
140172 if self ._section_header is not None :
141173 parser = parser .add_argument_group (self ._section_header )
142- for name in self ._fields :
143- c = self ._cmd_args [name ]
144- if c is None :
145- continue
146- parser .add_argument (c , dest = c .replace ('-' , '_' ), required = False ,
147- type = self ._types [name ], help = self ._descs [name ])
174+ for (arg , value ) in self ._cmd_args .items ():
175+ (field , kwargs ) = value
176+ parser .add_argument (arg , dest = field , ** kwargs )
148177
149178 for (name , c ) in self ._components .items ():
150179 if components is None or name in components :
@@ -157,14 +186,12 @@ def parse_args(self, options):
157186 configuration values.
158187 """
159188 d = {}
160- for name in self ._fields :
161- c = self ._cmd_args [name ]
162- if c is None :
189+ for (field , _ ) in self ._cmd_args .values ():
190+ if not hasattr (options , field ) or getattr (options , field ) is None :
163191 continue
164- n = c .replace ('-' , '_' )
165- if not hasattr (options , n ) or getattr (options , n ) is None :
192+ if getattr (options , field ) is _NotSpecified :
166193 continue
167- d [name ] = getattr (options , n )
194+ d [field ] = getattr (options , field )
168195 self ._load_dict (d , None )
169196
170197 for c in self ._components .values ():
@@ -183,6 +210,7 @@ def load(self, yaml_file: str = None, yaml_str: str = None):
183210 """
184211 base_path = None
185212 if yaml_file :
213+ #print("Loading config file: " + yaml_file)
186214 if not os .path .exists (yaml_file ):
187215 raise Exception ('Config file does not exist: ' + yaml_file )
188216 with open (yaml_file , 'r' ) as f :
0 commit comments