Skip to content

Commit

Permalink
CLI: Fix verdi process [show|report|status|watch|call-root] no output
Browse files Browse the repository at this point in the history
The commands take one or more processes, but if no processes were
provided no output was shown whatsoever which can be confusing to the
user. Now an error is now shown if no processes are defined.
  • Loading branch information
agoscinski authored and sphuber committed Jun 7, 2024
1 parent 0812f4b commit a56a138
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 12 deletions.
36 changes: 36 additions & 0 deletions src/aiida/cmdline/commands/cmd_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ def process_show(processes, most_recent_node):
"""Show details for one or multiple processes."""
from aiida.cmdline.utils.common import get_node_info

if not processes and not most_recent_node:
raise click.UsageError(
'Please specify one or multiple processes by their identifier (PK, UUID or label) or use an option.'
)

if processes and most_recent_node:
raise click.BadOptionUsage(
'most_recent_node',
Expand All @@ -206,6 +211,8 @@ def process_show(processes, most_recent_node):
@decorators.with_dbenv()
def process_call_root(processes):
"""Show root process of the call stack for the given processes."""
if not processes:
raise click.UsageError('Please specify one or multiple processes by their identifier (PK, UUID or label).')
for process in processes:
caller = process.caller

Expand Down Expand Up @@ -244,6 +251,11 @@ def process_report(processes, most_recent_node, levelname, indent_size, max_dept
from aiida.cmdline.utils.common import get_calcjob_report, get_process_function_report, get_workchain_report
from aiida.orm import CalcFunctionNode, CalcJobNode, WorkChainNode, WorkFunctionNode

if not processes and not most_recent_node:
raise click.UsageError(
'Please specify one or multiple processes by their identifier (PK, UUID or label) or use an option.'
)

if processes and most_recent_node:
raise click.BadOptionUsage(
'most_recent_node',
Expand Down Expand Up @@ -275,6 +287,11 @@ def process_status(call_link_label, most_recent_node, max_depth, processes):
"""Print the status of one or multiple processes."""
from aiida.cmdline.utils.ascii_vis import format_call_graph

if not processes and not most_recent_node:
raise click.UsageError(
'Please specify one or multiple processes by their identifier (PK, UUID or label) or use an option.'
)

if processes and most_recent_node:
raise click.BadOptionUsage(
'most_recent_node',
Expand All @@ -299,6 +316,11 @@ def process_kill(processes, all_entries, timeout, wait):
"""Kill running processes."""
from aiida.engine.processes import control

if not processes and not all_entries:
raise click.UsageError(
'Please specify one or multiple processes by their identifier (PK, UUID or label) or use an option.'
)

if processes and all_entries:
raise click.BadOptionUsage('all', 'cannot specify individual processes and the `--all` flag at the same time.')

Expand Down Expand Up @@ -326,6 +348,11 @@ def process_pause(processes, all_entries, timeout, wait):
"""Pause running processes."""
from aiida.engine.processes import control

if not processes and not all_entries:
raise click.UsageError(
'Please specify one or multiple processes by their identifier (PK, UUID or label) or use an option.'
)

if processes and all_entries:
raise click.BadOptionUsage('all', 'cannot specify individual processes and the `--all` flag at the same time.')

Expand All @@ -350,6 +377,11 @@ def process_play(processes, all_entries, timeout, wait):
"""Play (unpause) paused processes."""
from aiida.engine.processes import control

if not processes and not all_entries:
raise click.UsageError(
'Please specify one or multiple processes by their identifier (PK, UUID or label) or use an option.'
)

if processes and all_entries:
raise click.BadOptionUsage('all', 'cannot specify individual processes and the `--all` flag at the same time.')

Expand All @@ -370,6 +402,10 @@ def process_play(processes, all_entries, timeout, wait):
@decorators.only_if_daemon_running(echo.echo_warning, 'daemon is not running, so process may not be reachable')
def process_watch(broker, processes):
"""Watch the state transitions for a process."""

if not processes:
raise click.UsageError('Please specify one or multiple processes by their identifier (PK, UUID or label).')

from time import sleep

from kiwipy import BroadcastFilter
Expand Down
1 change: 1 addition & 0 deletions src/aiida/cmdline/utils/echo.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class ExitCode(enum.IntEnum):
"""Exit codes for the verdi command line."""

CRITICAL = 1
USAGE_ERROR = 2
DEPRECATED = 80
UNKNOWN = 99
SUCCESS = 0
Expand Down
58 changes: 46 additions & 12 deletions tests/cmdline/commands/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,11 @@ def test_process_show(self, run_cli_command):
calcjob_one.store()
calcjob_two.store()

# Running without identifiers should not except and not print anything
# Running without identifiers should except and print something
options = []
result = run_cli_command(cmd_process.process_show, options)

assert len(result.output_lines) == 0
result = run_cli_command(cmd_process.process_show, options, raises=True)
assert result.exit_code == ExitCode.USAGE_ERROR
assert len(result.output_lines) > 0

# Giving a single identifier should print a non empty string message
options = [str(workchain_one.pk)]
Expand All @@ -232,11 +232,11 @@ def test_process_report(self, run_cli_command):
"""Test verdi process report"""
node = WorkflowNode().store()

# Running without identifiers should not except and not print anything
# Running without identifiers should except and print something
options = []
result = run_cli_command(cmd_process.process_report, options)

assert len(result.output_lines) == 0
result = run_cli_command(cmd_process.process_report, options, raises=True)
assert result.exit_code == ExitCode.USAGE_ERROR
assert len(result.output_lines) > 0

# Giving a single identifier should print a non empty string message
options = [str(node.pk)]
Expand All @@ -255,11 +255,11 @@ def test_process_status(self, run_cli_command):
node = WorkflowNode().store()
node.set_process_state(ProcessState.RUNNING)

# Running without identifiers should not except and not print anything
# Running without identifiers should except and print something
options = []
result = run_cli_command(cmd_process.process_status, options)
assert result.exception is None, result.output
assert len(result.output_lines) == 0
result = run_cli_command(cmd_process.process_status, options, raises=True)
assert result.exit_code == ExitCode.USAGE_ERROR
assert len(result.output_lines) > 0

# Giving a single identifier should print a non empty string message
options = [str(node.pk)]
Expand All @@ -273,6 +273,15 @@ def test_process_status(self, run_cli_command):
assert result.exception is None, result.output
assert len(result.output_lines) == 0

@pytest.mark.requires_rmq
def test_process_watch(self, run_cli_command):
"""Test verdi process watch"""
# Running without identifiers should except and print something
options = []
result = run_cli_command(cmd_process.process_watch, options, raises=True)
assert result.exit_code == ExitCode.USAGE_ERROR
assert len(result.output_lines) > 0

def test_process_status_call_link_label(self, run_cli_command):
"""Test ``verdi process status --call-link-label``."""
node = WorkflowNode().store()
Expand Down Expand Up @@ -460,6 +469,13 @@ def test_multiple_processes(self, run_cli_command):
assert str(self.node_root.pk) in result.output_lines[1]
assert str(self.node_root.pk) in result.output_lines[2]

def test_no_process_argument(self, run_cli_command):
# Running without identifiers should except and print something
options = []
result = run_cli_command(cmd_process.process_call_root, options, raises=True)
assert result.exit_code == ExitCode.USAGE_ERROR
assert len(result.output_lines) > 0


@pytest.mark.requires_rmq
@pytest.mark.usefixtures('started_daemon_client')
Expand All @@ -471,6 +487,12 @@ def test_process_pause(submit_and_await, run_cli_command):
run_cli_command(cmd_process.process_pause, [str(node.pk), '--wait'])
await_condition(lambda: node.paused)

# Running without identifiers should except and print something
options = []
result = run_cli_command(cmd_process.process_pause, options, raises=True)
assert result.exit_code == ExitCode.USAGE_ERROR
assert len(result.output_lines) > 0


@pytest.mark.requires_rmq
@pytest.mark.usefixtures('started_daemon_client')
Expand All @@ -484,6 +506,12 @@ def test_process_play(submit_and_await, run_cli_command):
run_cli_command(cmd_process.process_play, [str(node.pk), '--wait'])
await_condition(lambda: not node.paused)

# Running without identifiers should except and print something
options = []
result = run_cli_command(cmd_process.process_play, options, raises=True)
assert result.exit_code == ExitCode.USAGE_ERROR
assert len(result.output_lines) > 0


@pytest.mark.requires_rmq
@pytest.mark.usefixtures('started_daemon_client')
Expand Down Expand Up @@ -515,6 +543,12 @@ def test_process_kill(submit_and_await, run_cli_command):
await_condition(lambda: node.is_killed)
assert node.process_status == 'Killed through `verdi process kill`'

# Running without identifiers should except and print something
options = []
result = run_cli_command(cmd_process.process_kill, options, raises=True)
assert result.exit_code == ExitCode.USAGE_ERROR
assert len(result.output_lines) > 0


@pytest.mark.requires_rmq
@pytest.mark.usefixtures('started_daemon_client')
Expand Down

0 comments on commit a56a138

Please sign in to comment.