Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 58 additions & 15 deletions ros2action/ros2action/verb/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,25 @@
from ros2cli.node.strategy import NodeStrategy


def _split_fully_qualified_name(fqn):
if not fqn.startswith('/'):
return '/', fqn
idx = fqn.rfind('/')
if idx == 0:
return '/', fqn[1:]
return fqn[:idx], fqn[idx + 1:]


def _format_action_endpoint_block(node_fqn, types, endpoint_label):
node_namespace, node_name = _split_fully_qualified_name(node_fqn)
return (
f'Node name: {node_name}\n'
f'Node namespace: {node_namespace}\n'
f'Action type: {", ".join(types)}\n'
f'Endpoint type: {endpoint_label}'
)


class InfoVerb(VerbExtension):
"""Print information about an action."""

Expand All @@ -33,6 +52,12 @@ def add_arguments(self, parser, cli_name):
parser.add_argument(
'-c', '--count', action='store_true',
help='Only display the number of action clients and action servers')
parser.add_argument(
'--verbose', '-v', action='store_true',
help='Prints detailed information for each action client and action server, '
'including the node name, node namespace, action type, and endpoint type '
'(CLIENT or SERVER). QoS profiles and type hashes are not exposed for '
'action endpoints.')

def main(self, *, args):
with NodeStrategy(args) as node:
Expand All @@ -44,20 +69,38 @@ def main(self, *, args):
except (ValueError, rclpy.exceptions.InvalidTopicNameException) as e:
raise RuntimeError(e)

print('Action: {}'.format(args.action_name))
print('Action clients: {}'.format(len(action_clients)))
line_end = '\n\n' if args.verbose else '\n'

print('Action: {}'.format(args.action_name), end=line_end)

print('Action clients: {}'.format(len(action_clients)), end=line_end)
if not args.count:
for client_name, client_types in action_clients:
if args.show_types:
types_formatted = ', '.join(client_types)
print(f' {client_name} [{types_formatted}]')
else:
print(f' {client_name}')
print('Action servers: {}'.format(len(action_servers)))
if args.verbose:
for node_fqn, client_types in action_clients:
print(
_format_action_endpoint_block(node_fqn, client_types, 'CLIENT'),
end=line_end,
)
else:
for client_name, client_types in action_clients:
if args.show_types:
types_formatted = ', '.join(client_types)
print(f' {client_name} [{types_formatted}]')
else:
print(f' {client_name}')

print('Action servers: {}'.format(len(action_servers)), end=line_end)
if not args.count:
for server_name, server_types in action_servers:
if args.show_types:
types_formatted = ', '.join(server_types)
print(f' {server_name} [{types_formatted}]')
else:
print(f' {server_name}')
if args.verbose:
for node_fqn, server_types in action_servers:
print(
_format_action_endpoint_block(node_fqn, server_types, 'SERVER'),
end=line_end,
)
else:
for server_name, server_types in action_servers:
if args.show_types:
types_formatted = ', '.join(server_types)
print(f' {server_name} [{types_formatted}]')
else:
print(f' {server_name}')
38 changes: 38 additions & 0 deletions ros2action/test/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,44 @@ def test_fibonacci_info_count(self):
strict=False
)

@launch_testing.markers.retry_on_failure(times=5, delay=1)
def test_fibonacci_info_verbose(self):
with self.launch_action_command(
arguments=['info', '-v', '/test/fibonacci']) as action_command:
assert action_command.wait_for_shutdown(timeout=10)
assert action_command.exit_code == launch_testing.asserts.EXIT_OK
assert launch_testing.tools.expect_output(
expected_lines=[
'Action: /test/fibonacci',
'Action clients: 0',
'Action servers: 1',
'Node name: fibonacci_action_server',
'Node namespace: /test',
'Action type: test_msgs/action/Fibonacci',
'Endpoint type: SERVER',
],
text=action_command.output,
strict=False
)

@launch_testing.markers.retry_on_failure(times=5, delay=1)
def test_fibonacci_info_verbose_count(self):
with self.launch_action_command(
arguments=['info', '-v', '-c', '/test/fibonacci']) as action_command:
assert action_command.wait_for_shutdown(timeout=10)
assert action_command.exit_code == launch_testing.asserts.EXIT_OK
assert launch_testing.tools.expect_output(
expected_lines=[
'Action: /test/fibonacci',
'Action clients: 0',
'Action servers: 1',
],
text=action_command.output,
strict=False
)
assert 'Node name:' not in action_command.output
assert 'Endpoint type:' not in action_command.output

@launch_testing.markers.retry_on_failure(times=5, delay=1)
def test_list(self):
with self.launch_action_command(arguments=['list']) as action_command:
Expand Down