Skip to content

Commit

Permalink
Merge pull request #3974 from oliver-sanders/literal_eval
Browse files Browse the repository at this point in the history
templatevars: parse CLI opts with literal_eval
  • Loading branch information
wxtim authored Dec 7, 2020
2 parents 86228c7 + dd8495d commit a6bac41
Show file tree
Hide file tree
Showing 65 changed files with 329 additions and 205 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ symlink to `DIR` (see #3884).

### Enhancements

[#3974](https://github.com/cylc/cylc-flow/pull/3974) - Template variables,
both in set files and provided via the -s/--set command line options are
now parsed using ast.literal_eval. This permits non-string data types,
strings must now be quoted.

[#3811](https://github.com/cylc/cylc-flow/pull/3811) - Move from cycle based
to `n` distance dependency graph window node generation and pruning of the
data-store (API/visual backing data). Ability to modify distance of live
Expand Down
2 changes: 1 addition & 1 deletion cylc/flow/network/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,7 @@ class Meta:
running at reload time.
If the suite was started with Jinja2 template variables set on the
command line (cylc run --set FOO=bar REG) the same template
command line (cylc run --set "FOO='bar'" REG) the same template
settings apply to the reload (only changes to the flow.cylc
file itself are reloaded).
Expand Down
18 changes: 12 additions & 6 deletions cylc/flow/option_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,16 @@ def add_std_options(self):
self.add_std_option(
"-s", "--set", metavar="NAME=VALUE",
help=(
"Set the value of a Jinja2 template variable in the "
"suite definition. This option can be used multiple "
"times on the command line. "
"NOTE: these settings persist across suite restarts, "
"but can be set again on the \"cylc restart\" "
"command line if they need to be overridden."
"Set the value of a Jinja2 template variable in the"
" suite definition."
" Values should be valid Python literals so strings"
" must be quoted"
" e.g. 'STR=\"string\"', INT=43, BOOL=True."
" This option can be used multiple "
" times on the command line."
" NOTE: these settings persist across suite restarts,"
" but can be set again on the \"cylc restart\""
" command line if they need to be overridden."
),
action="append", default=[], dest="templatevars")

Expand All @@ -187,6 +191,8 @@ def add_std_options(self):
"Set the value of Jinja2 template variables in the "
"suite definition from a file containing NAME=VALUE "
"pairs (one per line). "
"As with --set values should be valid Python literals "
"so strings must be quoted e.g. STR='string'. "
"NOTE: these settings persist across suite restarts, "
"but can be set again on the \"cylc restart\" "
"command line if they need to be overridden."
Expand Down
2 changes: 1 addition & 1 deletion cylc/flow/scripts/reload.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
already running at reload time.
If the suite was started with Jinja2 template variables set on the command line
(cylc run --set FOO=bar REG) the same template settings apply to the reload
(cylc run --set 'FOO="bar"' REG) the same template settings apply to the reload
(only changes to the flow.cylc file itself are reloaded).
If the modified suite definition does not parse, failure to reload will
Expand Down
40 changes: 38 additions & 2 deletions cylc/flow/templatevars.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,42 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Load custom variables for template processor."""

from ast import literal_eval

from cylc.flow.exceptions import UserInputError


def eval_var(var):
"""Wrap ast.literal_eval to provide more helpful error.
Examples:
>>> eval_var('42')
42
>>> eval_var('"string"')
'string'
>>> eval_var('string')
Traceback (most recent call last):
cylc.flow.exceptions.UserInputError: Invalid template variable: string
(note string values must be quoted)
>>> eval_var('[')
Traceback (most recent call last):
cylc.flow.exceptions.UserInputError: Invalid template variable: [
(values must be valid Python literals)
"""
try:
return literal_eval(var)
except ValueError:
raise UserInputError(
f'Invalid template variable: {var}'
'\n(note string values must be quoted)'
) from None
except SyntaxError:
raise UserInputError(
f'Invalid template variable: {var}'
'\n(values must be valid Python literals)'
) from None


def load_template_vars(template_vars=None, template_vars_file=None):
"""Load template variables from key=value strings."""
Expand All @@ -25,9 +61,9 @@ def load_template_vars(template_vars=None, template_vars_file=None):
if not line:
continue
key, val = line.split("=", 1)
res[key.strip()] = val.strip()
res[key.strip()] = eval_var(val.strip())
if template_vars:
for pair in template_vars:
key, val = pair.split("=", 1)
res[key.strip()] = val.strip()
res[key.strip()] = eval_var(val.strip())
return res
4 changes: 2 additions & 2 deletions tests/flakyfunctional/cylc-show/00-simple.t
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ TEST_SHOW_OUTPUT_PATH="${PWD}/${TEST_NAME_BASE}-show"
#-------------------------------------------------------------------------------
TEST_NAME="${TEST_NAME_BASE}-validate"
run_ok "${TEST_NAME}" cylc validate \
--set=TEST_OUTPUT_PATH="${TEST_SHOW_OUTPUT_PATH}" "${SUITE_NAME}"
--set="TEST_OUTPUT_PATH='${TEST_SHOW_OUTPUT_PATH}'" "${SUITE_NAME}"
#-------------------------------------------------------------------------------
TEST_NAME="${TEST_NAME_BASE}-run"
suite_run_ok "${TEST_NAME}" cylc run --reference-test --debug --no-detach \
--set=TEST_OUTPUT_PATH="${TEST_SHOW_OUTPUT_PATH}" "${SUITE_NAME}"
--set="TEST_OUTPUT_PATH='${TEST_SHOW_OUTPUT_PATH}'" "${SUITE_NAME}"
#-------------------------------------------------------------------------------
TEST_NAME="${TEST_NAME_BASE}-show"
cmp_ok "${TEST_NAME}-suite" <<'__SHOW_OUTPUT__'
Expand Down
2 changes: 1 addition & 1 deletion tests/flakyfunctional/restart/19-checkpoint/flow.cylc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ if [[ "${CYLC_TASK_CYCLE_POINT}" == '2017' ]]; then
cylc__job__poll_grep_suite_log -F \
'[t1.2017] status=submitted: (received)started'
sleep 2 # make sure status change recorded in DB
cylc broadcast "${CYLC_SUITE_NAME}" -p '2017' -n 't1' --set='script=true'
cylc broadcast "${CYLC_SUITE_NAME}" -p '2017' -n 't1' --set='script="true"'
cylc hold "${CYLC_SUITE_NAME}"
cylc__job__poll_grep_suite_log -F \
'INFO - Command succeeded: hold()'
Expand Down
40 changes: 20 additions & 20 deletions tests/flakyfunctional/special/04-clock-triggered.t
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,37 @@ set_test_number 4
install_suite "${TEST_NAME_BASE}" "${TEST_NAME_BASE}"
#-------------------------------------------------------------------------------
run_ok "${TEST_NAME_BASE}-validate" cylc validate "${SUITE_NAME}" \
-s "START=$(date '+%Y%m%dT%H')" \
-s "HOUR=$(date '+%H')" \
-s 'UTC_MODE=False' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT12S'
-s "START='$(date '+%Y%m%dT%H')'" \
-s "HOUR='$(date '+%H')'" \
-s 'UTC_MODE="False"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT12S"'
#-------------------------------------------------------------------------------
run_ok "${TEST_NAME_BASE}-run-now" \
cylc run --debug --no-detach "${SUITE_NAME}" \
-s "START=$(date '+%Y%m%dT%H')" \
-s "HOUR=$(date '+%H')" \
-s 'UTC_MODE=False' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT12S'
-s "START='$(date '+%Y%m%dT%H')'" \
-s "HOUR='$(date '+%H')'" \
-s 'UTC_MODE="False"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT12S"'
#-------------------------------------------------------------------------------
NOW="$(date '+%Y%m%dT%H')"
run_ok "${TEST_NAME_BASE}-run-past" \
cylc run --debug --no-detach "${SUITE_NAME}" \
-s "START=$(cylc cycle-point "${NOW}" --offset-hour='-10')" \
-s "HOUR=$(cylc cycle-point "${NOW}" --offset-hour='-10' --print-hour)" \
-s 'UTC_MODE=False' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT1M'
-s "START='$(cylc cycle-point "${NOW}" --offset-hour='-10')'" \
-s "HOUR='$(cylc cycle-point "${NOW}" --offset-hour='-10' --print-hour)'" \
-s 'UTC_MODE="False"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT1M"'
#-------------------------------------------------------------------------------
NOW="$(date '+%Y%m%dT%H')"
run_fail "${TEST_NAME_BASE}-run-later" \
cylc run --debug --no-detach "${SUITE_NAME}" \
-s "START=$(cylc cycle-point "${NOW}" --offset-hour='10')" \
-s "HOUR=$(cylc cycle-point "${NOW}" --offset-hour='10' --print-hour)" \
-s 'UTC_MODE=False' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT12S'
-s "START='$(cylc cycle-point "${NOW}" --offset-hour='10')'" \
-s "HOUR='$(cylc cycle-point "${NOW}" --offset-hour='10' --print-hour)'" \
-s 'UTC_MODE="False"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT12S"'
#-------------------------------------------------------------------------------
purge
exit
40 changes: 20 additions & 20 deletions tests/flakyfunctional/special/05-clock-triggered-utc.t
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,37 @@ set_test_number 4
install_suite "${TEST_NAME_BASE}" "${TEST_NAME_BASE}"
#-------------------------------------------------------------------------------
run_ok "${TEST_NAME_BASE}-validate" cylc validate "${SUITE_NAME}" \
-s "START=$(date -u '+%Y%m%dT%H00')Z" \
-s "HOUR=$(date -u '+%H')" \
-s 'UTC_MODE=True' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT12S'
-s "START='$(date -u '+%Y%m%dT%H00')Z'" \
-s "HOUR='$(date -u '+%H')'" \
-s 'UTC_MODE="True"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT12S"'
#-------------------------------------------------------------------------------
run_ok "${TEST_NAME_BASE}-run-now" \
cylc run --debug --no-detach "${SUITE_NAME}" \
-s "START=$(date -u '+%Y%m%dT%H00')Z" \
-s "HOUR=$(date -u '+%H')" \
-s 'UTC_MODE=True' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT1M'
-s "START='$(date -u '+%Y%m%dT%H00')Z'" \
-s "HOUR='$(date -u '+%H')'" \
-s 'UTC_MODE="True"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT1M"'
#-------------------------------------------------------------------------------
NOW="$(date -u '+%Y%m%dT%H00')Z"
run_ok "${TEST_NAME_BASE}-run-past" \
cylc run --debug --no-detach "${SUITE_NAME}" \
-s "START=$(cylc cycle-point "${NOW}" --offset-hour='-10')" \
-s "HOUR=$(cylc cycle-point "${NOW}" --offset-hour='-10' --print-hour)" \
-s 'UTC_MODE=True' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT12S'
-s "START='$(cylc cycle-point "${NOW}" --offset-hour='-10')'" \
-s "HOUR='$(cylc cycle-point "${NOW}" --offset-hour='-10' --print-hour)'" \
-s 'UTC_MODE="True"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT12S"'
#-------------------------------------------------------------------------------
NOW="$(date -u '+%Y%m%dT%H00')Z"
run_fail "${TEST_NAME_BASE}-run-later" \
cylc run --debug --no-detach "${SUITE_NAME}" \
-s "START=$(cylc cycle-point "${NOW}" --offset-hour='10')" \
-s "HOUR=$(cylc cycle-point "${NOW}" --offset-hour='10' --print-hour)" \
-s 'UTC_MODE=True' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT12S'
-s "START='$(cylc cycle-point "${NOW}" --offset-hour='10')'" \
-s "HOUR='$(cylc cycle-point "${NOW}" --offset-hour='10' --print-hour)'" \
-s 'UTC_MODE="True"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT12S"'
#-------------------------------------------------------------------------------
purge
exit
40 changes: 20 additions & 20 deletions tests/flakyfunctional/special/06-clock-triggered-iso.t
Original file line number Diff line number Diff line change
Expand Up @@ -23,38 +23,38 @@ set_test_number 4
install_suite "${TEST_NAME_BASE}" "${TEST_NAME_BASE}"
#-------------------------------------------------------------------------------
run_ok "${TEST_NAME_BASE}-validate" cylc validate "${SUITE_NAME}" \
-s "START=$(date '+%Y%m%dT%H%z')" \
-s "HOUR=$(date '+%H')" \
-s 'UTC_MODE=False' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT12S'
-s "START='$(date '+%Y%m%dT%H%z')'" \
-s "HOUR='$(date '+%H')'" \
-s 'UTC_MODE="False"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT12S"'
#-------------------------------------------------------------------------------
run_ok "${TEST_NAME_BASE}-run-now" \
cylc run --debug --no-detach "${SUITE_NAME}" \
-s "START=$(date '+%Y%m%dT%H%z')" \
-s "HOUR=$(date '+%H')" \
-s 'UTC_MODE=False' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT12S'
-s "START='$(date '+%Y%m%dT%H%z')'" \
-s "HOUR='$(date '+%H')'" \
-s 'UTC_MODE="False"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT12S"'
#-------------------------------------------------------------------------------
TZSTR="$(date '+%z')"
NOW="$(date '+%Y%m%dT%H')"
run_ok "${TEST_NAME_BASE}-run-past" \
cylc run --debug --no-detach "${SUITE_NAME}" \
-s "START=$(cylc cycle-point "${NOW}" --offset-hour='-10')${TZSTR}" \
-s "HOUR=$(cylc cycle-point "${NOW}" --offset-hour='-10' --print-hour)" \
-s 'UTC_MODE=False' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT1M'
-s "START='$(cylc cycle-point "${NOW}" --offset-hour='-10')${TZSTR}'" \
-s "HOUR='$(cylc cycle-point "${NOW}" --offset-hour='-10' --print-hour)'" \
-s 'UTC_MODE="False"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT1M"'
#-------------------------------------------------------------------------------
NOW="$(date '+%Y%m%dT%H')"
run_fail "${TEST_NAME_BASE}-run-later" \
cylc run --debug --no-detach "${SUITE_NAME}" \
-s "START=$(cylc cycle-point "${NOW}" --offset-hour='10')${TZSTR}" \
-s "HOUR=$(cylc cycle-point "${NOW}" --offset-hour='10' --print-hour)" \
-s 'UTC_MODE=False' \
-s 'OFFSET=PT0S' \
-s 'TIMEOUT=PT12S'
-s "START='$(cylc cycle-point "${NOW}" --offset-hour='10')${TZSTR}'" \
-s "HOUR='$(cylc cycle-point "${NOW}" --offset-hour='10' --print-hour)'" \
-s 'UTC_MODE="False"' \
-s 'OFFSET="PT0S"' \
-s 'TIMEOUT="PT12S"'
#-------------------------------------------------------------------------------
purge
exit
14 changes: 7 additions & 7 deletions tests/flakyfunctional/special/08-clock-triggered-0.t
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,27 @@ set_test_number 4
install_suite "${TEST_NAME_BASE}" "${TEST_NAME_BASE}"
#-------------------------------------------------------------------------------
run_ok "${TEST_NAME_BASE}-validate" \
cylc validate "${SUITE_NAME}" -s START="$(date '+%Y%m%dT%H%z')" \
-s HOUR="$(date '+%H')" -s 'UTC_MODE=False' -s 'TIMEOUT=PT0.2M'
cylc validate "${SUITE_NAME}" -s "START='$(date '+%Y%m%dT%H%z')'" \
-s "HOUR='$(date '+%H')'" -s 'UTC_MODE="False"' -s 'TIMEOUT="PT0.2M"'
#-------------------------------------------------------------------------------
run_ok "${TEST_NAME_BASE}-run-now" \
cylc run --debug --no-detach "${SUITE_NAME}" \
-s START="$(date '+%Y%m%dT%H%z')" \
-s HOUR="$(date '+%H')" -s 'UTC_MODE=False' -s 'TIMEOUT=PT0.2M'
-s "START='$(date '+%Y%m%dT%H%z')'" \
-s "HOUR='$(date '+%H')'" -s 'UTC_MODE="False"' -s 'TIMEOUT="PT0.2M"'
#-------------------------------------------------------------------------------
NOW="$(date '+%Y%m%dT%H')"
START="$(cylc cycle-point "${NOW}" --offset-hour='-10')$(date '+%z')"
HOUR="$(cylc cycle-point "${NOW}" --offset-hour='-10' --print-hour)"
run_ok "${TEST_NAME_BASE}-run-past" \
cylc run --debug --no-detach "${SUITE_NAME}" -s START="${START}" \
-s HOUR="${HOUR}" -s 'UTC_MODE=False' -s 'TIMEOUT=PT1M'
cylc run --debug --no-detach "${SUITE_NAME}" -s "START='${START}'" \
-s "HOUR='${HOUR}'" -s 'UTC_MODE="False"' -s 'TIMEOUT="PT1M"'
#-------------------------------------------------------------------------------
NOW="$(date '+%Y%m%dT%H')"
START="$(cylc cycle-point "${NOW}" --offset-hour='10')$(date '+%z')"
HOUR="$(cylc cycle-point "${NOW}" --offset-hour='10' --print-hour)"
run_fail "${TEST_NAME_BASE}-run-later" \
cylc run --debug --no-detach "${SUITE_NAME}" -s START="${START}" \
-s HOUR="${HOUR}" -s 'UTC_MODE=False' -s 'TIMEOUT=PT0.2M'
-s "HOUR='${HOUR}'" -s 'UTC_MODE="False"' -s 'TIMEOUT="PT0.2M"'
#-------------------------------------------------------------------------------
purge
exit
5 changes: 3 additions & 2 deletions tests/flakyfunctional/xtriggers/00-wall_clock.t
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
. "$(dirname "$0")/test_header"

run_suite() {
cylc run --no-detach --debug "$1" -s "START=$2" -s "HOUR=$3" -s "OFFSET=$4"
cylc run --no-detach --debug "$1" \
-s "START='$2'" -s "HOUR='$3'" -s "OFFSET='$4'"
}

set_test_number 5
Expand All @@ -33,7 +34,7 @@ HOUR="$(date +%H)"
OFFSET="PT0S"

run_ok "${TEST_NAME_BASE}-val" cylc validate "${SUITE_NAME}" \
-s "START=${START}" -s "HOUR=${HOUR}" -s "OFFSET=${OFFSET}"
-s "START='${START}'" -s "HOUR='${HOUR}'" -s "OFFSET='${OFFSET}'"

TEST_NAME="${TEST_NAME_BASE}-now"
run_ok "${TEST_NAME}" run_suite "${SUITE_NAME}" "${START}" "${HOUR}" "${OFFSET}"
Expand Down
4 changes: 2 additions & 2 deletions tests/flakyfunctional/xtriggers/01-suite_state.t
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ run_ok "${TEST_NAME_BASE}-val-up" cylc val --debug "${SUITE_NAME_UPSTREAM}"

# Validate the downstream test suite.
run_ok "${TEST_NAME_BASE}-val" \
cylc val --debug --set="UPSTREAM=${SUITE_NAME_UPSTREAM}" "${SUITE_NAME}"
cylc val --debug --set="UPSTREAM='${SUITE_NAME_UPSTREAM}'" "${SUITE_NAME}"

# Run the upstream suite and detach (not a test).
cylc run "${SUITE_NAME_UPSTREAM}"

# Run the test suite - it should fail after inactivity ...
TEST_NAME="${TEST_NAME_BASE}-run-fail"
suite_run_fail "${TEST_NAME}" \
cylc run --set="UPSTREAM=${SUITE_NAME_UPSTREAM}" --no-detach "${SUITE_NAME}"
cylc run --set="UPSTREAM='${SUITE_NAME_UPSTREAM}'" --no-detach "${SUITE_NAME}"

SUITE_LOG="$(cylc cat-log -m 'p' "${SUITE_NAME}")"
grep_ok 'WARNING - suite timed out after inactivity for PT10S' "${SUITE_LOG}"
Expand Down
Loading

0 comments on commit a6bac41

Please sign in to comment.