Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
15 changes: 12 additions & 3 deletions ros2interface/ros2interface/verb/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,17 @@ def _is_nested(self) -> bool:
return False


def _get_interface_lines(interface_identifier: str) -> typing.Iterable[InterfaceTextLine]:
def _get_interface_lines(
interface_identifier: str,
file_path: str,
) -> typing.Iterable[InterfaceTextLine]:
parts: typing.List[str] = interface_identifier.split('/')
if len(parts) != 3:
raise ValueError(
f"Invalid name '{interface_identifier}'. Expected three parts separated by '/'"
)
pkg_name, _, msg_name = parts

file_path = get_interface_path(interface_identifier)
with open(file_path) as file_handler:
for line in file_handler:
yield InterfaceTextLine(
Expand Down Expand Up @@ -147,7 +149,14 @@ def _show_interface(
is_show_nested_comments: bool = False,
indent_level: int = 0
):
for line in _get_interface_lines(interface_identifier):
file_path = get_interface_path(interface_identifier)
if file_path.endswith('.idl'):
with open(file_path) as file_handler:
content = file_handler.read()
print(content, end='' if content.endswith('\n') else '\n')
return

for line in _get_interface_lines(interface_identifier, file_path):
Comment on lines +152 to +163

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this just displays whatever format the original is in. but it's a UX regression relative to what users get for .msg, where the whole point of interface show is that you see the full recursive structure without opening more files. i think recursive approach or consideration is completely off from this PR.

and what if the case with " .msg parent with an .idl-only nested type"?
the new IDL branch ignores indent_level (and the comment flags) entirely, raw module/struct boilerplate lands un-indented, i think this prints ugly...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. I agree that an unindented raw IDL block in a nested expansion is poor UX. In 1aea823, the raw-IDL branch now applies the existing indent_level recursively to every line. The new CLI integration test covers a .msg parent with an IDL-only nested type.

I kept the IDL body in its original format intentionally: the maintainer guidance in #780 is that ros2 interface show should display the original format because some IDL cannot be converted to .msg / .srv (#780 (comment)).

That decision means the raw IDL branch currently preserves IDL comments for both comment options. Applying --no-comments / --all-comments to raw IDL would require defining an IDL-specific transformation rather than displaying its source. Could you please confirm whether you want that new formatting behavior, or whether preserving raw IDL with correct recursive indentation is the intended scope for this PR?


_print_interface_line(
line, is_show_comments=is_show_comments, indent_level=indent_level)
Expand Down
48 changes: 48 additions & 0 deletions ros2interface/test/test_show.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright 2026 Old-Ding

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is just a test for API, i think unit test for actually idl types should be added to ros2cli_test_interfaces.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. I replaced the temporary API-only test in 1aea823 with real interfaces in ros2cli_test_interfaces:

  • IdlOnly.idl and test_show_idl_message exercise ros2 interface show for a top-level IDL message.
  • ShortVariedIdlNested.msg and test_show_message_with_idl_nested_type exercise a .msg parent whose nested type is IDL, and assert the recursive tab indentation on every IDL line.

These are CLI integration tests, rather than a mocked get_interface_path unit test. I have completed static validation locally (python -m compileall and git diff --check), but this machine has no ROS build environment and no ROS CI job has been scheduled for the new head yet. I will provide the actual ROS test result once the build is available.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update with the requested ROS test result: https://github.com/Old-Ding/ros2cli/actions/runs/29411539491

I built the current PR head in an Ubuntu ROS Rolling container and ran the ros2interface test suite. The run built 3 packages; its test/test_cli.py launch test passed, and colcon test-result --verbose reports 5 tests, 0 errors, 0 failures, 0 skipped. This covers the two new real-IDL CLI cases in that test file.

#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Tests for the interface show verb."""

from ros2interface.verb import show


def test_show_msg_interface(tmp_path, monkeypatch, capsys):
msg_text = 'uint32 value\n'
msg_path = tmp_path / 'Basic.msg'
msg_path.write_text(msg_text)
monkeypatch.setattr(show, 'get_interface_path', lambda _: str(msg_path))

show._show_interface('test_interfaces/msg/Basic')

assert capsys.readouterr().out == msg_text


def test_show_idl_interface(tmp_path, monkeypatch, capsys):
idl_text = """\
module test_interfaces {
module msg {
struct IdlOnly {
uint32 value;
};
};
};
"""
idl_path = tmp_path / 'IdlOnly.idl'
monkeypatch.setattr(show, 'get_interface_path', lambda _: str(idl_path))

for file_text in (idl_text, idl_text.rstrip('\n')):
idl_path.write_text(file_text)
show._show_interface('test_interfaces/msg/IdlOnly')

assert capsys.readouterr().out == idl_text