Skip to content

Commit 1f6e471

Browse files
committed
Fix config and add anyconfig cli decorator
1 parent 75030c2 commit 1f6e471

File tree

1 file changed

+70
-2
lines changed

1 file changed

+70
-2
lines changed

wirecell/util/cli.py

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,13 +276,81 @@ def wrapper(*args, **kwds):
276276
return func(*args, **kwds)
277277
return wrapper
278278

279+
def anyconfig_file(name, section=None, cname=None, fmt='ini', shortarg="-c", longarg="--config", defaults=None):
280+
'''
281+
A decorator for a command that accepts a config file.
282+
283+
This transforms a config file of a given format to a data object using the anyconfig module.
284+
285+
- section :: if given, name a top level config key and attempt to set any
286+
kwds which are None to a value of an attribute of that section of the same
287+
key name.
288+
289+
- name :: the application name, used to locate default XDG config path.
290+
- cname :: config file name if not based on name
291+
- fmt :: if default load fails, try again assuming this format
292+
'''
293+
import anyconfig
294+
295+
def decorator(func):
296+
@click.option(shortarg, longarg, type=str, default=None, help="Set Configuration file.")
297+
@functools.wraps(func)
298+
def wrapper(*args, **kwds):
299+
varname = longarg.replace("--","").replace("-","_")
300+
cpath = kwds.pop(varname)
301+
if cpath:
302+
cpath = Path(cpath)
303+
else:
304+
nonlocal cname
305+
nonlocal fmt
306+
if not cname:
307+
cname = name + '.' + fmt
308+
base = os.environ.get("XDG_CONFIG_HOME", None)
309+
if base:
310+
bash = Path(base)
311+
else:
312+
base = Path(os.environ["HOME"]) / ".config"
313+
cpath = base / name / cname
314+
cfg = None
315+
if cpath.exists():
316+
try:
317+
cfg = anyconfig.load(cpath)
318+
except anyconfig.UnknownFileTypeError:
319+
cfg = None
320+
if cfg is None:
321+
cfg = anyconfig.load(cpath, ac_parser=fmt)
322+
323+
if cfg and section and cfg.get(section, None):
324+
sec = cfg[section]
325+
for key, val in kwds.items():
326+
if val is not None:
327+
continue
328+
val = sec.get(key, None)
329+
dval = defaults.get(key, None)
330+
if val is None:
331+
val = dval
332+
if val is None:
333+
continue
334+
if dval is not None:
335+
val = type(dval)(val)
336+
kwds[key] = val
337+
338+
kwds[varname] = cfg
339+
return func(*args, **kwds)
340+
return wrapper
341+
return decorator
342+
343+
279344
def config_file(name, cname=None, shortarg="-c", longarg="--config"):
280345
'''
281346
A decorator for a command that accepts a config file.
282347
283348
This transforms config file to config parser object.
349+
284350
'''
285-
def decoratgor(func):
351+
import configparser
352+
353+
def decorator(func):
286354
@click.option(shortarg, longarg, type=str, default=None, help="Set Configuration file.")
287355
@functools.wraps(func)
288356
def wrapper(*args, **kwds):
@@ -303,7 +371,7 @@ def wrapper(*args, **kwds):
303371
if cpath.exists():
304372
cfg.read(cpath)
305373
kwds[varname] = cfg
306-
return
374+
return func(*args, **kwds)
307375
return wrapper
308376
return decorator
309377

0 commit comments

Comments
 (0)