diff --git a/changes.d/6892.feat.md b/changes.d/6892.feat.md new file mode 100644 index 00000000000..4ca1eda92a9 --- /dev/null +++ b/changes.d/6892.feat.md @@ -0,0 +1 @@ +Added `--format=json` option to `cylc broadcast` for use with the `--display` option. Deprecated the `--raw` option in favour of `--format=raw`. diff --git a/cylc/flow/scripts/broadcast.py b/cylc/flow/scripts/broadcast.py index 86b96cc39d6..b9ae72863cb 100755 --- a/cylc/flow/scripts/broadcast.py +++ b/cylc/flow/scripts/broadcast.py @@ -111,6 +111,11 @@ from optparse import Values +RAW_DEPR_MSG = ( + "DEPRECATED: the --raw option will be removed at Cylc 8.7; " + "use --format=raw instead." +) + REC_ITEM = re.compile(r'^\[([^\]]*)\](.*)$') MUTATION = ''' @@ -312,12 +317,33 @@ def get_option_parser() -> COP: help="Use unicode box characters with -d, -k.", action="store_true", default=False, dest="unicode") + # BACK COMPAT: --raw + # From: < 8.5.1 + # To: 8.5.1 + # Remove at: 8.7.0 parser.add_option( "-r", "--raw", - help="With -d/--display or -k/--display-task, write out " - "the broadcast config structure in raw Python form.", + help=( + "With -d/--display or -k/--display-task, write out " + "the broadcast config structure in raw Python form. " + f"{RAW_DEPR_MSG}" + ), action="store_true", default=False, dest="raw") + parser.add_option( + '--format', + help=( + "With -d/--display or -k/--display-task, write out " + "the broadcast config structure in one of the following formats: " + "tree, json, or raw (like json but as a Python dictionary). " + r"Default: %default." + ), + action='store', + dest='format', + choices=('tree', 'json', 'raw'), + default='tree', + ) + return parser @@ -356,6 +382,9 @@ async def run(options: 'Values', workflow_id): } + if options.raw: + ret['stderr'].append(cparse(f"{RAW_DEPR_MSG}")) + if options.show or options.showtask: if options.showtask: try: @@ -369,7 +398,12 @@ async def run(options: 'Values', workflow_id): for wflow in result['workflows']: settings = wflow['broadcasts'] padding = get_padding(settings) * ' ' - if options.raw: + if options.format == 'json': + import json + ret['stdout'].append( + json.dumps(settings, indent=2, sort_keys=True) + ) + elif options.raw or options.format == 'raw': ret['stdout'].append(str(settings)) else: ret['stdout'].extend( diff --git a/tests/functional/broadcast/14-display-format.t b/tests/functional/broadcast/14-display-format.t new file mode 100644 index 00000000000..239d10827a4 --- /dev/null +++ b/tests/functional/broadcast/14-display-format.t @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. +# Copyright (C) NIWA & British Crown (Met Office) & Contributors. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test the --format option. + +. "$(dirname "$0")/test_header" +set_test_number 6 + +init_workflow "${TEST_NAME_BASE}" << '__EOF__' +[scheduler] + [[events]] + stall timeout = PT0S + abort on stall timeout = True +[scheduling] + [[graph]] + R1 = foo +[runtime] + [[foo]] + pre-script = """ + cylc broadcast "$CYLC_WORKFLOW_ID" \ + -p "$CYLC_TASK_CYCLE_POINT" -n "$CYLC_TASK_NAME" \ + --set '[environment]horse=dorothy' \ + --set 'post-script=echo "$horse"' + """ + script = """ + cylc broadcast "$CYLC_WORKFLOW_ID" --display --format json > out.json + cylc broadcast "$CYLC_WORKFLOW_ID" --display --format raw > raw1.stdout + # Test deprecated option: + cylc broadcast "$CYLC_WORKFLOW_ID" --display --raw 1> raw2.stdout 2> raw2.stderr + """ +__EOF__ + +run_ok "${TEST_NAME_BASE}-validate" cylc validate "${WORKFLOW_NAME}" +workflow_run_ok "${TEST_NAME_BASE}-run" cylc play "${WORKFLOW_NAME}" --no-detach + +FOO_WORK_DIR="${WORKFLOW_RUN_DIR}/work/1/foo" + +TEST_NAME="${TEST_NAME_BASE}-cmp-json" +cmp_json "$TEST_NAME" "${FOO_WORK_DIR}/out.json" << '__EOF__' +{ + "1": { + "foo": { + "environment": { + "horse": "dorothy" + }, + "post-script": "echo \"$horse\"" + } + } +} +__EOF__ + +cmp_ok "${FOO_WORK_DIR}/raw1.stdout" << '__EOF__' +{'1': {'foo': {'environment': {'horse': 'dorothy'}, 'post-script': 'echo "$horse"'}}} +__EOF__ + +cmp_ok "${FOO_WORK_DIR}/raw2.stdout" "${FOO_WORK_DIR}/raw1.stdout" + +cmp_ok "${FOO_WORK_DIR}/raw2.stderr" << __EOF__ +DEPRECATED: the --raw option will be removed at Cylc 8.7; use --format=raw instead. +__EOF__ + +purge