Skip to content

Commit 125c48f

Browse files
authored
Merge pull request #6981 from cylc/8.5.x-sync
2 parents 4cbe3de + fc8738f commit 125c48f

File tree

5 files changed

+58
-24
lines changed

5 files changed

+58
-24
lines changed

CHANGES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ $ towncrier create <PR-number>.<break|feat|fix>.md --content "Short description"
1111

1212
<!-- towncrier release notes start -->
1313

14+
## __cylc-8.5.3 (Released 2025-09-09)__
15+
16+
### 🔧 Fixes
17+
18+
[#6590](https://github.com/cylc/cylc-flow/pull/6590) - Fix validation of conditional expressions with negative integer offsets larger than `-P1`.
19+
20+
[#6980](https://github.com/cylc/cylc-flow/pull/6980) - Fixed a bug where the GUI views would go blank when reloading a workflow.
21+
1422
## __cylc-8.5.2 (Released 2025-09-04)__
1523

1624
### 🚀 Enhancements

cylc/flow/commands.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ async def reload_workflow(schd: 'Scheduler', reload_global: bool = False):
624624
schd.task_job_mgr.task_remote_mgr.remote_init_map.clear()
625625
schd.task_job_mgr.task_remote_mgr.is_reload = True
626626
schd.pool.reload(config)
627+
schd.data_store_mgr.apply_task_proxy_db_history()
627628
# Load jobs from DB
628629
schd.workflow_db_mgr.pri_dao.select_jobs_for_restart(
629630
schd.data_store_mgr.insert_db_job

cylc/flow/data_store_mgr.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ def __init__(self, schd, n_edge_distance=1):
570570
self.n_window_completed_walks = set()
571571
self.n_window_depths = {}
572572
self.update_window_depths = False
573-
self.db_load_task_proxies = {}
573+
self.db_load_task_proxies: Dict[str, Tuple[TaskProxy, bool]] = {}
574574
self.family_pruned_ids = set()
575575
self.prune_trigger_nodes = {}
576576
self.prune_flagged_nodes = set()
@@ -1527,12 +1527,10 @@ def apply_task_proxy_db_history(self):
15271527
# added to an already-spawned task before restart.)
15281528

15291529
# Extract info from itasks to data-store.
1530-
for task_info in self.db_load_task_proxies.values():
1530+
for itask, _is_parent in self.db_load_task_proxies.values():
15311531
self._process_internal_task_proxy(
1532-
task_info[0],
1533-
self.added[TASK_PROXIES][
1534-
self.id_.duplicate(task_info[0].tokens).id
1535-
]
1532+
itask,
1533+
self.added[TASK_PROXIES][self.id_.duplicate(itask.tokens).id]
15361534
)
15371535

15381536
# Batch load jobs from DB.

cylc/flow/prerequisite.py

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

tests/integration/test_reload.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
from contextlib import suppress
2020

2121
from cylc.flow import commands
22+
from cylc.flow.data_store_mgr import TASK_PROXIES
23+
from cylc.flow.scheduler import Scheduler
2224
from cylc.flow.task_state import (
2325
TASK_STATUS_WAITING,
2426
TASK_STATUS_PREPARING,
@@ -46,16 +48,7 @@ async def test_reload_waits_for_pending_tasks(
4648
See https://github.com/cylc/cylc-flow/issues/5107
4749
"""
4850
# a simple workflow with a single task
49-
id_ = flow({
50-
'scheduling': {
51-
'graph': {
52-
'R1': 'foo',
53-
},
54-
},
55-
'runtime': {
56-
'foo': {},
57-
},
58-
})
51+
id_ = flow('foo')
5952
schd = scheduler(id_, paused_start=False)
6053

6154
# we will artificially push the task through these states
@@ -270,7 +263,6 @@ async def test_reload_global_platform_group(
270263

271264
# Task using the platform group
272265
conf = {
273-
'scheduler': {'allow implicit tasks': True},
274266
'scheduling': {'graph': {'R1': 'one'}},
275267
'runtime': {
276268
'one': {
@@ -314,3 +306,23 @@ async def test_reload_global_platform_group(
314306
)
315307
platform = get_platform(rtconf)
316308
assert platform['meta']['x'] == '2'
309+
310+
311+
async def test_data_store_tproxy(flow, scheduler, start):
312+
"""Check N>0 task proxy in data store has correct info on reload.
313+
314+
https://github.com/cylc/cylc-flow/issues/6973
315+
"""
316+
schd: Scheduler = scheduler(flow('foo => bar'))
317+
318+
def get_ds_tproxy(task):
319+
return schd.data_store_mgr.data[schd.id][TASK_PROXIES][
320+
f'{schd.id}//1/{task}'
321+
]
322+
323+
async with start(schd):
324+
await schd.update_data_structure()
325+
assert str(get_ds_tproxy('bar').runtime)
326+
327+
await commands.run_cmd(commands.reload_workflow(schd))
328+
assert str(get_ds_tproxy('bar').runtime)

0 commit comments

Comments
 (0)