Cmd / Cmds: Add config file support

An application based on Cmds will now try to read StringTree
formatted config data from a file $HOME/.<name>rc, and make the data
available via the newly added conf_value() method.

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2022-12-08 16:44:49 +01:00
commit a4fb791649
2 changed files with 31 additions and 0 deletions

View file

@ -3,9 +3,11 @@
from typing import Optional
import os, sys, argcomplete, argparse, importlib, inspect, re, pickle, asyncio, cProfile
from argparse import ArgumentParser
from pathlib import Path, PurePath
import jwutils
from jwutils.log import *
from jwutils.stree import serdes
class Cmds: # export
@ -30,10 +32,19 @@ class Cmds: # export
for sub_cmd in cmd.children:
self.__add_cmd_to_parser(sub_cmd, subparsers)
def __parse_config(self):
exe_stem = str(PurePath(sys.argv[0]).stem)
path = str(Path.home()) + '/.' + exe_stem + 'rc'
if not os.path.exists(path):
return None, []
slog(DEBUG, 'Reading configuration "{}"'.format(path))
return serdes.read(path, ''), [path]
def __init__(self, description: str = '', filter: str = '^Cmd.*', modules: None=None, eloop: None=None) -> None:
self.__description = description
self.__filter = filter
self.__modules = modules
self.__conf, self.__conf_paths = self.__parse_config()
self.__cmds = []
self.eloop = eloop
self.__own_eloop = False
@ -43,6 +54,7 @@ class Cmds: # export
log_level = "notice"
log_flags = 'stderr,position,prio,color'
log_file = None
# poor man's parsing in the absence of a complete command-line definition
for i in range(1, len(sys.argv)):
if i >= len(sys.argv) - 1:
@ -64,6 +76,7 @@ class Cmds: # export
self.__parser.add_argument('--log-level', help='Log level', default=log_level)
self.__parser.add_argument('--backtrace', help='Show exception backtraces', action='store_true', default=False)
self.__parser.add_argument('--write-profile', help='Profile code and store output to file', default=None)
self.__parser.add_argument('--log-file', help='Log file', default=log_file)
if self.__modules == None:
self.__modules = [ '__main__' ]
subcmds = set()
@ -118,6 +131,11 @@ class Cmds: # export
if pr is not None:
pr.enable()
if self.__conf:
self.__conf.dump(DEBUG, "Configuration")
if self.args.log_file is not None:
add_log_file(self.args.log_file)
try:
ret = await self._run(self.args)
except Exception as e:
@ -144,6 +162,12 @@ class Cmds: # export
self.eloop = None
self.__own_eloop = False
def conf_value(self, path, default=None):
ret = None if self.__conf is None else self.__conf.value(path)
if ret is None and default is not None:
return default
return ret
def parser(self) -> ArgumentParser:
return self.__parser