Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cylc show: More user friendly pre-requisite labels #2191

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 28 additions & 20 deletions bin/cylc-show
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ def main():
('REG', 'Suite name'),
('[TASKID ...]', 'Task names or identifiers')])

parser.add_option('--list-prereqs', action="store_true", default=False,
help="Print a task's pre-requisites as a list.")

options, args = parser.parse_args()
suite = args[0]
task_args = args[1:]
Expand Down Expand Up @@ -73,29 +76,34 @@ def main():

if task_ids:
results, bad_items = pclient.get_info(
'get_task_requisites', items=task_ids)
'get_task_requisites', items=task_ids,
list_prereqs=options.list_prereqs)
for task_id, result in sorted(results.items()):
if len(results) > 1:
print "----\nTASK ID: %s" % task_id
for key, value in sorted(
result["descriptions"].items(), reverse=True):
print "%s: %s" % (key, value or "(not given)")

for name, done in [
("prerequisites", "satisfied"), ("outputs", "completed")]:
print '\n%s (- => not %s):' % (name, done)
if not result[name]:
print ' (None)'
for msg, state in result[name]:
if state:
print ' + ' + msg
else:
print ' - ' + msg

if result["extras"]:
print '\nother:'
for key, value in result["extras"].items():
print ' o %s ... %s' % (key, value)
if options.list_prereqs:
for prereq in result["prerequisites"]:
print prereq
else:
for key, value in sorted(
result["descriptions"].items(), reverse=True):
print "%s: %s" % (key, value or "(not given)")

for name, done in [("prerequisites", "satisfied"),
("outputs", "completed")]:
print '\n%s (- => not %s):' % (name, done)
if not result[name]:
print ' (None)'
for msg, state in result[name]:
if state:
print ' + ' + msg
else:
print ' - ' + msg

if result["extras"]:
print '\nother:'
for key, value in result["extras"].items():
print ' o %s ... %s' % (key, value)
for bad_item in bad_items:
sys.stderr.write("No matching tasks found: %s\n" % bad_item)
if bad_items:
Expand Down
5 changes: 3 additions & 2 deletions lib/cylc/network/https/suite_info_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,11 @@ def get_graph_raw(self, start_point_string, stop_point_string,

@cherrypy.expose
@cherrypy.tools.json_out()
def get_task_requisites(self, items):
def get_task_requisites(self, items=None, list_prereqs=False):
if not isinstance(items, list):
items = [items]
return self._put("get_task_requisites", (items,))
return self._put("get_task_requisites", (items,),
{"list_prereqs": list_prereqs in [True, 'True']})

def _put(self, command, command_args, command_kwargs=None):
if command_args is None:
Expand Down
19 changes: 14 additions & 5 deletions lib/cylc/prerequisite.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import math
import re
import sys

from cylc.conditional_simplifier import ConditionalSimplifier
from cylc.cycling.loader import get_point
from cylc.suite_logging import ERR
Expand Down Expand Up @@ -192,11 +194,18 @@ def dump(self):
# return an array of strings representing each message and its state
res = []
if self.raw_conditional_expression:
for label, val in self.satisfied.items():
res.append([' LABEL: %s = %s' %
(label, self.messages[label]), val])
res.append(['CONDITION: %s' %
self.raw_conditional_expression, self.is_satisfied()])
temp = self.raw_conditional_expression
labels = []
num_length = int(math.ceil(float(len(self.labels)) / float(10)))
for ind, (task, label,) in enumerate(sorted(self.labels.items())):
char = '%.{0}d'.format(num_length) % ind
labels.append(['\t%s = %s' % (char, task),
self.satisfied[label]])
temp = temp.replace(label, char)
temp = temp.replace('|', ' | ')
temp = temp.replace('&', ' & ')
res.append([temp, self.is_satisfied()])
res.extend(labels)
elif self.satisfied:
for label, val in self.satisfied.items():
res.append([self.messages[label], val])
Expand Down
4 changes: 2 additions & 2 deletions lib/cylc/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -814,9 +814,9 @@ def info_get_graph_raw(self, cto, ctn, group_nodes=None,
rgraph, self.config.suite_polling_tasks, self.config.leaves,
self.config.feet)

def info_get_task_requisites(self, items):
def info_get_task_requisites(self, items, list_prereqs=False):
"""Return prerequisites of a task."""
return self.pool.get_task_requisites(items)
return self.pool.get_task_requisites(items, list_prereqs=list_prereqs)

def command_set_stop_cleanly(self, kill_active_tasks=False):
"""Stop job submission and set the flag for clean shutdown."""
Expand Down
8 changes: 7 additions & 1 deletion lib/cylc/task_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,7 @@ def get_task_jobfile_path(self, id_):
return path, os.path.dirname(os.path.dirname(path))
return False, "task not found"

def get_task_requisites(self, items):
def get_task_requisites(self, items, list_prereqs=False):
"""Return task prerequisites.

Result in a dict of a dict:
Expand All @@ -1402,6 +1402,12 @@ def get_task_requisites(self, items):
itasks, bad_items = self._filter_task_proxies(items)
results = {}
for itask in itasks:
if list_prereqs:
results[itask.identity] = {
'prerequisites': itask.state.prerequisites_dump(
list_prereqs=True)}
continue

extras = {}
if itask.tdef.clocktrigger_offset is not None:
extras['Clock trigger time reached'] = (
Expand Down
11 changes: 8 additions & 3 deletions lib/cylc/task_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,16 @@ def set_prerequisites_not_satisfied(self):
prereq.set_not_satisfied()
self._is_satisfied = None

def prerequisites_dump(self):
def prerequisites_dump(self, list_prereqs=False):
"""Dump prerequisites."""
res = []
for preq in self.prerequisites:
res += preq.dump()
if list_prereqs:
for prereq in self.prerequisites:
for task in sorted(prereq.labels):
res.append(task)
else:
for preq in self.prerequisites:
res += preq.dump()
return res

def get_resolved_dependencies(self):
Expand Down
64 changes: 64 additions & 0 deletions tests/cylc-show/05-complex.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/bash
# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
# Copyright (C) 2008-2017 NIWA
#
# 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 <http://www.gnu.org/licenses/>.
#-------------------------------------------------------------------------------
# Test cylc show for a basic task.
. $(dirname $0)/test_header
#-------------------------------------------------------------------------------
set_test_number 6
#-------------------------------------------------------------------------------
install_suite "${TEST_NAME_BASE}" "${TEST_NAME_BASE}"
#-------------------------------------------------------------------------------
TEST_NAME="${TEST_NAME_BASE}-validate"
run_ok "${TEST_NAME}" cylc validate "${SUITE_NAME}"
#-------------------------------------------------------------------------------
TEST_NAME="${TEST_NAME_BASE}-run"
run_ok "${TEST_NAME}" cylc run "${SUITE_NAME}" --hold
#-------------------------------------------------------------------------------
TEST_NAME="${TEST_NAME_BASE}-long"
run_ok "${TEST_NAME}" cylc show "${SUITE_NAME}" 'f.20000102T00Z'
cmp_ok "${TEST_NAME}.stdout" << '__OUT__'
title: (not given)
description: (not given)

prerequisites (- => not satisfied):
- 0 & 1 & (2 | (3 & 4)) & 5
- 0 = a.20000102T0000Z succeeded
- 1 = b.20000102T0000Z succeeded
- 2 = c.20000102T0000Z succeeded
- 3 = d.20000102T0000Z succeeded
- 4 = e.20000102T0000Z succeeded
- 5 = f.20000101T0000Z succeeded

outputs (- => not completed):
- f.20000102T0000Z submitted
- f.20000102T0000Z started
- f.20000102T0000Z succeeded
__OUT__
#-------------------------------------------------------------------------------
TEST_NAME="${TEST_NAME_BASE}-short"
run_ok "${TEST_NAME}" cylc show "${SUITE_NAME}" 'f.20000102T00Z' --list-prereqs
cmp_ok "${TEST_NAME}.stdout" << '__OUT__'
a.20000102T0000Z succeeded
b.20000102T0000Z succeeded
c.20000102T0000Z succeeded
d.20000102T0000Z succeeded
e.20000102T0000Z succeeded
f.20000101T0000Z succeeded
__OUT__
#-------------------------------------------------------------------------------
cylc stop "${SUITE_NAME}" --now
purge_suite "${SUITE_NAME}"
13 changes: 13 additions & 0 deletions tests/cylc-show/05-complex/suite.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[cylc]
UTC mode = True
[scheduling]
initial cycle point = 2000
spawn to max active cycle points = True
max active cycle points = 2
[[dependencies]]
[[[T00]]]
graph = a & b & (c | (d & e)) & f[-P1D] => f
[runtime]
[[root]]
script = sleep 1
[[a, b, c, d, e, f]]
13 changes: 7 additions & 6 deletions tests/triggering/16-fam-expansion.t
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ TEST_NAME=$TEST_NAME_BASE-show
run_ok $TEST_NAME cylc show $SUITE_NAME bar.1
#-------------------------------------------------------------------------------
contains_ok $TEST_NAME.stdout <<'__SHOW_DUMP__'
- LABEL: foo3_colon_succeed = foo3.1 succeeded
- LABEL: foo1_colon_succeed = foo1.1 succeeded
- LABEL: foo2_colon_succeed = foo2.1 succeeded
- LABEL: foo3_colon_fail = foo3.1 failed
- LABEL: foo2_colon_fail = foo2.1 failed
- LABEL: foo1_colon_fail = foo1.1 failed
- (((1 | 0) & (3 | 2) & (5 | 4)) & (0 | 2 | 4))
- 0 = foo1.1 failed
- 1 = foo1.1 succeeded
- 2 = foo2.1 failed
- 3 = foo2.1 succeeded
- 4 = foo3.1 failed
- 5 = foo3.1 succeeded
__SHOW_DUMP__
#-------------------------------------------------------------------------------
cylc stop $SUITE_NAME
Expand Down