commands: config: add -d and -D options for deleting

These allow the user to delete existing options.

Signed-off-by: Marti Bolivar <marti.bolivar@nordicsemi.no>
This commit is contained in:
Marti Bolivar 2019-05-24 23:27:37 -06:00
parent 4fe9d4a042
commit 0da14440c6
2 changed files with 117 additions and 5 deletions

View File

@ -8,7 +8,8 @@ import argparse
import configparser
from west import log
from west.configuration import read_config, update_config, ConfigFile
from west.configuration import read_config, update_config, delete_config, \
ConfigFile
from west.commands import WestCommand, CommandError
CONFIG_DESCRIPTION = '''\
@ -52,6 +53,16 @@ To set a value for <name>, type:
To list all options and their values:
west config -l
To delete <name> in the local or global file (wherever it's set
first, not in both; if set locally, global values become visible):
west config -d <name>
To delete <name> in the global file only:
west config -d --global <name>
To delete <name> everywhere it's set, including the system file:
west config -D <name>
'''
CONFIG_EPILOG = '''\
@ -98,6 +109,10 @@ class Config(WestCommand):
parser.add_argument('-l', '--list', action='store_true',
help='list all options and their values')
parser.add_argument('-d', '--delete', action='store_true',
help='delete an option in one config file')
parser.add_argument('-D', '--delete-all', action='store_true',
help="delete an option everywhere it's set")
group = parser.add_argument_group(
'configuration file to use (give at most one)')
@ -116,15 +131,22 @@ class Config(WestCommand):
return parser
def do_run(self, args, user_args):
delete = args.delete or args.delete_all
if args.list:
if args.name:
self.parser.error('-l cannot be combined with name argument')
elif delete:
self.parser.error('-l cannot be combined with -d or -D')
elif not args.name:
self.parser.error('missing argument name '
'(to list all options and values, use -l)')
elif args.delete and args.delete_all:
self.parser.error('-d cannot be combined with -D')
if args.list:
self.list(args)
elif delete:
self.delete(args)
elif args.value is None:
self.read(args)
else:
@ -138,6 +160,24 @@ class Config(WestCommand):
for k, v in cfg[s].items():
log.inf('{}.{}={}'.format(s, k, v))
def delete(self, args):
section, key = self._sk(args)
if args.delete_all:
what = ALL
elif args.configfile:
what = args.configfile
else:
what = None # local or global, whichever comes first
try:
delete_config(section, key, configfile=what)
except KeyError:
log.dbg('{} was not set in requested location(s)'.
format(args.name))
raise CommandError(returncode=1)
except PermissionError as pe:
self._perm_error(pe, what, section, key)
def read(self, args):
section, key = self._sk(args)
cfg = configparser.ConfigParser()
@ -155,10 +195,7 @@ class Config(WestCommand):
try:
update_config(section, key, args.value, configfile=what)
except PermissionError as pe:
log.die("can't set {}.{}: permission denied when writing {}{}".
format(section, key, pe.filename,
('; are you root/administrator?' if what == SYSTEM
else '')))
self._perm_error(pe, what, section, key)
def _sk(self, args):
name_list = args.name.split(".", 1)
@ -166,3 +203,9 @@ class Config(WestCommand):
self.parser.error('name {} should be in the form <section>.<key>',
exit_code=3)
return name_list[0], name_list[1]
def _perm_error(self, pe, what, section, key):
rootp = ('; are you root/administrator?' if what in [SYSTEM, ALL]
else '')
log.die("can't update {}.{}: permission denied when writing {}{}".
format(section, key, pe.filename, rootp))

View File

@ -342,6 +342,75 @@ def test_delete_local_one():
assert 'pytest' in cfg(f=LOCAL)
assert cfg(f=LOCAL)['pytest']['key2'] == 'bar'
def test_delete_cmd_all():
# west config -D should delete from everywhere
cmd('config --system pytest.key system')
cmd('config --global pytest.key global')
cmd('config --local pytest.key local')
assert cfg(f=ALL)['pytest']['key'] == 'local'
cmd('config -D pytest.key')
assert 'pytest' not in cfg(f=ALL)
with pytest.raises(subprocess.CalledProcessError):
cmd('config -D pytest.key')
def test_delete_cmd_none():
# west config -d should delete from lowest-precedence global or
# local file only.
cmd('config --system pytest.key system')
cmd('config --global pytest.key global')
cmd('config --local pytest.key local')
cmd('config -d pytest.key')
assert cmd('config pytest.key').rstrip() == 'global'
cmd('config -d pytest.key')
assert cmd('config pytest.key').rstrip() == 'system'
with pytest.raises(subprocess.CalledProcessError):
cmd('config -d pytest.key')
def test_delete_cmd_system():
# west config -d --system should only delete from system
cmd('config --system pytest.key system')
cmd('config --global pytest.key global')
cmd('config --local pytest.key local')
cmd('config -d --system pytest.key')
with pytest.raises(subprocess.CalledProcessError):
cmd('config --system pytest.key')
assert cmd('config --global pytest.key').rstrip() == 'global'
assert cmd('config --local pytest.key').rstrip() == 'local'
def test_delete_cmd_global():
# west config -d --global should only delete from global
cmd('config --system pytest.key system')
cmd('config --global pytest.key global')
cmd('config --local pytest.key local')
cmd('config -d --global pytest.key')
assert cmd('config --system pytest.key').rstrip() == 'system'
with pytest.raises(subprocess.CalledProcessError):
cmd('config --global pytest.key')
assert cmd('config --local pytest.key').rstrip() == 'local'
def test_delete_cmd_local():
# west config -d --local should only delete from local
cmd('config --system pytest.key system')
cmd('config --global pytest.key global')
cmd('config --local pytest.key local')
cmd('config -d --local pytest.key')
assert cmd('config --system pytest.key').rstrip() == 'system'
assert cmd('config --global pytest.key').rstrip() == 'global'
with pytest.raises(subprocess.CalledProcessError):
cmd('config --local pytest.key')
def test_delete_cmd_error():
# Verify illegal combinations of flags error out.
with pytest.raises(subprocess.CalledProcessError) as e:
cmd('config -l -d pytest.key')
assert '-l cannot be combined with -d or -D' in str(e)
with pytest.raises(subprocess.CalledProcessError) as e:
cmd('config -l -D pytest.key')
assert '-l cannot be combined with -d or -D' in str(e)
with pytest.raises(subprocess.CalledProcessError) as e:
cmd('config -d -D pytest.key')
assert '-d cannot be combined with -D' in str(e)
def test_default_config():
# Writing to a value without a config destination should default
# to --local.