diff --git a/CHANGES.md b/CHANGES.md index ea9a0a05323..49008dcb7cd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -38,6 +38,11 @@ namespace, under `cylc.jinja.filters`. [#3541](https://github.com/cylc/cylc-flow/pull/3541) - Don't warn that a task was already added to an internal queue, if the queue is the same. +[#3602](https://github.com/cylc/cylc-flow/pull/3602) - Fix a bug that prevented +cycle point format conversion by the `cylc suite-state` command and the +`suite_state` xtrigger function, if the target suite used the default format +but downstream command or suite did not. + ------------------------------------------------------------------------------- ## __cylc-8.0a2 (2019-Q4?)__ diff --git a/cylc/flow/config.py b/cylc/flow/config.py index 409baaa27b9..cc18109a133 100644 --- a/cylc/flow/config.py +++ b/cylc/flow/config.py @@ -50,7 +50,7 @@ from cylc.flow.cycling.loader import ( get_point, get_point_relative, get_interval, get_interval_cls, get_sequence, get_sequence_cls, init_cyclers, INTEGER_CYCLING_TYPE, - ISO8601_CYCLING_TYPE) + ISO8601_CYCLING_TYPE, get_dump_format) from cylc.flow.cycling.iso8601 import ingest_time import cylc.flow.flags from cylc.flow.graphnode import GraphNodeParser @@ -311,6 +311,8 @@ def __init__( # after the call to init_cyclers, we can start getting proper points. init_cyclers(self.cfg) + self.cycling_type = get_interval_cls().get_null().TYPE + self.cycle_point_dump_format = get_dump_format(self.cycling_type) # Running in UTC time? (else just use the system clock) if self.cfg['cylc']['UTC mode'] is None: @@ -374,7 +376,7 @@ def __init__( fcp_str = self.cfg['scheduling']['final cycle point'] if fcp_str is not None: # Is the final "point"(/interval) relative to initial? - if get_interval_cls().get_null().TYPE == INTEGER_CYCLING_TYPE: + if self.cycling_type == INTEGER_CYCLING_TYPE: if "P" in fcp_str: # Relative, integer cycling. self.final_point = get_point_relative( @@ -1050,7 +1052,7 @@ def compute_runahead_limits(self): if not limit: limit = None if (limit is not None and limit.isdigit() and - get_interval_cls().get_null().TYPE == ISO8601_CYCLING_TYPE): + self.cycling_type == ISO8601_CYCLING_TYPE): # Backwards-compatibility for raw number of hours. limit = "PT%sH" % limit diff --git a/cylc/flow/cycling/integer.py b/cylc/flow/cycling/integer.py index bb8bfe5274b..1a88f7aed10 100644 --- a/cylc/flow/cycling/integer.py +++ b/cylc/flow/cycling/integer.py @@ -595,6 +595,12 @@ def init_from_cfg(_): pass +def get_dump_format(cycling_type=None): + """Return cycle point string dump format.""" + # Not used for integer cycling. + return None + + def get_point_relative(point_expr, context_point): """Create a point from relative_string applied to base_point.""" if REC_RELATIVE_POINT.search(point_expr): diff --git a/cylc/flow/cycling/iso8601.py b/cylc/flow/cycling/iso8601.py index 54b67f98365..2c98048eff0 100644 --- a/cylc/flow/cycling/iso8601.py +++ b/cylc/flow/cycling/iso8601.py @@ -843,6 +843,11 @@ def init(num_expanded_year_digits=0, custom_dump_format=None, time_zone=None, ) +def get_dump_format(): + """Return cycle point string dump format.""" + return SuiteSpecifics.DUMP_FORMAT + + def get_point_relative(offset_string, base_point): """Create a point from offset_string applied to base_point.""" try: diff --git a/cylc/flow/cycling/loader.py b/cylc/flow/cycling/loader.py index f7c3e0e220b..7451e8e3762 100644 --- a/cylc/flow/cycling/loader.py +++ b/cylc/flow/cycling/loader.py @@ -36,6 +36,9 @@ POINTS = {INTEGER_CYCLING_TYPE: integer.IntegerPoint, ISO8601_CYCLING_TYPE: iso8601.ISO8601Point} +DUMP_FORMAT_GETTERS = {INTEGER_CYCLING_TYPE: integer.get_dump_format, + ISO8601_CYCLING_TYPE: iso8601.get_dump_format} + POINT_RELATIVE_GETTERS = { INTEGER_CYCLING_TYPE: integer.get_point_relative, ISO8601_CYCLING_TYPE: iso8601.get_point_relative @@ -73,6 +76,11 @@ def get_point_cls(cycling_type=None): return POINTS[cycling_type] +def get_dump_format(cycling_type=None): + """Return cycle point dump format, or None.""" + return DUMP_FORMAT_GETTERS[cycling_type]() + + def get_point_relative(*args, **kwargs): """Return a point from an offset expression and a base point.""" cycling_type = kwargs.pop("cycling_type", DefaultCycler.TYPE) diff --git a/cylc/flow/scripts/cylc_validate.py b/cylc/flow/scripts/cylc_validate.py index c1247ab65c6..1cd7e65f7ce 100755 --- a/cylc/flow/scripts/cylc_validate.py +++ b/cylc/flow/scripts/cylc_validate.py @@ -82,7 +82,6 @@ def parse_args(): @cli_function(parse_args) def main(_, options, reg): """cylc validate CLI.""" - # import pdb; pdb.set_trace() profiler = Profiler(options.profile_mode) profiler.start() diff --git a/cylc/flow/suite_db_mgr.py b/cylc/flow/suite_db_mgr.py index 2d55844efef..fa3ec70bc64 100644 --- a/cylc/flow/suite_db_mgr.py +++ b/cylc/flow/suite_db_mgr.py @@ -291,10 +291,10 @@ def put_suite_params(self, schd): {"key": "cylc_version", "value": CYLC_VERSION}, {"key": "UTC_mode", "value": get_utc_mode()}, ]) - if schd.config.cfg['cylc']['cycle point format']: + if schd.config.cycle_point_dump_format is not None: self.db_inserts_map[self.TABLE_SUITE_PARAMS].append({ "key": "cycle_point_format", - "value": schd.config.cfg['cylc']['cycle point format']}) + "value": schd.config.cycle_point_dump_format}) if schd.pool.is_held: self.db_inserts_map[self.TABLE_SUITE_PARAMS].append({ "key": self.KEY_HOLD, "value": 1}) diff --git a/tests/suite-state/06-format.t b/tests/suite-state/06-format.t index ad06f53b395..1649937e2ce 100755 --- a/tests/suite-state/06-format.t +++ b/tests/suite-state/06-format.t @@ -15,24 +15,36 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . #------------------------------------------------------------------------------- -# Test cylc suite-state "template" option +# Test "cylc suite-state" cycle point format conversion, when the target suite +# sets an explicit cycle point format, and the CLI does not. . "$(dirname "$0")/test_header" #------------------------------------------------------------------------------- set_test_number 5 #------------------------------------------------------------------------------- -install_suite "${TEST_NAME_BASE}" format +init_suite "${TEST_NAME_BASE}" <<'__SUITERC__' +[cylc] + UTC mode = True + cycle point format = CCYY-MM-DD +[scheduling] + initial cycle point = 20100101 +[[graph]] + R1 = foo +[runtime] + [[foo]] + script = true +__SUITERC__ #------------------------------------------------------------------------------- TEST_NAME="${TEST_NAME_BASE}-run" suite_run_ok "${TEST_NAME}" cylc run --debug --no-detach "${SUITE_NAME}" #------------------------------------------------------------------------------- -TEST_NAME=${TEST_NAME_BASE}-cli-template-poll +TEST_NAME=${TEST_NAME_BASE}-cli-poll run_ok "${TEST_NAME}" cylc suite-state "${SUITE_NAME}" -p 20100101T0000Z \ --task=foo --status=succeeded contains_ok "${TEST_NAME}.stdout" <<__OUT__ polling for 'succeeded': satisfied __OUT__ #------------------------------------------------------------------------------- -TEST_NAME=${TEST_NAME_BASE}-cli-template-dump +TEST_NAME=${TEST_NAME_BASE}-cli-dump run_ok "${TEST_NAME}" cylc suite-state "${SUITE_NAME}" -p 20100101T0000Z contains_ok "${TEST_NAME}.stdout" <<__OUT__ foo, 2010-01-01, succeeded diff --git a/tests/suite-state/06a-noformat.t b/tests/suite-state/06a-noformat.t new file mode 100755 index 00000000000..403f75b5e0d --- /dev/null +++ b/tests/suite-state/06a-noformat.t @@ -0,0 +1,56 @@ +#!/bin/bash +# THIS FILE IS PART OF THE CYLC SUITE 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 "cylc suite-state" cycle point format conversion, when the target suite +# sets no explicit cycle point format, and the CLI does (the reverse of 06.t). + +. "$(dirname "$0")/test_header" +#------------------------------------------------------------------------------- +set_test_number 5 +#------------------------------------------------------------------------------- +init_suite "${TEST_NAME_BASE}" <<'__SUITERC__' +[cylc] + UTC mode = True + # (Use default cycle point format) +[scheduling] + initial cycle point = 20100101T0000Z +[[graph]] + R1 = foo +[runtime] + [[foo]] + script = true +__SUITERC__ +#------------------------------------------------------------------------------- +TEST_NAME="${TEST_NAME_BASE}-run" +suite_run_ok "${TEST_NAME}" cylc run --debug --no-detach "${SUITE_NAME}" +#------------------------------------------------------------------------------- +TEST_NAME=${TEST_NAME_BASE}-cli-poll +run_ok "${TEST_NAME}" cylc suite-state "${SUITE_NAME}" -p 2010-01-01T00:00Z \ + --task=foo --status=succeeded +contains_ok "${TEST_NAME}.stdout" <<__OUT__ +polling for 'succeeded': satisfied +__OUT__ +#------------------------------------------------------------------------------- +TEST_NAME=${TEST_NAME_BASE}-cli-dump +run_ok "${TEST_NAME}" cylc suite-state "${SUITE_NAME}" -p 2010-01-01T00:00Z +contains_ok "${TEST_NAME}.stdout" <<__OUT__ +foo, 20100101T0000Z, succeeded +__OUT__ +#------------------------------------------------------------------------------- +purge_suite "${SUITE_NAME}" +#------------------------------------------------------------------------------- +exit 0 diff --git a/tests/suite-state/format/suite.rc b/tests/suite-state/format/suite.rc deleted file mode 100644 index 84ccd865335..00000000000 --- a/tests/suite-state/format/suite.rc +++ /dev/null @@ -1,13 +0,0 @@ -[cylc] - UTC mode = True - cycle point format = CCYY-MM-DD - -[scheduling] - initial cycle point = 20100101 - -[[graph]] - R1 = foo - -[runtime] - [[foo]] - script = true