httpie-cli/tests/utils/__init__.py

447 lines
12 KiB
Python
Raw Normal View History

2016-03-01 16:22:50 +01:00
"""Utilities for HTTPie test suite."""
import re
import shlex
2014-04-24 14:07:31 +02:00
import sys
import time
import json
import tempfile
import warnings
2022-02-01 10:14:24 +01:00
import pytest
from contextlib import suppress
from io import BytesIO
from pathlib import Path
from typing import Any, Optional, Union, List, Iterable
import httpie.core as core
import httpie.manager.__main__ as manager
2014-04-24 14:07:31 +02:00
2019-09-16 13:26:18 +02:00
from httpie.status import ExitStatus
from httpie.config import Config
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
from httpie.encoding import UTF8
from httpie.context import Environment
2022-02-01 10:14:24 +01:00
from httpie.utils import url_as_host
2014-04-24 14:07:31 +02:00
REMOTE_HTTPBIN_DOMAIN = 'pie.dev'
# pytest-httpbin currently does not support chunked requests:
# <https://github.com/kevin1024/pytest-httpbin/issues/33>
# <https://github.com/kevin1024/pytest-httpbin/issues/28>
HTTPBIN_WITH_CHUNKED_SUPPORT_DOMAIN = 'pie.dev'
HTTPBIN_WITH_CHUNKED_SUPPORT = 'http://' + HTTPBIN_WITH_CHUNKED_SUPPORT_DOMAIN
TESTS_ROOT = Path(__file__).parent.parent
2014-04-24 14:07:31 +02:00
CRLF = '\r\n'
2014-04-24 15:48:01 +02:00
COLOR = '\x1b['
COLOR_RE = re.compile(r'\x1b\[\d+(;\d+)*?m', re.MULTILINE)
HTTP_OK = '200 OK'
# noinspection GrazieInspection
2014-04-24 15:48:01 +02:00
HTTP_OK_COLOR = (
2014-04-24 14:07:31 +02:00
'HTTP\x1b[39m\x1b[38;5;245m/\x1b[39m\x1b'
'[38;5;37m1.1\x1b[39m\x1b[38;5;245m \x1b[39m\x1b[38;5;37m200'
'\x1b[39m\x1b[38;5;245m \x1b[39m\x1b[38;5;136mOK'
)
DUMMY_URL = 'http://this-should.never-resolve' # Note: URL never fetched
2022-02-01 10:14:24 +01:00
DUMMY_HOST = url_as_host(DUMMY_URL)
2014-04-24 14:07:31 +02:00
def strip_colors(colorized_msg: str) -> str:
return COLOR_RE.sub('', colorized_msg)
def mk_config_dir() -> Path:
2016-03-01 16:22:50 +01:00
dirname = tempfile.mkdtemp(prefix='httpie_config_')
return Path(dirname)
2014-04-24 15:48:01 +02:00
2014-04-25 13:10:01 +02:00
def add_auth(url, auth):
proto, rest = url.split('://', 1)
return f'{proto}://{auth}@{rest}'
2014-04-24 14:07:31 +02:00
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
class Encoder:
"""
Encode binary fragments into a text stream. This is used
to embed raw binary data (which can't be decoded) into the
fake standard output we use on MockEnvironment.
Each data fragment is embedded by it's hash:
"Some data hash(XXX) more data."
Which then later converted back to a bytes object:
b"Some data <real data> more data."
"""
TEMPLATE = 'hash({})'
STR_PATTERN = re.compile(r'hash\((.*)\)')
BYTES_PATTERN = re.compile(rb'hash\((.*)\)')
def __init__(self):
self.substitutions = {}
def substitute(self, data: bytes) -> str:
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
idx = hash(data)
self.substitutions[idx] = data
return self.TEMPLATE.format(idx)
def decode(self, data: str) -> Union[str, bytes]:
if self.STR_PATTERN.search(data) is None:
return data
raw_data = data.encode()
return self.BYTES_PATTERN.sub(
lambda match: self.substitutions[int(match.group(1))],
raw_data
)
class FakeBytesIOBuffer(BytesIO):
def __init__(self, original, encoder, *args, **kwargs):
self.original_buffer = original
self.encoder = encoder
super().__init__(*args, **kwargs)
def write(self, data):
try:
self.original_buffer.write(data.decode(UTF8))
except UnicodeDecodeError:
self.original_buffer.write(self.encoder.substitute(data))
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
finally:
self.original_buffer.flush()
class StdinBytesIO(BytesIO):
"""To be used for `MockEnvironment.stdin`"""
len = 0 # See `prepare_request_body()`
class MockEnvironment(Environment):
2016-03-01 16:22:50 +01:00
"""Environment subclass with reasonable defaults for testing."""
colors = 0 # For easier debugging
stdin_isatty = True
2014-04-24 14:07:31 +02:00
stdout_isatty = True
is_windows = False
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
show_displays = False
2014-04-24 15:48:01 +02:00
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
def __init__(self, create_temp_config_dir=True, **kwargs):
self._encoder = Encoder()
2014-04-24 14:07:31 +02:00
if 'stdout' not in kwargs:
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
kwargs['stdout'] = tempfile.NamedTemporaryFile(
mode='w+t',
prefix='httpie_stderr',
newline='',
encoding=UTF8,
2016-03-01 16:11:06 +01:00
)
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
kwargs['stdout'].buffer = FakeBytesIOBuffer(kwargs['stdout'], self._encoder)
2014-04-24 14:07:31 +02:00
if 'stderr' not in kwargs:
2016-03-01 16:11:06 +01:00
kwargs['stderr'] = tempfile.TemporaryFile(
mode='w+t',
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
prefix='httpie_stderr',
encoding=UTF8,
2016-03-01 16:11:06 +01:00
)
super().__init__(**kwargs)
self._create_temp_config_dir = create_temp_config_dir
2016-03-01 16:11:06 +01:00
self._delete_config_dir = False
self._temp_dir = Path(tempfile.gettempdir())
2016-03-01 16:11:06 +01:00
@property
def config(self) -> Config:
if (self._create_temp_config_dir
and self._temp_dir not in self.config_dir.parents):
self.create_temp_config_dir()
return super().config
2016-03-01 16:11:06 +01:00
def create_temp_config_dir(self):
self.config_dir = mk_config_dir()
self._delete_config_dir = True
2016-03-01 16:11:06 +01:00
def cleanup(self):
self.stdout.close()
self.stderr.close()
warnings.resetwarnings()
2016-03-01 16:11:06 +01:00
if self._delete_config_dir:
assert self._temp_dir in self.config_dir.parents
2016-03-01 16:11:06 +01:00
from shutil import rmtree
rmtree(self.config_dir, ignore_errors=True)
2014-04-24 14:07:31 +02:00
def __del__(self):
# noinspection PyBroadException
2016-03-01 16:11:06 +01:00
try:
self.cleanup()
except Exception:
pass
2014-04-24 14:07:31 +02:00
class BaseCLIResponse:
2016-03-01 16:22:50 +01:00
"""
Represents the result of simulated `$ http' invocation via `http()`.
2016-03-01 16:22:50 +01:00
Holds and provides access to:
- stdout output: print(self)
- stderr output: print(self.stderr)
2020-07-15 00:21:57 +02:00
- devnull output: print(self.devnull)
2016-03-01 16:22:50 +01:00
- exit_status output: print(self.exit_status)
"""
stderr: str = None
2020-07-15 00:21:57 +02:00
devnull: str = None
json: dict = None
exit_status: ExitStatus = None
command: str = None
args: List[str] = []
complete_args: List[str] = []
@property
def command(self):
cmd = ' '.join(shlex.quote(arg) for arg in ['http', *self.args])
# pytest-httpbin to real httpbin.
return re.sub(r'127\.0\.0\.1:\d+', 'httpbin.org', cmd)
2016-03-01 16:22:50 +01:00
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
@classmethod
def from_raw_data(self, data: Union[str, bytes]) -> 'BaseCLIResponse':
if isinstance(data, bytes):
with suppress(UnicodeDecodeError):
data = data.decode()
if isinstance(data, bytes):
return BytesCLIResponse(data)
else:
return StrCLIResponse(data)
2016-03-01 16:22:50 +01:00
class BytesCLIResponse(bytes, BaseCLIResponse):
"""
Used as a fallback when a StrCLIResponse cannot be used.
E.g. when the output contains binary data or when it is colorized.
`.json` will always be None.
"""
class StrCLIResponse(str, BaseCLIResponse):
@property
def json(self) -> Optional[dict]:
2016-03-01 16:22:50 +01:00
"""
Return deserialized the request or response JSON body,
if one (and only one) included in the output and is parsable.
2016-03-01 16:22:50 +01:00
"""
if not hasattr(self, '_json'):
self._json = None
# De-serialize JSON body if possible.
if COLOR in self:
# Colorized output cannot be parsed.
pass
elif self.strip().startswith('{'):
# Looks like JSON body.
self._json = json.loads(self)
elif self.count('Content-Type:') == 1:
# Looks like a HTTP message,
# try to extract JSON from its body.
2016-03-01 16:22:50 +01:00
try:
j = self.strip()[self.strip().rindex('\r\n\r\n'):]
except ValueError:
pass
else:
try:
# noinspection PyAttributeOutsideInit
2016-03-01 16:22:50 +01:00
self._json = json.loads(j)
except ValueError:
pass
return self._json
2016-03-02 06:31:23 +01:00
class ExitStatusError(Exception):
2016-03-02 06:16:41 +01:00
pass
2022-02-01 10:14:24 +01:00
@pytest.fixture
def mock_env() -> MockEnvironment:
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
env = MockEnvironment()
2022-02-01 10:14:24 +01:00
yield env
env.cleanup()
def normalize_args(args: Iterable[Any]) -> List[str]:
return [str(arg) for arg in args]
def httpie(
*args,
**kwargs
) -> StrCLIResponse:
"""
Run HTTPie manager command with the given
args/kwargs, and capture stderr/out and exit
status.
"""
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
env = kwargs.setdefault('env', MockEnvironment())
cli_args = ['httpie']
if not kwargs.pop('no_debug', False):
cli_args.append('--debug')
cli_args += normalize_args(args)
exit_status = manager.main(
args=cli_args,
**kwargs
)
env.stdout.seek(0)
env.stderr.seek(0)
try:
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
response = BaseCLIResponse.from_raw_data(env.stdout.read())
response.stderr = env.stderr.read()
response.exit_status = exit_status
response.args = cli_args
finally:
env.stdout.truncate(0)
env.stderr.truncate(0)
env.stdout.seek(0)
env.stderr.seek(0)
return response
def http(
*args,
program_name='http',
tolerate_error_exit_status=False,
**kwargs,
) -> Union[StrCLIResponse, BytesCLIResponse]:
2016-03-01 16:11:06 +01:00
# noinspection PyUnresolvedReferences
2014-04-24 14:07:31 +02:00
"""
2016-03-01 16:13:45 +01:00
Run HTTPie and capture stderr/out and exit status.
Content written to devnull will be captured only if
2020-07-15 00:21:57 +02:00
env.devnull is set manually.
2014-04-25 12:18:35 +02:00
2016-03-01 16:13:45 +01:00
Invoke `httpie.core.main()` with `args` and `kwargs`,
and return a `CLIResponse` subclass instance.
2016-03-01 16:13:45 +01:00
The return value is either a `StrCLIResponse`, or `BytesCLIResponse`
2020-07-15 00:21:57 +02:00
if unable to decode the output. Devnull is string when possible,
bytes otherwise.
2014-04-24 14:07:31 +02:00
2016-03-01 16:13:45 +01:00
The response has the following attributes:
2014-04-24 14:07:31 +02:00
2016-03-01 16:13:45 +01:00
`stdout` is represented by the instance itself (print r)
`stderr`: text written to stderr
2020-07-15 00:21:57 +02:00
`devnull` text written to devnull.
2016-03-01 16:13:45 +01:00
`exit_status`: the exit status
`json`: decoded JSON (if possible) or `None`
2014-04-24 14:07:31 +02:00
2016-03-01 16:13:45 +01:00
Exceptions are propagated.
If you pass ``tolerate_error_exit_status=True``, then error exit statuses
2016-03-01 16:13:45 +01:00
won't result into an exception.
2016-03-01 16:13:45 +01:00
Example:
2014-04-24 14:07:31 +02:00
2020-12-24 21:34:30 +01:00
$ http --auth=user:password GET pie.dev/basic-auth/user/password
2016-03-01 16:13:45 +01:00
>>> httpbin = getfixture('httpbin')
>>> r = http('-a', 'user:pw', httpbin.url + '/basic-auth/user/pw')
>>> type(r) == StrCLIResponse
True
>>> r.exit_status is ExitStatus.SUCCESS
True
2016-03-01 16:13:45 +01:00
>>> r.stderr
''
>>> 'HTTP/1.1 200 OK' in r
True
>>> r.json == {'authenticated': True, 'user': 'user'}
True
2016-03-01 16:13:45 +01:00
"""
2014-04-24 14:07:31 +02:00
env = kwargs.get('env')
if not env:
env = kwargs['env'] = MockEnvironment()
2014-04-24 14:07:31 +02:00
stdout = env.stdout
stderr = env.stderr
devnull = env.devnull
2014-04-24 14:07:31 +02:00
2014-04-25 12:42:50 +02:00
args = list(args)
args_with_config_defaults = args + env.config.default_options
add_to_args = []
if '--debug' not in args_with_config_defaults:
if (not tolerate_error_exit_status
and '--traceback' not in args_with_config_defaults):
add_to_args.append('--traceback')
if not any('--timeout' in arg for arg in args_with_config_defaults):
add_to_args.append('--timeout=3')
complete_args = [program_name, *add_to_args, *args]
# print(' '.join(complete_args))
2014-04-25 12:42:50 +02:00
def dump_stderr():
stderr.seek(0)
sys.stderr.write(stderr.read())
2014-04-24 18:32:15 +02:00
try:
2014-04-24 14:07:31 +02:00
try:
exit_status = core.main(args=complete_args, **kwargs)
2014-04-24 14:07:31 +02:00
if '--download' in args:
# Let the progress reporter thread finish.
time.sleep(.5)
except SystemExit:
if tolerate_error_exit_status:
2016-03-02 06:16:41 +01:00
exit_status = ExitStatus.ERROR
else:
dump_stderr()
raise
2014-04-24 14:07:31 +02:00
except Exception:
stderr.seek(0)
2014-04-24 14:07:31 +02:00
sys.stderr.write(stderr.read())
raise
else:
if (not tolerate_error_exit_status
and exit_status != ExitStatus.SUCCESS):
dump_stderr()
2016-03-02 06:31:23 +01:00
raise ExitStatusError(
2016-03-02 06:16:41 +01:00
'httpie.core.main() unexpectedly returned'
f' a non-zero exit status: {exit_status}'
2016-03-02 06:16:41 +01:00
)
2014-04-24 14:07:31 +02:00
stdout.seek(0)
stderr.seek(0)
devnull.seek(0)
2014-04-24 14:07:31 +02:00
output = stdout.read()
devnull_output = devnull.read()
[Major] UI Enhancements (#1321) * Refactor tests to use a text-based standard output. (#1318) * Implement new style `--help` (#1316) * Implement man page generation (#1317) * Implement rich progress bars. (#1324) * Man page deployment & isolation. (#1325) * Remove all unsorted usages in the CLI docs * Implement isolated mode for man page generation * Add a CI job for autogenerated files * Distribute man pages through PyPI * Pin the date for man pages. (#1326) * Hide suppressed arguments from --help/man pages (#1329) * Change download spinner to line (#1328) * Regenerate autogenerated files when pushed against to master. (#1339) * Highlight options (#1340) * Additional man page enhancements (#1341) * Group options by the parent category & highlight -o/--o * Display (and underline) the METAVAR on man pages. * Make help message processing more robust (#1342) * Inherit `help` from `short_help` * Don't mirror short_help directly. * Fixup the serialization * Use `pager` and `man` on `--manual` when applicable (#1343) * Run `man $program` on --manual * Page the output of `--manual` for systems that lack man pages * Improvements over progress bars (separate bar, status line, etc.) (#1346) * Redesign the --help layout. * Make our usage of rich compatible with 9.10.0 * Add `HTTPIE_NO_MAN_PAGES` * Make tests also patch os.get_terminal_size * Generate CLI spec from HTTPie & Man Page Hook (#1354) * Generate CLI spec from HTTPie & add man page hook * Use the full command space for the option headers
2022-04-14 16:43:10 +02:00
if hasattr(env, '_encoder'):
output = env._encoder.decode(output)
r = BaseCLIResponse.from_raw_data(output)
2020-07-15 00:21:57 +02:00
try:
devnull_output = devnull_output.decode()
2020-07-15 00:21:57 +02:00
except Exception:
pass
r.devnull = devnull_output
2014-04-24 14:07:31 +02:00
r.stderr = stderr.read()
r.exit_status = exit_status
r.args = args
r.complete_args = ' '.join(complete_args)
2014-04-24 14:07:31 +02:00
if r.exit_status != ExitStatus.SUCCESS:
sys.stderr.write(r.stderr)
# print(f'\n\n$ {r.command}\n')
2014-04-24 14:07:31 +02:00
return r
finally:
devnull.close()
2014-04-24 14:07:31 +02:00
stdout.close()
stderr.close()
2016-03-01 16:11:06 +01:00
env.cleanup()