Skip to content

Commit

Permalink
Merge branch 'main' into 136-trailing-spaces
Browse files Browse the repository at this point in the history
  • Loading branch information
lengau authored Sep 10, 2024
2 parents 7fa64c8 + 73e896e commit 1b98f96
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 8 deletions.
28 changes: 25 additions & 3 deletions craft_cli/helptexts.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ def _build_plain_command_help(
self,
usage: str,
overview: str,
parameters: list[tuple[str, str]],
options: list[tuple[str, str]],
other_command_names: list[str],
) -> list[str]:
Expand All @@ -285,6 +286,7 @@ def _build_plain_command_help(
- usage
- summary
- positional arguments (only if parameters are not empty)
- options
- other related commands
- footer
Expand All @@ -306,6 +308,13 @@ def _build_plain_command_help(
# column alignment is dictated by longest options title
max_title_len = max(len(title) for title, text in options)

if parameters:
# command positional arguments
positional_args_lines = ["Positional arguments:"]
for title, text in parameters:
positional_args_lines.extend(_build_item_plain(title, text, max_title_len))
textblocks.append("\n".join(positional_args_lines))

# command options
option_lines = ["Options:"]
for title, text in options:
Expand All @@ -330,6 +339,7 @@ def _build_markdown_command_help(
self,
usage: str,
overview: str,
parameters: list[tuple[str, str]],
options: list[tuple[str, str]],
other_command_names: list[str],
) -> list[str]:
Expand All @@ -339,6 +349,7 @@ def _build_markdown_command_help(
- usage
- summary
- positional arguments (only if parameters are not empty)
- options
- other related commands
- footer
Expand All @@ -359,6 +370,17 @@ def _build_markdown_command_help(
overview = process_overview_for_markdown(overview)
textblocks.append(f"## Summary:\n\n{overview}")

if parameters:
parameters_lines = [
"## Positional arguments:",
"| | |",
"|-|-|",
]
for title, text in parameters:
parameters_lines.append(f"| `{title}` | {text} |")

textblocks.append("\n".join(parameters_lines))

option_lines = [
"## Options:",
"| | |",
Expand Down Expand Up @@ -403,11 +425,11 @@ def get_command_help(
if name[0] == "-":
options.append((name, title))
else:
parameters.append(name)
parameters.append((name, title))

usage = f"{self.appname} {command.name} [options]"
if parameters:
usage += " " + " ".join(f"<{parameter}>" for parameter in parameters)
usage += " " + " ".join(f"<{parameter[0]}>" for parameter in parameters)

for command_group in self.command_groups:
if any(isinstance(command, command_class) for command_class in command_group.commands):
Expand All @@ -422,7 +444,7 @@ def get_command_help(
builder = self._build_markdown_command_help
else:
builder = self._build_plain_command_help
textblocks = builder(usage, command.overview, options, other_command_names)
textblocks = builder(usage, command.overview, parameters, options, other_command_names)

# join all stripped blocks, leaving ONE empty blank line between
return "\n\n".join(block.strip() for block in textblocks) + "\n"
8 changes: 5 additions & 3 deletions craft_cli/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ def ended_ok(self) -> None:
"""Finish the messaging system gracefully."""
self._stop()

def _report_error(self, error: errors.CraftError) -> None:
def _report_error(self, error: errors.CraftError) -> None: # noqa: PLR0912 (too many branches)
"""Report the different message lines from a CraftError."""
if self._mode in (EmitterMode.QUIET, EmitterMode.BRIEF, EmitterMode.VERBOSE):
use_timestamp = False
Expand All @@ -719,8 +719,10 @@ def _report_error(self, error: errors.CraftError) -> None:
use_timestamp = True
full_stream = sys.stderr

# the initial message
self._printer.show(sys.stderr, str(error), use_timestamp=use_timestamp, end_line=True)
# The initial message. Print every line individually to correctly clear
# previous lines, if necessary.
for line in str(error).splitlines():
self._printer.show(sys.stderr, line, use_timestamp=use_timestamp, end_line=True)

if isinstance(error, errors.CraftCommandError):
stderr = error.stderr
Expand Down
9 changes: 7 additions & 2 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ Changelog
See the `Releases page`_ on GitHub for a complete list of commits that are
included in each version.

2.6.0 (2024-02-07)
------------------
2.7.0 (2024-Sep-05)
-------------------
- Add a new ``CraftCommandError`` class for errors that wrap command output
- Fix the reporting of error messages containing multiple lines

2.6.0 (2024-Jul-02)
-------------------
- Disable exception chaining for help/usage exceptions
- Support a doc slug in CraftError in addition to full urls

Expand Down
3 changes: 3 additions & 0 deletions docs/tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ Ask help for specifically for the command::

It will return successfully if the file was properly removed.

Positional arguments:
filepath: The file to be removed

Options:
-h, --help: Show this help message and exit
-v, --verbose: Show debug information and be more verbose
Expand Down
9 changes: 9 additions & 0 deletions examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,15 @@ def example_30():
time.sleep(0.001)


def example_31():
"""Multiline error message."""
emit.progress("Setting up computer for build...")
time.sleep(1)
emit.progress("A long progress message")
time.sleep(6)
raise CraftError("Error 1\nError 2")


# -- end of test cases

if len(sys.argv) < 2:
Expand Down
17 changes: 17 additions & 0 deletions tests/integration/test_messages_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,23 @@ def test_error_unexpected_debugish(capsys, mode):
assert_outputs(capsys, emit, expected_err=expected, expected_log=expected)


@pytest.mark.parametrize("output_is_terminal", [True])
def test_error_multiline_brief(capsys):
emit = Emitter()
emit.init(EmitterMode.BRIEF, "testapp", GREETING)
emit.progress("A very long message detailing the current task.")
error = CraftError("Error line 1.\nError line 2.", logpath_report=False)
emit.error(error)

expected = [
Line("A very long message detailing the current task.", permanent=False),
# The error message is split on two separate lines.
Line("Error line 1.", permanent=True),
Line("Error line 2.", permanent=True),
]
assert_outputs(capsys, emit, expected_err=expected, expected_log=expected)


@pytest.mark.parametrize(
"mode",
[
Expand Down
10 changes: 10 additions & 0 deletions tests/unit/test_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,10 @@ def test_command_help_text_with_parameters(output_format):
Summary:
Quite some long text.
Positional arguments:
name: The name of the charm.
extraparam: Another parameter..
Options:
-h, --help: Show this help message and exit.
--revision: The revision to release (defaults to latest).
Expand All @@ -439,6 +443,12 @@ def test_command_help_text_with_parameters(output_format):
Quite some long text.
## Positional arguments:
| | |
|-|-|
| `name` | The name of the charm. |
| `extraparam` | Another parameter.. |
## Options:
| | |
|-|-|
Expand Down

0 comments on commit 1b98f96

Please sign in to comment.