Skip to content

Commit 5c4532c

Browse files
committed
Squashed commit of the following:
commit ad8231a8f22dd3cd8d887774474f97df2c83e429 Merge: acc0ca3 6fc3c58 Author: Hilary James Oliver <hilary.j.oliver@gmail.com> Date: Mon Mar 20 10:27:19 2023 +1300 Merge branch 'master' into initial-final-graph commit acc0ca3 Author: Hilary Oliver <hilary.j.oliver@gmail.com> Date: Wed Oct 26 12:00:00 2022 +1300 Style fix. commit a7170fb Author: Hilary Oliver <hilary.j.oliver@gmail.com> Date: Wed Oct 26 11:53:31 2022 +1300 Update change log. commit 9024065 Merge: 858a8c1 b0ff549 Author: Hilary Oliver <hilary.j.oliver@gmail.com> Date: Wed Oct 26 11:32:26 2022 +1300 Merge branch 'master' into initial-final-graph commit 858a8c1 Author: Hilary James Oliver <hilary.j.oliver@gmail.com> Date: Mon Sep 26 23:27:01 2022 +1300 Fix alpha/omega graph runahead release. commit b581ab2 Author: Hilary James Oliver <hilary.j.oliver@gmail.com> Date: Mon Sep 26 23:26:33 2022 +1300 Add new func tests. commit 8d09900 Author: Hilary James Oliver <hilary.j.oliver@gmail.com> Date: Mon Sep 26 15:53:42 2022 +1300 Revert graph sorting change. commit 75c1763 Author: Hilary James Oliver <hilary.j.oliver@gmail.com> Date: Fri Sep 23 22:44:08 2022 +1200 Adapt integration tests. commit 1b685a0 Author: Hilary James Oliver <hilary.j.oliver@gmail.com> Date: Fri Sep 23 15:55:57 2022 +1200 Tidy up. commit 7a62450 Author: Hilary James Oliver <hilary.j.oliver@gmail.com> Date: Fri Sep 23 13:20:51 2022 +1200 Switch to alpha and omega. commit 129c2e3 Author: Hilary James Oliver <hilary.j.oliver@gmail.com> Date: Fri Sep 23 10:32:54 2022 +1200 Implicit integer ICP if only nocycle graphs. commit a53ac82 Author: Hilary James Oliver <hilary.j.oliver@gmail.com> Date: Thu Sep 22 16:23:16 2022 +1200 startup and shutdown graphs; needs tidying
1 parent 6fc3c58 commit 5c4532c

File tree

25 files changed

+629
-87
lines changed

25 files changed

+629
-87
lines changed

CHANGES.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ Cylc to crash when preparing the job script.
2424
-------------------------------------------------------------------------------
2525
## __cylc-8.2.0 (<span actions:bind='release-date'>Coming Soon</span>)__
2626

27+
### Enhancements
28+
29+
[#5090](https://github.com/cylc/cylc-flow/pull/5090) - Implement initial and
30+
final graphs, distinct from the main cycling graph.
31+
2732
### Fixes
2833
[#5328](https://github.com/cylc/cylc-flow/pull/5328) -
2934
Efficiency improvements to reduce task management overheads on the Scheduler.
@@ -73,19 +78,20 @@ workflows with many-to-many dependencies (e.g. `<a> => <b>`).
7378

7479
### Enhancements
7580

81+
[#5184](https://github.com/cylc/cylc-flow/pull/5184) - Scan for active
82+
runs of the same workflow at install time.
83+
84+
[#5032](https://github.com/cylc/cylc-flow/pull/5032) - Set a default limit of
85+
7686
[#5229](https://github.com/cylc/cylc-flow/pull/5229) -
7787
- Added a single command to validate a previously run workflow against changes
7888
to its source and reinstall a workflow.
7989
- Allows Cylc commands (including validate, list, view, config, and graph) to load template variables
8090
configured by `cylc install` and `cylc play`.
8191

82-
[#5184](https://github.com/cylc/cylc-flow/pull/5184) - scan for active
83-
runs of the same workflow at install time.
84-
8592
[#5121](https://github.com/cylc/cylc-flow/pull/5121) - Added a single
8693
command to validate, install and play a workflow.
8794

88-
[#5032](https://github.com/cylc/cylc-flow/pull/5032) - set a default limit of
8995
100 for the "default" queue.
9096

9197
[#5055](https://github.com/cylc/cylc-flow/pull/5055) and

cylc/flow/config.py

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@
5454
get_sequence, get_sequence_cls, init_cyclers, get_dump_format,
5555
INTEGER_CYCLING_TYPE, ISO8601_CYCLING_TYPE
5656
)
57+
from cylc.flow.cycling.nocycle import (
58+
NocycleSequence,
59+
NOCYCLE_SEQ_ALPHA,
60+
NOCYCLE_SEQ_OMEGA
61+
)
5762
from cylc.flow.id import Tokens
5863
from cylc.flow.cycling.integer import IntegerInterval
5964
from cylc.flow.cycling.iso8601 import ingest_time, ISO8601Interval
@@ -270,6 +275,7 @@ def __init__(
270275
self.start_point: 'PointBase'
271276
self.stop_point: Optional['PointBase'] = None
272277
self.final_point: Optional['PointBase'] = None
278+
self.nocycle_sequences: Set['NocycleSequence'] = set()
273279
self.sequences: List['SequenceBase'] = []
274280
self.actual_first_point: Optional['PointBase'] = None
275281
self._start_point_for_actual_first_point: Optional['PointBase'] = None
@@ -618,9 +624,16 @@ def prelim_process_graph(self) -> None:
618624
if (
619625
'cycling mode' not in self.cfg['scheduling'] and
620626
self.cfg['scheduling'].get('initial cycle point', '1') == '1' and
621-
all(item in ['graph', '1', 'R1'] for item in graphdict)
627+
all(
628+
item in [
629+
'graph', '1', 'R1',
630+
str(NOCYCLE_SEQ_ALPHA),
631+
str(NOCYCLE_SEQ_OMEGA)
632+
]
633+
for item in graphdict
634+
)
622635
):
623-
# Pure acyclic graph, assume integer cycling mode with '1' cycle
636+
# Non-cycling graph, assume integer cycling mode with '1' cycle
624637
self.cfg['scheduling']['cycling mode'] = INTEGER_CYCLING_TYPE
625638
for key in ('initial cycle point', 'final cycle point'):
626639
if key not in self.cfg['scheduling']:
@@ -2087,15 +2100,24 @@ def load_graph(self):
20872100
try:
20882101
seq = get_sequence(section, icp, fcp)
20892102
except (AttributeError, TypeError, ValueError, CylcError) as exc:
2090-
if cylc.flow.flags.verbosity > 1:
2091-
traceback.print_exc()
2092-
msg = 'Cannot process recurrence %s' % section
2093-
msg += ' (initial cycle point=%s)' % icp
2094-
msg += ' (final cycle point=%s)' % fcp
2095-
if isinstance(exc, CylcError):
2096-
msg += ' %s' % exc.args[0]
2097-
raise WorkflowConfigError(msg)
2098-
self.sequences.append(seq)
2103+
try:
2104+
seq = NocycleSequence(section)
2105+
except ValueError:
2106+
if cylc.flow.flags.verbosity > 1:
2107+
traceback.print_exc()
2108+
msg = (
2109+
f"Cannot process recurrence {section}"
2110+
f" (initial cycle point={icp})"
2111+
f" (final cycle point={fcp})"
2112+
)
2113+
if isinstance(exc, CylcError):
2114+
msg += ' %s' % exc.args[0]
2115+
raise WorkflowConfigError(msg)
2116+
else:
2117+
self.nocycle_sequences.add(seq)
2118+
else:
2119+
self.sequences.append(seq)
2120+
20992121
parser = GraphParser(
21002122
family_map,
21012123
self.parameters,

cylc/flow/cycling/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,11 @@ def TYPE_SORT_KEY(self) -> int:
345345
@classmethod
346346
@abstractmethod # Note: stacked decorator not strictly enforced in Py2.x
347347
def get_async_expr(cls, start_point=0):
348-
"""Express a one-off sequence at the initial cycle point."""
348+
"""Express a one-off sequence at the initial cycle point.
349+
350+
Note "async" has nothing to do with asyncio. It was a (bad)
351+
name for one-off (non-cycling) graphs in early Cylc versions.
352+
"""
349353
pass
350354

351355
@abstractmethod

cylc/flow/cycling/integer.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@
2121
import re
2222

2323
from cylc.flow.cycling import (
24-
PointBase, IntervalBase, SequenceBase, ExclusionBase, parse_exclusion, cmp
24+
PointBase,
25+
IntervalBase,
26+
SequenceBase,
27+
ExclusionBase,
28+
parse_exclusion,
29+
cmp
2530
)
2631
from cylc.flow.exceptions import (
2732
CylcMissingContextPointError,

cylc/flow/cycling/nocycle.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
2+
# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
3+
#
4+
# This program is free software: you can redistribute it and/or modify
5+
# it under the terms of the GNU General Public License as published by
6+
# the Free Software Foundation, either version 3 of the License, or
7+
# (at your option) any later version.
8+
#
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License
15+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
"""
18+
Cycling logic for isolated non-cycling startup and shutdown graphs.
19+
"""
20+
21+
from cylc.flow.cycling import PointBase, SequenceBase, cmp
22+
23+
# TODO: scheduler check DB to be sure alpha and omega sections have run or not.
24+
25+
# cycle point values
26+
NOCYCLE_PT_ALPHA = "alpha"
27+
NOCYCLE_PT_OMEGA = "omega"
28+
29+
NOCYCLE_POINTS = (
30+
NOCYCLE_PT_ALPHA,
31+
NOCYCLE_PT_OMEGA
32+
)
33+
34+
CYCLER_TYPE_NOCYCLE = "nocycle"
35+
CYCLER_TYPE_SORT_KEY_NOCYCLE = 1
36+
37+
38+
class NocyclePoint(PointBase):
39+
"""A string-valued point."""
40+
41+
TYPE = CYCLER_TYPE_NOCYCLE
42+
TYPE_SORT_KEY = CYCLER_TYPE_SORT_KEY_NOCYCLE
43+
44+
__slots__ = ('value')
45+
46+
def __init__(self, value: str) -> None:
47+
if value not in [NOCYCLE_PT_ALPHA, NOCYCLE_PT_OMEGA]:
48+
raise ValueError(f"Illegal Nocycle value {value}")
49+
self.value = value
50+
51+
def __hash__(self):
52+
return hash(self.value)
53+
54+
def __eq__(self, other):
55+
return str(other) == self.value
56+
57+
def __le__(self, other):
58+
"""less than or equal only if equal."""
59+
return str(other) == self.value
60+
61+
def __lt__(self, other):
62+
"""never less than."""
63+
return False
64+
65+
def __gt__(self, other):
66+
"""never greater than."""
67+
return False
68+
69+
def __str__(self):
70+
return self.value
71+
72+
def _cmp(self, other):
73+
return cmp(int(self), int(other))
74+
75+
def add(self, other):
76+
# NOT USED
77+
return None
78+
79+
def sub(self, other):
80+
# NOT USED
81+
return None
82+
83+
84+
class NocycleSequence(SequenceBase):
85+
"""A single point sequence."""
86+
87+
def __init__(self, dep_section, p_context_start=None, p_context_stop=None):
88+
"""Workflow cycling context is ignored."""
89+
self.point = NocyclePoint(dep_section)
90+
91+
def __hash__(self):
92+
return hash(str(self.point))
93+
94+
def is_valid(self, point):
95+
"""Is point on-sequence and in-bounds?"""
96+
return str(point) == self.point
97+
98+
def get_first_point(self, point):
99+
"""First point is the only point"""
100+
return self.point
101+
102+
def get_next_point(self, point):
103+
"""There is no next point"""
104+
return None
105+
106+
def get_next_point_on_sequence(self, point):
107+
"""There is no next point"""
108+
return None
109+
110+
def __eq__(self, other):
111+
try:
112+
return other.point == self.point
113+
except AttributeError:
114+
# (other is not a nocycle sequence)
115+
return False
116+
117+
def __str__(self):
118+
return str(self.point)
119+
120+
def TYPE(self) -> str:
121+
raise NotImplementedError
122+
123+
def TYPE_SORT_KEY(self) -> int:
124+
raise NotImplementedError
125+
126+
def get_async_expr(cls, start_point=0):
127+
raise NotImplementedError
128+
129+
def get_interval(self):
130+
"""Return the cycling interval of this sequence."""
131+
raise NotImplementedError
132+
133+
def get_offset(self):
134+
"""Deprecated: return the offset used for this sequence."""
135+
raise NotImplementedError
136+
137+
def set_offset(self, i_offset):
138+
"""Deprecated: alter state to offset the entire sequence."""
139+
raise NotImplementedError
140+
141+
def is_on_sequence(self, point):
142+
"""Is point on-sequence, disregarding bounds?"""
143+
raise NotImplementedError
144+
145+
def get_prev_point(self, point):
146+
"""Return the previous point < point, or None if out of bounds."""
147+
raise NotImplementedError
148+
149+
def get_nearest_prev_point(self, point):
150+
"""Return the largest point < some arbitrary point."""
151+
raise NotImplementedError
152+
153+
def get_stop_point(self):
154+
"""Return the last point in this sequence, or None if unbounded."""
155+
raise NotImplementedError
156+
157+
158+
NOCYCLE_SEQ_ALPHA = NocycleSequence(NOCYCLE_PT_ALPHA)
159+
NOCYCLE_SEQ_OMEGA = NocycleSequence(NOCYCLE_PT_OMEGA)

0 commit comments

Comments
 (0)