mirror of
https://github.com/httpie/cli.git
synced 2024-11-25 01:03:27 +01:00
Make the naked invocation display a compacted help
This commit is contained in:
parent
9241a09360
commit
350abe3033
@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|||||||
- Fixed displaying of status code without a status message on non-`auto` themes. ([#1300](https://github.com/httpie/httpie/issues/1300))
|
- Fixed displaying of status code without a status message on non-`auto` themes. ([#1300](https://github.com/httpie/httpie/issues/1300))
|
||||||
- Fixed redundant issuance of stdin detection warnings on some rare cases due to underlying implementation. ([#1303](https://github.com/httpie/httpie/pull/1303))
|
- Fixed redundant issuance of stdin detection warnings on some rare cases due to underlying implementation. ([#1303](https://github.com/httpie/httpie/pull/1303))
|
||||||
- Improved regulation of top-level arrays. ([#1292](https://github.com/httpie/httpie/commit/225dccb2186f14f871695b6c4e0bfbcdb2e3aa28))
|
- Improved regulation of top-level arrays. ([#1292](https://github.com/httpie/httpie/commit/225dccb2186f14f871695b6c4e0bfbcdb2e3aa28))
|
||||||
|
- Improved UI layout for standalone invocations. ([#1296](https://github.com/httpie/httpie/pull/1296))
|
||||||
- Double `--quiet` flags will now suppress all python level warnings. ([#1271](https://github.com/httpie/httpie/issues/1271))
|
- Double `--quiet` flags will now suppress all python level warnings. ([#1271](https://github.com/httpie/httpie/issues/1271))
|
||||||
|
|
||||||
## [3.0.2](https://github.com/httpie/httpie/compare/3.0.1...3.0.2) (2022-01-24)
|
## [3.0.2](https://github.com/httpie/httpie/compare/3.0.1...3.0.2) (2022-01-24)
|
||||||
|
@ -48,12 +48,39 @@ class HTTPieHelpFormatter(RawDescriptionHelpFormatter):
|
|||||||
text = dedent(text).strip() + '\n\n'
|
text = dedent(text).strip() + '\n\n'
|
||||||
return text.splitlines()
|
return text.splitlines()
|
||||||
|
|
||||||
|
def add_usage(self, usage, actions, groups, prefix=None):
|
||||||
|
# Only display the positional arguments
|
||||||
|
displayed_actions = [
|
||||||
|
action
|
||||||
|
for action in actions
|
||||||
|
if not action.option_strings
|
||||||
|
]
|
||||||
|
|
||||||
|
_, exception, _ = sys.exc_info()
|
||||||
|
if (
|
||||||
|
isinstance(exception, argparse.ArgumentError)
|
||||||
|
and len(exception.args) >= 1
|
||||||
|
and isinstance(exception.args[0], argparse.Action)
|
||||||
|
):
|
||||||
|
# add_usage path is also taken when you pass an invalid option,
|
||||||
|
# e.g --style=invalid. If something like that happens, we want
|
||||||
|
# to include to action that caused to the invalid usage into
|
||||||
|
# the list of actions we are displaying.
|
||||||
|
displayed_actions.insert(0, exception.args[0])
|
||||||
|
|
||||||
|
super().add_usage(
|
||||||
|
usage,
|
||||||
|
displayed_actions,
|
||||||
|
groups,
|
||||||
|
prefix="usage:\n "
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# TODO: refactor and design type-annotated data structures
|
# TODO: refactor and design type-annotated data structures
|
||||||
# for raw args + parsed args and keep things immutable.
|
# for raw args + parsed args and keep things immutable.
|
||||||
class BaseHTTPieArgumentParser(argparse.ArgumentParser):
|
class BaseHTTPieArgumentParser(argparse.ArgumentParser):
|
||||||
def __init__(self, *args, formatter_class=HTTPieHelpFormatter, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, formatter_class=formatter_class, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.env = None
|
self.env = None
|
||||||
self.args = None
|
self.args = None
|
||||||
self.has_stdin_data = False
|
self.has_stdin_data = False
|
||||||
@ -116,9 +143,9 @@ class HTTPieArgumentParser(BaseHTTPieArgumentParser):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, formatter_class=HTTPieHelpFormatter, **kwargs):
|
||||||
kwargs.setdefault('add_help', False)
|
kwargs.setdefault('add_help', False)
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, formatter_class=formatter_class, **kwargs)
|
||||||
|
|
||||||
# noinspection PyMethodOverriding
|
# noinspection PyMethodOverriding
|
||||||
def parse_args(
|
def parse_args(
|
||||||
@ -529,3 +556,21 @@ class HTTPieArgumentParser(BaseHTTPieArgumentParser):
|
|||||||
for options_group in format_options:
|
for options_group in format_options:
|
||||||
parsed_options = parse_format_options(options_group, defaults=parsed_options)
|
parsed_options = parse_format_options(options_group, defaults=parsed_options)
|
||||||
self.args.format_options = parsed_options
|
self.args.format_options = parsed_options
|
||||||
|
|
||||||
|
def error(self, message):
|
||||||
|
"""Prints a usage message incorporating the message to stderr and
|
||||||
|
exits."""
|
||||||
|
self.print_usage(sys.stderr)
|
||||||
|
self.exit(
|
||||||
|
2,
|
||||||
|
dedent(
|
||||||
|
f'''
|
||||||
|
error:
|
||||||
|
{message}
|
||||||
|
|
||||||
|
For more information:
|
||||||
|
- Try running {self.prog} --help
|
||||||
|
- Or visiting https://httpie.io/docs/cli
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
)
|
||||||
|
84
tests/test_cli_ui.py
Normal file
84
tests/test_cli_ui.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import pytest
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from tests.utils import http
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 9):
|
||||||
|
REQUEST_ITEM_MSG = "[REQUEST_ITEM ...]"
|
||||||
|
else:
|
||||||
|
REQUEST_ITEM_MSG = "[REQUEST_ITEM [REQUEST_ITEM ...]]"
|
||||||
|
|
||||||
|
|
||||||
|
NAKED_HELP_MESSAGE = f"""\
|
||||||
|
usage:
|
||||||
|
http [METHOD] URL {REQUEST_ITEM_MSG}
|
||||||
|
|
||||||
|
error:
|
||||||
|
the following arguments are required: URL
|
||||||
|
|
||||||
|
For more information:
|
||||||
|
- Try running http --help
|
||||||
|
- Or visiting https://httpie.io/docs/cli
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
NAKED_HELP_MESSAGE_PRETTY_WITH_NO_ARG = f"""\
|
||||||
|
usage:
|
||||||
|
http [--pretty {{all,colors,format,none}}] [METHOD] URL {REQUEST_ITEM_MSG}
|
||||||
|
|
||||||
|
error:
|
||||||
|
argument --pretty: expected one argument
|
||||||
|
|
||||||
|
For more information:
|
||||||
|
- Try running http --help
|
||||||
|
- Or visiting https://httpie.io/docs/cli
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
NAKED_HELP_MESSAGE_PRETTY_WITH_INVALID_ARG = f"""\
|
||||||
|
usage:
|
||||||
|
http [--pretty {{all,colors,format,none}}] [METHOD] URL {REQUEST_ITEM_MSG}
|
||||||
|
|
||||||
|
error:
|
||||||
|
argument --pretty: invalid choice: '$invalid' (choose from 'all', 'colors', 'format', 'none')
|
||||||
|
|
||||||
|
For more information:
|
||||||
|
- Try running http --help
|
||||||
|
- Or visiting https://httpie.io/docs/cli
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
PREDEFINED_TERMINAL_SIZE = (160, 80)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function")
|
||||||
|
def ignore_terminal_size(monkeypatch):
|
||||||
|
"""Some tests wrap/crop the output depending on the
|
||||||
|
size of the executed terminal, which might not be consistent
|
||||||
|
through all runs.
|
||||||
|
|
||||||
|
This fixture ensures every run uses the same exact configuration.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def fake_terminal_size(*args, **kwargs):
|
||||||
|
return os.terminal_size(PREDEFINED_TERMINAL_SIZE)
|
||||||
|
|
||||||
|
# Setting COLUMNS as an env var is required for 3.8<
|
||||||
|
monkeypatch.setitem(os.environ, 'COLUMNS', str(PREDEFINED_TERMINAL_SIZE[0]))
|
||||||
|
monkeypatch.setattr(shutil, 'get_terminal_size', fake_terminal_size)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'args, expected_msg', [
|
||||||
|
([], NAKED_HELP_MESSAGE),
|
||||||
|
(['--pretty'], NAKED_HELP_MESSAGE_PRETTY_WITH_NO_ARG),
|
||||||
|
(['pie.dev', '--pretty'], NAKED_HELP_MESSAGE_PRETTY_WITH_NO_ARG),
|
||||||
|
(['--pretty', '$invalid'], NAKED_HELP_MESSAGE_PRETTY_WITH_INVALID_ARG),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_naked_invocation(ignore_terminal_size, args, expected_msg):
|
||||||
|
result = http(*args, tolerate_error_exit_status=True)
|
||||||
|
assert result.stderr == expected_msg
|
Loading…
Reference in New Issue
Block a user