ConfigArgParse icon indicating copy to clipboard operation
ConfigArgParse copied to clipboard

Empty environment variable and empty yaml key behave differently

Open rngadam opened this issue 1 year ago • 1 comments

configargparse v1.7

usage

given this add_argument:

        parser.add_argument(
            "--accept-taa",
            type=str,
            nargs=2,
            metavar=("<acceptance-mechanism>", "<taa-version>"),
            env_var="ACAPY_ACCEPT_TAA",
            help=(
                "Specify the acceptance mechanism and taa version for which to accept"
                " the transaction author agreement. If not provided, the TAA must"
                " be accepted through the TTY or the admin API."
            ),
        )

yaml

given this yaml file:

accept-taa: 

value is not set and is ignored

yaml

given this environment variable (loaded with docker --env-file):

ACAPY_ACCEPT_TAA=

exception:

error: argument --accept-taa: expected 2 arguments

expected

empty environment variable same behavior as no value yaml; if value-less and expect a value, just treat it as not specified

rngadam avatar Aug 22 '24 21:08 rngadam

The existing behavior is actually logically consistent. In YAML, foo: is equivalent to foo: null which is not the same as setting the value to the empty string (foo:''). The decision in ConfigArgParse is to treat the null/None as if the setting is not present.

With any environment var, it can be absent/unset or it can be set to the empty string but there is no separate concept of null/None. In shell scripting, in many cases setting an env var to be an empty string is treated as if unset, so for example:

foo=""
echo ${foo:-default}

will print default.

So there is an argument that ConfigArgParse should also treat env vars set to "" as None rather then "", but this would mean adding a special case for "", and the parsing of the default config file format (which also has no explicit None) would need to change accordingly. The current behaviour just treats "" as a regular string, which in Python it is.

If you really want this behaviour in your own code, you can simply strip out any env vars that have empty values before calling ap.parse():

my_env = {k:v for k,v in os.environ.items() if v}
ap.parse(env=my_env)

tbooth avatar Apr 22 '25 16:04 tbooth