Skip to content

Commit

Permalink
Merge pull request #6482 from oliver-sanders/coverage++
Browse files Browse the repository at this point in the history
coverage: fill some coverage holes
  • Loading branch information
hjoliver authored Nov 20, 2024
2 parents 1cbd009 + efdebd8 commit 062c5a1
Show file tree
Hide file tree
Showing 11 changed files with 589 additions and 57 deletions.
41 changes: 0 additions & 41 deletions cylc/flow/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
get_cylc_run_dir,
is_relative_to,
)
from cylc.flow.print_tree import print_tree
from cylc.flow.task_qualifiers import ALT_QUALIFIERS
from cylc.flow.simulation import configure_sim_modes
from cylc.flow.subprocctx import SubFuncContext
Expand Down Expand Up @@ -1604,18 +1603,6 @@ def get_linearized_ancestors(self):
def get_first_parent_descendants(self):
return self.runtime['first-parent descendants']

@staticmethod
def define_inheritance_tree(tree, hierarchy):
"""Combine inheritance hierarchies into a tree structure."""
for rt_ in hierarchy:
hier = copy(hierarchy[rt_])
hier.reverse()
cur_tree = tree
for item in hier:
if item not in cur_tree:
cur_tree[item] = {}
cur_tree = cur_tree[item]

def add_tree_titles(self, tree):
for key, val in tree.items():
if val == {}:
Expand Down Expand Up @@ -1651,34 +1638,6 @@ def get_mro(self, ns):
mro = ["no such namespace: " + ns]
return mro

def print_first_parent_tree(self, pretty=False, titles=False):
# find task namespaces (no descendants)
tasks = []
for ns in self.cfg['runtime']:
if ns not in self.runtime['descendants']:
tasks.append(ns)

pruned_ancestors = self.get_first_parent_ancestors(pruned=True)
tree = {}
self.define_inheritance_tree(tree, pruned_ancestors)
padding = ''
if titles:
self.add_tree_titles(tree)
# compute pre-title padding
maxlen = 0
for namespace in pruned_ancestors:
items = copy(pruned_ancestors[namespace])
items.reverse()
for itt, item in enumerate(items):
tmp = 2 * itt + 1 + len(item)
if itt == 0:
tmp -= 1
if tmp > maxlen:
maxlen = tmp
padding = maxlen * ' '

print_tree(tree, padding=padding, use_unicode=pretty)

def process_workflow_env(self):
"""Export Workflow context to the local environment.
Expand Down
5 changes: 1 addition & 4 deletions cylc/flow/cycling/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def standardise(self, allow_truncated: bool = True) -> 'PointBase':
missing off the front) will be tollerated, if False, truncated
points will cause an exception to be raised.
"""
return self
raise NotImplementedError

@abstractmethod
def sub(self, other):
Expand Down Expand Up @@ -254,9 +254,6 @@ def sub(self, other):
"""Subtract other (interval) from self; return an interval."""
pass

def is_null(self):
return (self == self.get_null())

def __str__(self) -> str:
# Stringify.
return self.value
Expand Down
70 changes: 62 additions & 8 deletions cylc/flow/scripts/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,22 @@
"""

import asyncio
from copy import copy
import os
from pathlib import Path
import sys
from typing import TYPE_CHECKING

from cylc.flow.config import WorkflowConfig
from cylc.flow.exceptions import InputError
from cylc.flow.id_cli import parse_id_async
from cylc.flow.option_parsers import (
AGAINST_SOURCE_OPTION,
WORKFLOW_ID_OR_PATH_ARG_DOC,
CylcOptionParser as COP,
icp_option,
)
from cylc.flow.print_tree import print_tree
from cylc.flow.workflow_files import get_workflow_run_dir
from cylc.flow.templatevars import get_template_vars
from cylc.flow.terminal import cli_function
Expand Down Expand Up @@ -109,10 +112,51 @@ def get_option_parser():

@cli_function(get_option_parser)
def main(parser: COP, options: 'Values', workflow_id: str) -> None:
asyncio.run(_main(parser, options, workflow_id))


async def _main(parser: COP, options: 'Values', workflow_id: str) -> None:
asyncio.run(_main(options, workflow_id))


def define_inheritance_tree(tree, hierarchy):
"""Combine inheritance hierarchies into a tree structure."""
for rt_ in hierarchy:
hier = copy(hierarchy[rt_])
hier.reverse()
cur_tree = tree
for item in hier:
if item not in cur_tree:
cur_tree[item] = {}
cur_tree = cur_tree[item]


def print_first_parent_tree(config, pretty=False, titles=False):
# find task namespaces (no descendants)
tasks = []
for ns in config.cfg['runtime']:
if ns not in config.runtime['descendants']:
tasks.append(ns)

pruned_ancestors = config.get_first_parent_ancestors(pruned=True)
tree = {}
define_inheritance_tree(tree, pruned_ancestors)
padding = ''
if titles:
config.add_tree_titles(tree)
# compute pre-title padding
maxlen = 0
for namespace in pruned_ancestors:
items = copy(pruned_ancestors[namespace])
items.reverse()
for itt, item in enumerate(items):
tmp = 2 * itt + 1 + len(item)
if itt == 0:
tmp -= 1
if tmp > maxlen:
maxlen = tmp
padding = maxlen * ' '

print_tree(tree, padding=padding, use_unicode=pretty)


async def _main(options: 'Values', workflow_id: str) -> None:
workflow_id, _, flow_file = await parse_id_async(
workflow_id,
src=True,
Expand All @@ -121,7 +165,14 @@ async def _main(parser: COP, options: 'Values', workflow_id: str) -> None:
template_vars = get_template_vars(options)

if options.all_tasks and options.all_namespaces:
parser.error("Choose either -a or -n")
raise InputError("Choose either -a or -n")
if (options.all_tasks or options.all_namespaces) and options.prange:
raise InputError(
'--points cannot be used with --all-tasks or --all-namespaces'
)
if options.box and not options.tree:
options.tree = True

if options.all_tasks:
which = "all tasks"
elif options.all_namespaces:
Expand All @@ -147,7 +198,7 @@ async def _main(parser: COP, options: 'Values', workflow_id: str) -> None:
options.tree = False

if options.titles and options.mro:
parser.error("Please choose --mro or --title, not both")
raise InputError("Please choose --mro or --title, not both")

if options.tree and any(
[options.all_tasks, options.all_namespaces, options.mro]):
Expand All @@ -166,8 +217,11 @@ async def _main(parser: COP, options: 'Values', workflow_id: str) -> None:
template_vars
)
if options.tree:
config.print_first_parent_tree(
pretty=options.box, titles=options.titles)
print_first_parent_tree(
config,
pretty=options.box,
titles=options.titles,
)
elif options.prange:
for node in sorted(config.get_node_labels(tr_start, tr_stop)):
print(node)
Expand Down
14 changes: 13 additions & 1 deletion tests/functional/cylc-config/09-platforms.t
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# Test cylc config --platform-names and --platforms
. "$(dirname "$0")/test_header"
#-------------------------------------------------------------------------------
set_test_number 5
set_test_number 7
#-------------------------------------------------------------------------------
cat > "global.cylc" <<__HEREDOC__
[platforms]
Expand Down Expand Up @@ -63,4 +63,16 @@ head -n 10 > just_platforms < global.cylc
run_ok "${TEST_NAME}" cylc config --platforms
cmp_ok "${TEST_NAME}.stdout" "just_platforms"

#-------------------------------------------------------------------------------
# test with no platforms or platform groups defined
rm "global.cylc"
touch "global.cylc"

TEST_NAME="${TEST_NAME_BASE}-names"
run_ok "${TEST_NAME}" cylc config --platform-names
cmp_ok "${TEST_NAME}.stdout" <<__HEREDOC__
localhost
__HEREDOC__

exit
61 changes: 61 additions & 0 deletions tests/functional/rnd/08-cylc-list.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
#
# 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/>.
#-------------------------------------------------------------------------------
# Functional test of the cylc-list command
# (see integration tests for more comprehensive tests)

. "$(dirname "$0")/test_header"
set_test_number 4


cat > flow.cylc <<__FLOW__
[scheduling]
[[graph]]
R1 = c
[runtime]
[[A]]
[[[meta]]]
title = Aaa
[[B]]
inherit = A
[[[meta]]]
title = Bbb
[[c]]
inherit = B
[[[meta]]]
title = Ccc
__FLOW__


# test signals on a detached scheduler
TEST_NAME="${TEST_NAME_BASE}-list"
run_ok "$TEST_NAME" cylc list '.' --all-namespaces --with-titles
cmp_ok "${TEST_NAME}.stdout" << __HERE__
A Aaa
B Bbb
c Ccc
root
__HERE__

TEST_NAME="${TEST_NAME_BASE}-tree"
run_ok "$TEST_NAME" cylc list '.' --tree --with-titles
cmp_ok "${TEST_NAME}.stdout" << '__HERE__'
root
`-A
`-B
`-c Ccc
__HERE__
Loading

0 comments on commit 062c5a1

Please sign in to comment.