Skip to content

Commit

Permalink
Merge pull request datalad#6864 from mih/bf-6863
Browse files Browse the repository at this point in the history
Support unsetting config via `datalad -c :<name>`
  • Loading branch information
yarikoptic committed Jul 21, 2022
2 parents 49db421 + a556c22 commit cefecae
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 10 deletions.
10 changes: 6 additions & 4 deletions datalad/cli/common_args.py
Expand Up @@ -34,10 +34,12 @@
('-c',),
dict(action='append',
dest='cfg_overrides',
metavar='KEY=VALUE',
help="""configuration variable setting. Overrides any
configuration read from a file, but is potentially overridden
itself by configuration variables in the process environment.
metavar='(:name|name=value)',
help="""specify configuration setting overrides. They override any
configuration read from a file. A configuration can also be
unset temporarily by prefixing its name with a colon (':'), e.g. ':user.name'.
Overrides specified here may be overridden themselves by
configuration settings declared as environment variables.
""")),
change_path=(
('-C',),
Expand Down
14 changes: 10 additions & 4 deletions datalad/cli/helpers.py
Expand Up @@ -255,17 +255,23 @@ def _parse_overrides_from_cmdline(cmdlineargs):
# errors: we need a section, a variable, and a value at minimum
# otherwise we break our own config parsing helpers
# https://github.com/datalad/datalad/issues/3451
noassign_expr = re.compile(r'[^\s]+\.[^\s]+=[\S]+')
assign_expr = re.compile(r'[^\s]+\.[^\s]+=[\S]+')
unset_expr = re.compile(r':[^\s]+\.[^\s=]+')
noassign = [
o
for o in cmdlineargs.cfg_overrides
if not noassign_expr.match(o)
if not (assign_expr.match(o) or unset_expr.match(o))
]
if noassign:
lgr.error(
"Configuration override without section/variable "
"or value assignment (must be 'section.variable=value'): %s",
"or unset marker or value assignment "
"(must be '(:section.variable|section.variable=value)'): %s",
noassign)
sys.exit(3)
overrides = dict(o.split('=', 1) for o in cmdlineargs.cfg_overrides)
overrides = dict(
[o[1:], None] if o.startswith(':')
else o.split('=', 1)
for o in cmdlineargs.cfg_overrides
)
return overrides
26 changes: 24 additions & 2 deletions datalad/cli/tests/test_main.py
Expand Up @@ -269,11 +269,12 @@ def test_script_shims(script):
get_numeric_portion(version))


@slow # 11.2591s
@with_tempfile(mkdir=True)
def test_cfg_override(path=None):
with chpwd(path):
cmd = ['datalad', 'wtf', '-s', 'some']
# use 'wtf' to dump the config
# should be rewritten to use `configuration`
cmd = ['datalad', 'wtf', '-S', 'configuration', '-s', 'some']
# control
out = Runner().run(cmd, protocol=StdOutErrCapture)['stdout']
assert_not_in('datalad.dummy: this', out)
Expand Down Expand Up @@ -305,6 +306,27 @@ def test_cfg_override(path=None):
protocol=StdOutErrCapture)['stdout']
assert_in('datalad.dummy: this', out)

# set a config
run_main([
'configuration', '--scope', 'local', 'set', 'mike.item=some'])
# verify it is successfully set
assert 'some' == run_main([
'configuration', 'get', 'mike.item'])[0].strip()
# verify that an override can unset the config
# we cannot use run_main(), because the "singleton" instance of the
# dataset we are in is still around in this session, and with it
# also its config managers that we will not be able to post-hoc
# overwrite with this method. Instead, we'll execute in a subprocess.
assert '' == Runner().run([
'datalad', '-c', ':mike.item',
'configuration', 'get', 'mike.item'],
protocol=StdOutErrCapture)['stdout'].strip()
# verify the effect is not permanent
assert 'some' == Runner().run([
'datalad',
'configuration', 'get', 'mike.item'],
protocol=StdOutErrCapture)['stdout'].strip()


def test_incorrect_cfg_override():
run_main(['-c', 'some', 'wtf'], exit_code=3)
Expand Down

0 comments on commit cefecae

Please sign in to comment.