1
0
mirror of https://github.com/httpie/cli.git synced 2024-11-30 08:46:48 +02:00

Finish --quiet

This commit is contained in:
Jakub Roztocil 2020-08-15 15:25:05 +02:00
parent 2c7f24e3e5
commit 1aa1366f99
6 changed files with 112 additions and 130 deletions

2
.github/FUNDING.yml vendored
View File

@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
liberapay: # Replace with a single Liberapay username liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username otechie: # Replace with a single Otechie username
custom: https://paypal.me/roztocil custom:

View File

@ -10,8 +10,8 @@ This project adheres to `Semantic Versioning <https://semver.org/>`_.
------------------------- -------------------------
* Added support for combining cookies specified on the CLI and in a session file (`#932`_). * Added support for combining cookies specified on the CLI and in a session file (`#932`_).
* Added out of the box SOCKS support with no extra installation (`#904`_). * Added out of the box SOCKS support with no extra installation (`#904`_).
* Added ``--quiet, -q`` flag to enforce silent behaviour.
* Removed Tox testing entirely (`#943`_). * Removed Tox testing entirely (`#943`_).
* Added a ``--quiet`` flag to enforce silent behaviour.
`2.2.0`_ (2020-06-18) `2.2.0`_ (2020-06-18)

View File

@ -1156,12 +1156,34 @@ be printed via several options:
``--verbose, -v`` Print the whole HTTP exchange (request and response). ``--verbose, -v`` Print the whole HTTP exchange (request and response).
This option also enables ``--all`` (see below). This option also enables ``--all`` (see below).
``--print, -p`` Selects parts of the HTTP exchange. ``--print, -p`` Selects parts of the HTTP exchange.
``--quiet, -q`` Doesn't print anything. Overrides other output flags. ``--quiet, -q`` Don't print anything to ``stdout`` and ``stderr``.
================= ===================================================== ================= =====================================================
If ``--quiet`` is used in conjuction with ``--output`` the flag is ignored
and ``stdout`` is still redirected. If ``--quiet`` is used with ``--download``
file is still downloaded as usual but ``stdout`` and ``stdin`` are redirected What parts of the HTTP exchange should be printed
to ``devnull``. -------------------------------------------------
All the other `output options`_ are under the hood just shortcuts for
the more powerful ``--print, -p``. It accepts a string of characters each
of which represents a specific part of the HTTP exchange:
========== ==================
Character Stands for
========== ==================
``H`` request headers
``B`` request body
``h`` response headers
``b`` response body
========== ==================
Print request and response headers:
.. code-block:: bash
$ http --print=Hh PUT httpbin.org/put hello=world
Verbose output
--------------
``--verbose`` can often be useful for debugging the request and generating ``--verbose`` can often be useful for debugging the request and generating
documentation examples: documentation examples:
@ -1192,28 +1214,12 @@ documentation examples:
[…] […]
} }
Quiet output
------------
What parts of the HTTP exchange should be printed ``--quiet`` redirects all output that would otherwise go to ``stdout``
------------------------------------------------- and ``stderr`` (except for error messages) to ``/dev/null``.
This doesn’t affect output to a file via ``--output`` or ``--download``.
All the other `output options`_ are under the hood just shortcuts for
the more powerful ``--print, -p``. It accepts a string of characters each
of which represents a specific part of the HTTP exchange:
========== ==================
Character Stands for
========== ==================
``H`` request headers
``B`` request body
``h`` response headers
``b`` response body
========== ==================
Print request and response headers:
.. code-block:: bash
$ http --print=Hh PUT httpbin.org/put hello=world
Viewing intermediary requests/responses Viewing intermediary requests/responses

View File

@ -35,7 +35,6 @@ class Environment:
stdout_encoding: str = None stdout_encoding: str = None
stderr: IO = sys.stderr stderr: IO = sys.stderr
stderr_isatty: bool = stderr.isatty() stderr_isatty: bool = stderr.isatty()
_devnull = None
colors = 256 colors = 256
program_name: str = 'http' program_name: str = 'http'
if not is_windows: if not is_windows:
@ -58,7 +57,7 @@ class Environment:
) )
del colorama del colorama
def __init__(self, **kwargs): def __init__(self, devnull=None, **kwargs):
""" """
Use keyword arguments to overwrite Use keyword arguments to overwrite
any of the class attributes for this instance. any of the class attributes for this instance.
@ -67,6 +66,10 @@ class Environment:
assert all(hasattr(type(self), attr) for attr in kwargs.keys()) assert all(hasattr(type(self), attr) for attr in kwargs.keys())
self.__dict__.update(**kwargs) self.__dict__.update(**kwargs)
# The original STDERR unaffected by --quiet’ing.
self._orig_stderr = self.stderr
self._devnull = devnull
# Keyword arguments > stream.encoding > default utf8 # Keyword arguments > stream.encoding > default utf8
if self.stdin and self.stdin_encoding is None: if self.stdin and self.stdin_encoding is None:
self.stdin_encoding = getattr( self.stdin_encoding = getattr(
@ -122,4 +125,4 @@ class Environment:
def log_error(self, msg, level='error'): def log_error(self, msg, level='error'):
assert level in ['error', 'warning'] assert level in ['error', 'warning']
self.stderr.write(f'\n{self.program_name}: {level}: {msg}\n\n') self._orig_stderr.write(f'\n{self.program_name}: {level}: {msg}\n\n')

View File

@ -183,52 +183,11 @@ class TestDownloads:
# Redirect from `/redirect/1` to `/get`. # Redirect from `/redirect/1` to `/get`.
expected_filename = '1.json' expected_filename = '1.json'
orig_cwd = os.getcwd() orig_cwd = os.getcwd()
os.chdir(tempfile.mkdtemp(prefix='httpie_download_test_')) with tempfile.TemporaryDirectory() as tmp_dirname:
try: os.chdir(tmp_dirname)
assert os.listdir('.') == [] try:
http('--download', httpbin.url + '/redirect/1') assert os.listdir('.') == []
assert os.listdir('.') == [expected_filename] http('--download', httpbin.url + '/redirect/1')
finally: assert os.listdir('.') == [expected_filename]
os.chdir(orig_cwd) finally:
os.chdir(orig_cwd)
def test_download_with_quiet_flag(self, httpbin):
robots_txt = '/robots.txt'
expected_body = requests.get(httpbin + robots_txt).text
expected_filename = 'robots.txt'
env = MockEnvironment(stdin_isatty=True, stdout_isatty=True)
orig_cwd = os.getcwd()
os.chdir(tempfile.mkdtemp(prefix='httpie_download_quiet_test_'))
try:
assert os.listdir('.') == []
r = http('--quiet', '--download', httpbin + robots_txt, env=env)
assert os.listdir('.') == [expected_filename]
assert r.stderr == ''
assert env.devnull == env.stderr
assert env.devnull == env.stdout
with open(expected_filename, 'r') as f:
assert f.read() == expected_body
finally:
os.chdir(orig_cwd)
def test_download_with_quiet_and_output_flag(self, httpbin):
robots_txt = '/robots.txt'
expected_body = requests.get(httpbin + robots_txt).text
expected_filename = 'test.txt'
env = MockEnvironment(stdin_isatty=True, stdout_isatty=True)
orig_cwd = os.getcwd()
os.chdir(tempfile.mkdtemp(prefix='httpie_download_quiet_test_'))
try:
assert os.listdir('.') == []
r = http('--quiet',
'--download',
'--output=' + expected_filename,
httpbin + robots_txt,
env=env)
assert os.listdir('.') == [expected_filename]
assert r.stderr == ''
assert env.devnull == env.stderr
assert env.devnull == env.stdout
with open(expected_filename, 'r') as f:
assert f.read() == expected_body
finally:
os.chdir(orig_cwd)

View File

@ -1,4 +1,6 @@
import argparse import argparse
from pathlib import Path
import mock import mock
import json import json
import os import os
@ -40,69 +42,81 @@ class TestQuietFlag:
@pytest.mark.parametrize('argument_name', ['--quiet', '-q']) @pytest.mark.parametrize('argument_name', ['--quiet', '-q'])
def test_quiet(self, httpbin, argument_name): def test_quiet(self, httpbin, argument_name):
env = MockEnvironment(stdin_isatty=True, stdout_isatty=True) env = MockEnvironment(
stdin_isatty=True,
stdout_isatty=True,
devnull=io.BytesIO()
)
r = http(argument_name, 'GET', httpbin.url + '/get', env=env) r = http(argument_name, 'GET', httpbin.url + '/get', env=env)
assert env.stdout == env.devnull assert env.stdout is env.devnull
assert env.stderr == env.devnull assert env.stderr is env.devnull
assert r.stderr == ''
assert str(r) == ''
@pytest.mark.parametrize('argument_name', ['--quiet', '-q'])
def test_quiet_correct_message(self, httpbin, argument_name):
sim_devnull = io.BytesIO()
env = MockEnvironment(stdin_isatty=True, stdout_isatty=True)
env.devnull = sim_devnull
r = http(argument_name, 'GET', httpbin.url + '/get', env=env)
assert env.stdout == env.devnull
assert env.stderr == env.devnull
assert r.stderr == ''
assert HTTP_OK in r.devnull assert HTTP_OK in r.devnull
assert str(r) == '' assert r == ''
assert r.stderr == ''
@mock.patch('httpie.cli.argtypes.AuthCredentials._getpass', @mock.patch('httpie.cli.argtypes.AuthCredentials._getpass',
new=lambda self, prompt: 'password') new=lambda self, prompt: 'password')
def test_quiet_password_prompt(self, httpbin): def test_quiet_with_password_prompt(self, httpbin):
""" Tests whether httpie still prompts for password when request """
requires authetication and only username is provided""" Tests whether httpie still prompts for a password when request
env = MockEnvironment(stdin_isatty=True, stdout_isatty=True) requires authentication and only username is provided
env.devnull = io.BytesIO()
r = http('--quiet', '--auth', 'user', 'GET', httpbin.url + '/basic-auth/user/password', env=env) """
env = MockEnvironment(
stdin_isatty=True,
stdout_isatty=True,
devnull=io.BytesIO()
)
r = http(
'--quiet', '--auth', 'user', 'GET',
httpbin.url + '/basic-auth/user/password',
env=env
)
assert env.stdout is env.devnull
assert env.stderr is env.devnull
assert HTTP_OK in r.devnull assert HTTP_OK in r.devnull
assert env.stdout == env.devnull assert r == ''
assert env.stderr == env.devnull
assert str(r) == ''
assert r.stderr == '' assert r.stderr == ''
@pytest.mark.parametrize('argument_name', ['-h', '-b', '-v', '-p=hH']) @pytest.mark.parametrize('argument_name', ['-h', '-b', '-v', '-p=hH'])
def test_quiet_flag_overrides_other_output_options(self, httpbin, argument_name): def test_quiet_with_explicit_output_options(self, httpbin, argument_name):
env = MockEnvironment(stdin_isatty=True, stdout_isatty=True) env = MockEnvironment(stdin_isatty=True, stdout_isatty=True)
r = http('--quiet', argument_name, httpbin.url + '/GET', env=env) r = http('--quiet', argument_name, httpbin.url + '/get', env=env)
assert env.stdout == env.devnull assert env.stdout is env.devnull
assert env.stderr == env.devnull assert env.stderr is env.devnull
assert str(r) == '' assert r == ''
assert r.stderr == '' assert r.stderr == ''
def test_quiet_flag_with_output_redirection(self, httpbin): @pytest.mark.parametrize('with_download', [True, False])
robots_txt = '/robots.txt' def test_quiet_with_output_redirection(self, httpbin, with_download):
expected_body = requests.get(httpbin + robots_txt).text url = httpbin + '/robots.txt'
expected_filename = 'test.txt' output_path = Path('output.txt')
env = MockEnvironment(stdin_isatty=True, stdout_isatty=True) env = MockEnvironment()
orig_cwd = os.getcwd() orig_cwd = os.getcwd()
os.chdir(tempfile.mkdtemp(prefix='httpie_download_quiet_test_')) output = requests.get(url).text
try: extra_args = ['--download'] if with_download else []
assert os.listdir('.') == [] with tempfile.TemporaryDirectory() as tmp_dirname:
r = http('--quiet', os.chdir(tmp_dirname)
'--output=' + expected_filename, try:
httpbin + robots_txt, assert os.listdir('.') == []
env=env) r = http(
assert os.listdir('.') == [expected_filename] '--quiet',
assert r.stderr == '' '--output', str(output_path),
assert env.devnull == env.stderr *extra_args,
assert env.devnull != env.stdout url,
with open(expected_filename, 'r') as f: env=env
assert f.read() == expected_body )
finally: assert os.listdir('.') == [str(output_path)]
os.chdir(orig_cwd) assert r == ''
assert r.stderr == ''
assert env.stderr is env.devnull
if with_download:
assert env.stdout is env.devnull
else:
assert env.stdout is not env.devnull # --output swaps stdout.
assert output_path.read_text() == output
finally:
os.chdir(orig_cwd)
class TestVerboseFlag: class TestVerboseFlag: