1
0
mirror of https://github.com/httpie/cli.git synced 2025-08-10 22:42:05 +02:00

Add --format-options to allow disabling sorting, etc.

#128
This commit is contained in:
Jakub Roztocil
2020-05-27 15:58:15 +02:00
parent 493e98c833
commit c2a0cef76e
11 changed files with 231 additions and 27 deletions

View File

@@ -2,9 +2,10 @@ import argparse
import getpass
import os
import sys
from typing import Union, List, Optional
from copy import deepcopy
from typing import List, Optional, Union
from httpie.cli.constants import SEPARATOR_CREDENTIALS
from httpie.cli.constants import DEFAULT_FORMAT_OPTIONS, SEPARATOR_CREDENTIALS
from httpie.sessions import VALID_SESSION_NAME_PATTERN
@@ -181,3 +182,65 @@ def readable_file_arg(filename):
return filename
except IOError as ex:
raise argparse.ArgumentTypeError(f'{filename}: {ex.args[1]}')
def parse_format_options(s: str, defaults: Optional[dict]) -> dict:
"""
Parse `s` and update `defaults` with the parsed values.
>>> parse_format_options(
... defaults={'json': {'indent': 4, 'sort_keys': True}},
... s='json.indent=2,json.sort_keys=False',
... )
{'json': {'indent': 2, 'sort_keys': False}}
"""
value_map = {
'true': True,
'false': False,
}
options = deepcopy(defaults or {})
for option in s.split(','):
try:
path, value = option.lower().split('=')
section, key = path.split('.')
except ValueError:
raise argparse.ArgumentTypeError(
f'--format-options: invalid option: {option!r}')
if value in value_map:
parsed_value = value_map[value]
else:
if value.isnumeric():
parsed_value = int(value)
else:
parsed_value = value
if defaults is None:
options.setdefault(section, {})
else:
try:
default_value = defaults[section][key]
except KeyError:
raise argparse.ArgumentTypeError(
f'--format-options: invalid key: {path!r} in {option!r}')
default_type, parsed_type = type(default_value), type(parsed_value)
if parsed_type is not default_type:
raise argparse.ArgumentTypeError(
'--format-options: invalid value type:'
f' {value!r} in {option!r}'
f' (expected {default_type.__name__}'
f' got {parsed_type.__name__})'
)
options[section][key] = parsed_value
return options
PARSED_DEFAULT_FORMAT_OPTIONS = parse_format_options(
s=','.join(DEFAULT_FORMAT_OPTIONS),
defaults=None,
)

View File

@@ -83,6 +83,15 @@ PRETTY_MAP = {
}
PRETTY_STDOUT_TTY_ONLY = object()
DEFAULT_FORMAT_OPTIONS = [
'headers.sort=true',
'json.format=true',
'json.indent=4',
'json.sort_keys=true',
]
# Defaults
OUTPUT_OPTIONS_DEFAULT = OUT_RESP_HEAD + OUT_RESP_BODY
OUTPUT_OPTIONS_DEFAULT_STDOUT_REDIRECTED = OUT_RESP_BODY

View File

@@ -8,20 +8,23 @@ from textwrap import dedent, wrap
from httpie import __doc__, __version__
from httpie.cli.argparser import HTTPieArgumentParser
from httpie.cli.argtypes import (
KeyValueArgType, SessionNameValidator, readable_file_arg,
KeyValueArgType, PARSED_DEFAULT_FORMAT_OPTIONS, SessionNameValidator,
parse_format_options,
readable_file_arg,
)
from httpie.cli.constants import (
OUTPUT_OPTIONS, OUTPUT_OPTIONS_DEFAULT, OUT_REQ_BODY, OUT_REQ_HEAD,
DEFAULT_FORMAT_OPTIONS, OUTPUT_OPTIONS,
OUTPUT_OPTIONS_DEFAULT, OUT_REQ_BODY, OUT_REQ_HEAD,
OUT_RESP_BODY, OUT_RESP_HEAD, PRETTY_MAP, PRETTY_STDOUT_TTY_ONLY,
SEPARATOR_GROUP_ALL_ITEMS, SEPARATOR_PROXY,
)
from httpie.output.formatters.colors import (
AUTO_STYLE, AVAILABLE_STYLES, DEFAULT_STYLE,
)
from httpie.plugins.registry import plugin_manager
from httpie.plugins.builtin import BuiltinAuthPlugin
from httpie.plugins.registry import plugin_manager
from httpie.sessions import DEFAULT_SESSIONS_DIR
from httpie.ssl import DEFAULT_SSL_CIPHERS, AVAILABLE_SSL_VERSION_ARG_MAPPING
from httpie.ssl import AVAILABLE_SSL_VERSION_ARG_MAPPING, DEFAULT_SSL_CIPHERS
parser = HTTPieArgumentParser(
@@ -206,9 +209,9 @@ output_processing.add_argument(
default=DEFAULT_STYLE,
choices=AVAILABLE_STYLES,
help="""
Output coloring style (default is "{default}"). One of:
Output coloring style (default is "{default}"). It can be One of:
{available_styles}
{available_styles}
The "{auto_style}" style follows your terminal's ANSI color styles.
@@ -221,11 +224,38 @@ output_processing.add_argument(
available_styles='\n'.join(
'{0}{1}'.format(8 * ' ', line.strip())
for line in wrap(', '.join(sorted(AVAILABLE_STYLES)), 60)
).rstrip(),
).strip(),
auto_style=AUTO_STYLE,
)
)
output_processing.add_argument(
'--format-options',
type=lambda s: parse_format_options(
s=s,
defaults=PARSED_DEFAULT_FORMAT_OPTIONS
),
default=PARSED_DEFAULT_FORMAT_OPTIONS,
help="""
Controls output formatting. Only relevant when formatting is enabled
through (explicit or implied) --pretty=all or --pretty=format.
The following are the default options:
{option_list}
You can specify multiple comma-separated options. For example, this modifies
the settings to disable the sorting of JSON keys and headers:
--format-options json.sort_keys=false,headers.sort=false
This is something you will typically put into your config file.
""".format(
option_list='\n'.join(
(8 * ' ') + option for option in DEFAULT_FORMAT_OPTIONS).strip()
)
)
#######################################################################
# Output options
#######################################################################