Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

templatevars: parse CLI opts with literal_eval #3974

Merged
merged 4 commits into from
Dec 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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