Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).

## [2.6.0.dev0](https://github.com/httpie/httpie/compare/2.5.0...master) (unreleased)

- Added the ability to silence warnings through using `-q` or `--quiet` twice (e.g. `-qq`) ([#1175](https://github.com/httpie/httpie/issues/1175))
- Added support for formatting & coloring of JSON bodies preceded by non-JSON data (e.g., an XXSI prefix). ([#1130](https://github.com/httpie/httpie/issues/1130))
- Added `--response-charset` to allow overriding the response encoding for terminal display purposes. ([#1168](https://github.com/httpie/httpie/issues/1168))
- Added `--response-mime` to allow overriding the response mime type for coloring and formatting for the terminal. ([#1168](https://github.com/httpie/httpie/issues/1168))
Expand Down
7 changes: 7 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,13 @@ This doesn’t affect output to a file via `--output` or `--download`.
$ http --quiet pie.dev/post enjoy='the silence'
```

If you’d like to silence warnings as well, use `-q` or `--quiet` twice:

```bash
# There will be no output, even in case of an unexpected response status code:
$ http -qq --check-status pie.dev/post enjoy='the silence without warnings'
```

### Viewing intermediary requests/responses

To see all the HTTP communication, i.e. the final request/response as well as any possible intermediary requests/responses, use the `--all` option.
Expand Down
8 changes: 5 additions & 3 deletions httpie/cli/definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -497,12 +497,14 @@

output_options.add_argument(
'--quiet', '-q',
action='store_true',
default=False,
action='count',
default=0,
help='''
Do not print to stdout or stderr.
Do not print to stdout or stderr, except for errors and warnings when provided once.
Provide twice to suppress warnings as well.
stdout is still redirected if --output is specified.
Flag doesn't affect behaviour of download beyond not printing to terminal.

'''
)

Expand Down
2 changes: 1 addition & 1 deletion httpie/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def request_body_read_callback(chunk: bytes):
final_response = message
if args.check_status or downloader:
exit_status = http_status_to_exit_status(http_status=message.status_code, follow=args.follow)
if exit_status != ExitStatus.SUCCESS and (not env.stdout_isatty or args.quiet):
if exit_status != ExitStatus.SUCCESS and (not env.stdout_isatty or args.quiet == 1):
env.log_error(f'HTTP {message.raw.status} {message.raw.reason}', level='warning')
write_message(requests_message=message, env=env, args=args, with_headers=with_headers,
with_body=do_write_body)
Expand Down
41 changes: 30 additions & 11 deletions tests/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,16 @@ def test_output_option(tmp_path, httpbin, stdout_isatty):


class TestQuietFlag:
QUIET_SCENARIOS = [('--quiet',), ('-q',), ('--quiet', '--quiet'), ('-qq',)]

@pytest.mark.parametrize('argument_name', ['--quiet', '-q'])
def test_quiet(self, httpbin, argument_name):
@pytest.mark.parametrize('quiet_flags', QUIET_SCENARIOS)
def test_quiet(self, httpbin, quiet_flags):
env = MockEnvironment(
stdin_isatty=True,
stdout_isatty=True,
devnull=io.BytesIO()
)
r = http(argument_name, 'GET', httpbin.url + '/get', env=env)
r = http(*quiet_flags, 'GET', httpbin.url + '/get', env=env)
assert env.stdout is env.devnull
assert env.stderr is env.devnull
assert HTTP_OK in r.devnull
Expand All @@ -69,9 +70,25 @@ def test_quiet_with_check_status_non_zero_pipe(self, httpbin):
)
assert 'http: warning: HTTP 500' in r.stderr

def test_quiet_quiet_with_check_status_non_zero(self, httpbin):
r = http(
'--quiet', '--quiet', '--check-status', httpbin + '/status/500',
tolerate_error_exit_status=True,
)
assert not r.stderr

def test_quiet_quiet_with_check_status_non_zero_pipe(self, httpbin):
r = http(
'--quiet', '--quiet', '--check-status', httpbin + '/status/500',
tolerate_error_exit_status=True,
env=MockEnvironment(stdout_isatty=False)
)
assert 'http: warning: HTTP 500' in r.stderr

@pytest.mark.parametrize('quiet_flags', QUIET_SCENARIOS)
@mock.patch('httpie.cli.argtypes.AuthCredentials._getpass',
new=lambda self, prompt: 'password')
def test_quiet_with_password_prompt(self, httpbin):
def test_quiet_with_password_prompt(self, httpbin, quiet_flags):
"""
Tests whether httpie still prompts for a password when request
requires authentication and only username is provided
Expand All @@ -83,7 +100,7 @@ def test_quiet_with_password_prompt(self, httpbin):
devnull=io.BytesIO()
)
r = http(
'--quiet', '--auth', 'user', 'GET',
*quiet_flags, '--auth', 'user', 'GET',
httpbin.url + '/basic-auth/user/password',
env=env
)
Expand All @@ -93,17 +110,19 @@ def test_quiet_with_password_prompt(self, httpbin):
assert r == ''
assert r.stderr == ''

@pytest.mark.parametrize('argument_name', ['-h', '-b', '-v', '-p=hH'])
def test_quiet_with_explicit_output_options(self, httpbin, argument_name):
@pytest.mark.parametrize('quiet_flags', QUIET_SCENARIOS)
@pytest.mark.parametrize('output_options', ['-h', '-b', '-v', '-p=hH'])
def test_quiet_with_explicit_output_options(self, httpbin, quiet_flags, output_options):
env = MockEnvironment(stdin_isatty=True, stdout_isatty=True)
r = http('--quiet', argument_name, httpbin.url + '/get', env=env)
r = http(*quiet_flags, output_options, httpbin.url + '/get', env=env)
assert env.stdout is env.devnull
assert env.stderr is env.devnull
assert r == ''
assert r.stderr == ''

@pytest.mark.parametrize('quiet_flags', QUIET_SCENARIOS)
@pytest.mark.parametrize('with_download', [True, False])
def test_quiet_with_output_redirection(self, tmp_path, httpbin, with_download):
def test_quiet_with_output_redirection(self, tmp_path, httpbin, quiet_flags, with_download):
url = httpbin + '/robots.txt'
output_path = Path('output.txt')
env = MockEnvironment()
Expand All @@ -114,7 +133,7 @@ def test_quiet_with_output_redirection(self, tmp_path, httpbin, with_download):
try:
assert os.listdir('.') == []
r = http(
'--quiet',
*quiet_flags,
'--output', str(output_path),
*extra_args,
url,
Expand Down Expand Up @@ -142,7 +161,7 @@ def test_verbose(self, httpbin):

def test_verbose_raw(self, httpbin):
r = http('--verbose', '--raw', 'foo bar',
'POST', httpbin.url + '/post',)
'POST', httpbin.url + '/post')
assert HTTP_OK in r
assert 'foo bar' in r

Expand Down