Skip to content

Commit cc49761

Browse files
hjoliverMetRonnie
andauthored
Fix evaluation of conditional expressions at negative cycle points (#6590)
* Fix prerequisite conditional expression sub. * Add a doctest. * Tweak new prereq sub code. --------- Co-authored-by: Ronnie Dutta <[email protected]>
1 parent 7c4af1c commit cc49761

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

changes.d/6590.fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix validation of conditional expressions with negative integer offsets larger than `-P1`.

cylc/flow/prerequisite.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,26 +198,41 @@ def set_conditional_expr(self, expr):
198198
199199
Examples:
200200
# GH #3644 construct conditional expression when one task name
201-
# is a substring of another: foo | xfoo => bar.
202-
# Add 'foo' to the 'satisfied' dict before 'xfoo'.
201+
# is a substring of another: 11/foo | 1/foo => bar.
203202
>>> preq = Prerequisite(1)
204203
>>> preq[(1, 'foo', 'succeeded')] = False
205-
>>> preq[(1, 'xfoo', 'succeeded')] = False
206-
>>> preq.set_conditional_expr("1/foo succeeded|1/xfoo succeeded")
204+
>>> preq[(11, 'foo', 'succeeded')] = False
205+
>>> preq.set_conditional_expr("11/foo succeeded|1/foo succeeded")
207206
>>> expr = preq.conditional_expression
208207
>>> expr.split('|') # doctest: +NORMALIZE_WHITESPACE
209-
['bool(self._satisfied[("1", "foo", "succeeded")])',
210-
'bool(self._satisfied[("1", "xfoo", "succeeded")])']
208+
['bool(self._satisfied[("11", "foo", "succeeded")])',
209+
'bool(self._satisfied[("1", "foo", "succeeded")])']
211210
211+
# GH #6588 integer offset "x[-P2] | a" gives a negative cycle point
212+
# during validation, for evaluation at the initial cycle point 1.
213+
>>> preq = Prerequisite(1)
214+
>>> preq[(-1, 'x', 'succeeded')] = False
215+
>>> preq[(1, 'a', 'succeeded')] = False
216+
>>> preq.set_conditional_expr("-1/x succeeded|1/a succeeded")
217+
>>> expr = preq.conditional_expression
218+
>>> expr.split('|') # doctest: +NORMALIZE_WHITESPACE
219+
['bool(self._satisfied[("-1", "x", "succeeded")])',
220+
'bool(self._satisfied[("1", "a", "succeeded")])']
212221
"""
213222
self._cached_satisfied = None
214223
if '|' in expr:
215224
# Make a Python expression so we can eval() the logic.
216225
for t_output in self._satisfied:
217226
# Use '\b' in case one task name is a substring of another
218227
# and escape special chars ('.', timezone '+') in task IDs.
228+
msg = self.MESSAGE_TEMPLATE % t_output
229+
if msg[0] == '-':
230+
# -ve cycles: \b needs to be to the right of the `-` char.
231+
pattern = fr"-\b{re.escape(msg[1:])}\b"
232+
else:
233+
pattern = fr"\b{re.escape(msg)}\b"
219234
expr = re.sub(
220-
fr"\b{re.escape(self.MESSAGE_TEMPLATE % t_output)}\b",
235+
pattern,
221236
self.SATISFIED_TEMPLATE % t_output,
222237
expr
223238
)

0 commit comments

Comments
 (0)