Skip to content

Commit

Permalink
Post-merge tweaks.
Browse files Browse the repository at this point in the history
  • Loading branch information
hjoliver committed Feb 13, 2025
1 parent 3bed101 commit a0b65ba
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 115 deletions.
3 changes: 2 additions & 1 deletion changes.d/5090.feat.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Implement initial and final graphs, distinct from the main cycling graph.
Distinct initial and final graphs, separated from the main cycling graph,
to make it easier to configure special behaviour at startup and shutdown.
25 changes: 18 additions & 7 deletions cylc/flow/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,8 +608,13 @@ def _warn_if_queues_have_implicit_tasks(
)

def prelim_process_graph(self) -> None:
"""Ensure graph is not empty; set integer cycling mode and icp/fcp = 1
for simplest "R1 = foo" type graphs.
"""Error if graph empty; set integer cycling and icp/fcp = 1,
if those settings are omitted and the graph is acyclic graphs.
Somewhat relevant notes:
- The default (if not set) cycling mode, gregorian, requires an ICP.
- cycling mode is not stored in the DB, so recompute for restarts.
"""
graphdict = self.cfg['scheduling']['graph']
if not any(graphdict.values()):
Expand All @@ -619,15 +624,20 @@ def prelim_process_graph(self) -> None:
'cycling mode' not in self.cfg['scheduling'] and
self.cfg['scheduling'].get('initial cycle point', '1') == '1' and
all(
item in [
'graph', '1', 'R1',
seq in [
'R1',
str(NOCYCLE_SEQ_ALPHA),
str(NOCYCLE_SEQ_OMEGA)
str(NOCYCLE_SEQ_OMEGA),
'graph', # Cylc 7 back-compat
'1' # Cylc 7 back-compat?
]
for item in graphdict
for seq in graphdict
)
):
# Non-cycling graph, assume integer cycling mode with '1' cycle
# Pure acyclic graph, assume integer cycling mode with '1' cycle
# Note typos in "alpha", "omega", or "R1" will appear as cyclic
# here, but will be fatal later during proper recurrance checking.

self.cfg['scheduling']['cycling mode'] = INTEGER_CYCLING_TYPE
for key in ('initial cycle point', 'final cycle point'):
if key not in self.cfg['scheduling']:
Expand Down Expand Up @@ -2260,6 +2270,7 @@ def load_graph(self):
seq = get_sequence(section, icp, fcp)
except (AttributeError, TypeError, ValueError, CylcError) as exc:
try:

Check warning on line 2272 in cylc/flow/config.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/config.py#L2272

Added line #L2272 was not covered by tests
# is it an alpha or omega graph?
seq = NocycleSequence(section)
except ValueError:

Check warning on line 2275 in cylc/flow/config.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/config.py#L2274-L2275

Added lines #L2274 - L2275 were not covered by tests
if cylc.flow.flags.verbosity > 1:
Expand Down
128 changes: 105 additions & 23 deletions cylc/flow/cycling/nocycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
Cycling logic for isolated non-cycling startup and shutdown graphs.
"""

from cylc.flow.cycling import PointBase, SequenceBase, cmp

# TODO: scheduler check DB to be sure alpha and omega sections have run or not.
from cylc.flow.cycling import PointBase, SequenceBase

# cycle point values
NOCYCLE_PT_ALPHA = "alpha"
Expand All @@ -34,91 +32,175 @@
CYCLER_TYPE_NOCYCLE = "nocycle"
CYCLER_TYPE_SORT_KEY_NOCYCLE = 1

# Unused abstract methods below left to raise NotImplementedError.


class NocyclePoint(PointBase):
"""A string-valued point."""
"""A non-advancing string-valued cycle point."""

TYPE = CYCLER_TYPE_NOCYCLE
TYPE_SORT_KEY = CYCLER_TYPE_SORT_KEY_NOCYCLE

__slots__ = ('value')

def __init__(self, value: str) -> None:
"""Initialise a nocycle point.
>>> NocyclePoint(NOCYCLE_PT_ALPHA)
alpha
>>> NocyclePoint("beta")
Traceback (most recent call last):
ValueError: Illegal Nocycle value 'beta'
"""
if value not in [NOCYCLE_PT_ALPHA, NOCYCLE_PT_OMEGA]:
raise ValueError(f"Illegal Nocycle value {value}")
raise ValueError(f"Illegal Nocycle value '{value}'")
self.value = value

def __hash__(self):
"""Hash it.
>>> bool(hash(NocyclePoint(NOCYCLE_PT_ALPHA)))
True
"""
return hash(self.value)

def __eq__(self, other):
return str(other) == self.value
"""Equality.
>>> NocyclePoint(NOCYCLE_PT_ALPHA) == NocyclePoint(NOCYCLE_PT_ALPHA)
True
>>> NocyclePoint(NOCYCLE_PT_ALPHA) == NocyclePoint(NOCYCLE_PT_OMEGA)
False
"""
return str(other) == str(self.value)

def __le__(self, other):
"""less than or equal only if equal."""
"""Less than or equal (only if equal).
>>> NocyclePoint(NOCYCLE_PT_ALPHA) <= NocyclePoint(NOCYCLE_PT_ALPHA)
True
>>> NocyclePoint(NOCYCLE_PT_ALPHA) <= NocyclePoint(NOCYCLE_PT_OMEGA)
False
"""
return str(other) == self.value

def __lt__(self, other):
"""never less than."""
"""Less than (never).
>>> NocyclePoint(NOCYCLE_PT_ALPHA) < NocyclePoint(NOCYCLE_PT_ALPHA)
False
>>> NocyclePoint(NOCYCLE_PT_ALPHA) < NocyclePoint(NOCYCLE_PT_OMEGA)
False
"""
return False

def __gt__(self, other):
"""never greater than."""
"""Greater than (never).
>>> NocyclePoint(NOCYCLE_PT_ALPHA) > NocyclePoint(NOCYCLE_PT_ALPHA)
False
>>> NocyclePoint(NOCYCLE_PT_ALPHA) > NocyclePoint(NOCYCLE_PT_OMEGA)
False
"""
return False

def __str__(self):
"""
>>> str(NocyclePoint(NOCYCLE_PT_ALPHA))
'alpha'
>>> str(NocyclePoint(NOCYCLE_PT_OMEGA))
'omega'
"""
return self.value

def _cmp(self, other):
return cmp(int(self), int(other))
raise NotImplementedError

def add(self, other):
# NOT USED
return None
# Not used.
raise NotImplementedError

def sub(self, other):
# NOT USED
return None
# Not used.
raise NotImplementedError


class NocycleSequence(SequenceBase):
"""A single point sequence."""

def __init__(self, dep_section, p_context_start=None, p_context_stop=None):
"""Workflow cycling context is ignored."""
"""Workflow cycling context is ignored.
>>> NocycleSequence("alpha").point
alpha
"""
self.point = NocyclePoint(dep_section)

def __hash__(self):
"""Hash it.
>>> bool(hash(NocycleSequence("alpha")))
True
"""
return hash(str(self.point))

def is_valid(self, point):
"""Is point on-sequence and in-bounds?"""
return str(point) == self.point
"""Is point on-sequence and in-bounds?
>>> NocycleSequence("alpha").is_valid("alpha")
True
>>> NocycleSequence("alpha").is_valid("omega")
False
"""
return str(point) == str(self.point)

def get_first_point(self, point):
"""First point is the only point"""
"""First point is the only point.
>>> NocycleSequence("alpha").get_first_point("omega")
alpha
"""
return self.point

def get_start_point(self, point):
"""First point is the only point"""
"""First point is the only point."""
# Not used.
raise NotImplementedError
return self.point

Check warning on line 168 in cylc/flow/cycling/nocycle.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/cycling/nocycle.py#L168

Added line #L168 was not covered by tests

def get_next_point(self, point):
"""There is no next point"""
"""There is no next point.
>>> NocycleSequence("alpha").get_next_point("alpha")
"""
return None

def get_next_point_on_sequence(self, point):
"""There is no next point"""
"""There is no next point.
>>> NocycleSequence("alpha").get_next_point_on_sequence("alpha")
"""
return None

def __eq__(self, other):
"""Equality.
>>> NocycleSequence("alpha") == NocycleSequence("alpha")
True
>>> NocycleSequence("alpha") == NocycleSequence("omega")
False
"""
try:
return other.point == self.point
return str(other.point) == str(self.point)
except AttributeError:

Check warning on line 194 in cylc/flow/cycling/nocycle.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/cycling/nocycle.py#L194

Added line #L194 was not covered by tests
# (other is not a nocycle sequence)
# (other has not .point)
return False

Check warning on line 196 in cylc/flow/cycling/nocycle.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/cycling/nocycle.py#L196

Added line #L196 was not covered by tests

def __str__(self):
"""String.
>>> str(NocycleSequence("alpha"))
'alpha'
"""
return str(self.point)

def TYPE(self):
Expand Down
Loading

0 comments on commit a0b65ba

Please sign in to comment.