summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2018-09-08 16:56:08 -0400
committerNed Batchelder <ned@nedbatchelder.com>2018-09-08 20:12:20 -0400
commit69d106fec5ac2e9aba1146c0004d961e8cb903f5 (patch)
tree25e385c4ed07dcf0b7d73e6c81bedc939b916baf
parentc001d1676de46aef12f80a21675937756e594acf (diff)
downloadpython-coveragepy-git-69d106fec5ac2e9aba1146c0004d961e8cb903f5.tar.gz
Defaultable variable substitution
-rw-r--r--CHANGES.rst7
-rw-r--r--coverage/misc.py15
-rw-r--r--doc/config.rst15
-rw-r--r--tests/test_misc.py1
4 files changed, 26 insertions, 12 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 23aa0921..8f8cd32b 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -17,9 +17,10 @@ Change history for Coverage.py
Unreleased
----------
-- Environment variable substitution in configuration files can now be strict:
- using a question mark suffix like ``${VARNAME?}`` will raise an error if
- ``VARNAME`` is not defined as an environment variable.
+- Environment variable substitution in configuration files now supports two
+ syntaxes for controlling the behavior of undefined variables: if ``VARNAME``
+ is not defined, ``${VARNAME?}`` will raise an error, and ``${VARNAME-default
+ value}`` will use "default value".
.. _changes_50a2:
diff --git a/coverage/misc.py b/coverage/misc.py
index 037332f5..7b8fbb93 100644
--- a/coverage/misc.py
+++ b/coverage/misc.py
@@ -258,7 +258,8 @@ def substitute_variables(text, variables=os.environ):
$VAR
${VAR}
- ${VAR?} strict: an error if VAR isn't defined.
+ ${VAR?} strict: an error if VAR isn't defined.
+ ${VAR-missing} defaulted: "missing" if VAR isn't defined.
A dollar can be inserted with ``$$``.
@@ -280,16 +281,20 @@ def substitute_variables(text, variables=os.environ):
if word not in variables:
msg = "Variable {} is undefined: {}".format(word, text)
raise CoverageException(msg)
- return variables.get(word, '')
+ return variables.get(word, m.group('defval') or '')
dollar_pattern = r"""(?x) # Use extended regex syntax
\$(?: # A dollar sign, then
(?P<v1>\w+) | # a plain word,
+ (?P<char>\$) | # or a dollar sign.
{ # or a {-wrapped word,
(?P<v2>\w+)
- (?P<strict>\??) # with maybe a strict marker
- } |
- (?P<char>[$]) # or a dollar sign.
+ (?:
+ (?P<strict>\?) # with a strict marker
+ |
+ -(?P<defval>[^}]*) # or a default value
+ )?
+ }
)
"""
text = re.sub(dollar_pattern, dollar_replace, text)
diff --git a/doc/config.rst b/doc/config.rst
index ab874619..666a1321 100644
--- a/doc/config.rst
+++ b/doc/config.rst
@@ -59,10 +59,17 @@ or ``0`` and are case-insensitive.
Environment variables can be substituted in by using dollar signs: ``$WORD``
or ``${WORD}`` will be replaced with the value of ``WORD`` in the environment.
-A dollar sign can be inserted with ``$$``. If you want to raise an error if
-an environment variable is undefined, use a question mark suffix: ``${WORD?}``.
-Otherwise, missing environment variables will result in empty strings with no
-error.
+A dollar sign can be inserted with ``$$``. Special forms can be used to
+control what happens if the variable isn't defined in the environment:
+
+- If you want to raise an error if an environment variable is undefined, use a
+ question mark suffix: ``${WORD?}``.
+
+- If you want to provide a default for missing variables, use a dash with a
+ default value: ``${WORD-default value}``.
+
+- Otherwise, missing environment variables will result in empty strings with no
+ error.
Many sections and values correspond roughly to commands and options in
the :ref:`command-line interface <cmd>`.
diff --git a/tests/test_misc.py b/tests/test_misc.py
index 65476928..c8c2c9e4 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -152,6 +152,7 @@ VARS = {
("Multiple: $$ $FOO $BAR ${FOO}", "Multiple: $ fooey xyzzy fooey"),
("Ill-formed: ${%5} ${{HI}} ${", "Ill-formed: ${%5} ${{HI}} ${"),
("Strict: ${FOO?} is there", "Strict: fooey is there"),
+ ("Defaulted: ${WUT-missing}!", "Defaulted: missing!"),
])
def test_substitute_variables(before, after):
assert substitute_variables(before, VARS) == after