You've already forked httpie-cli
							
							
				mirror of
				https://github.com/httpie/cli.git
				synced 2025-10-30 23:47:52 +02:00 
			
		
		
		
	Make the naked invocation display a compacted help
This commit is contained in:
		| @@ -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 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 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)) | ||||
|  | ||||
| ## [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' | ||||
|         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 | ||||
| #       for raw args + parsed args and keep things immutable. | ||||
| class BaseHTTPieArgumentParser(argparse.ArgumentParser): | ||||
|     def __init__(self, *args, formatter_class=HTTPieHelpFormatter, **kwargs): | ||||
|         super().__init__(*args, formatter_class=formatter_class, **kwargs) | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|         self.env = None | ||||
|         self.args = None | ||||
|         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) | ||||
|         super().__init__(*args, **kwargs) | ||||
|         super().__init__(*args, formatter_class=formatter_class, **kwargs) | ||||
|  | ||||
|     # noinspection PyMethodOverriding | ||||
|     def parse_args( | ||||
| @@ -529,3 +556,21 @@ class HTTPieArgumentParser(BaseHTTPieArgumentParser): | ||||
|         for options_group in format_options: | ||||
|             parsed_options = parse_format_options(options_group, defaults=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 | ||||
		Reference in New Issue
	
	Block a user