Skip to content

Commit

Permalink
Introduce a mode to suppress all warnings (#1283)
Browse files Browse the repository at this point in the history
  • Loading branch information
isidentical authored Mar 7, 2022
1 parent c901e70 commit 55087a9
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 6 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Fixed escaping of integer indexes with multiple backslashes in the nested JSON builder. ([#1285](https://github.com/httpie/httpie/issues/1285))
- Fixed displaying of status code without a status message on non-`auto` themes. ([#1300](https://github.com/httpie/httpie/issues/1300))
- Improved regulation of top-level arrays. ([#1292](https://github.com/httpie/httpie/commit/225dccb2186f14f871695b6c4e0bfbcdb2e3aa28))

- 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)

Expand Down
2 changes: 2 additions & 0 deletions httpie/cli/argparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,11 @@ def _setup_standard_streams(self):
self.env.stdout_isatty = False

if self.args.quiet:
self.env.quiet = self.args.quiet
self.env.stderr = self.env.devnull
if not (self.args.output_file_specified and not self.args.download):
self.env.stdout = self.env.devnull
self.env.apply_warnings_filter()

def _process_auth(self):
# TODO: refactor & simplify this method.
Expand Down
29 changes: 26 additions & 3 deletions httpie/context.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import sys
import os
import warnings
from contextlib import contextmanager
from pathlib import Path
from typing import Iterator, IO, Optional
from enum import Enum


try:
Expand All @@ -17,6 +19,17 @@
from .utils import repr_dict


class Levels(str, Enum):
WARNING = 'warning'
ERROR = 'error'


DISPLAY_THRESHOLDS = {
Levels.WARNING: 2,
Levels.ERROR: float('inf'), # Never hide errors.
}


class Environment:
"""
Information about the execution context
Expand Down Expand Up @@ -87,6 +100,8 @@ def __init__(self, devnull=None, **kwargs):
self.stdout_encoding = getattr(
actual_stdout, 'encoding', None) or UTF8

self.quiet = kwargs.pop('quiet', 0)

def __str__(self):
defaults = dict(type(self).__dict__)
actual = dict(defaults)
Expand Down Expand Up @@ -134,6 +149,14 @@ def as_silent(self) -> Iterator[None]:
self.stdout = original_stdout
self.stderr = original_stderr

def log_error(self, msg, level='error'):
assert level in ['error', 'warning']
self._orig_stderr.write(f'\n{self.program_name}: {level}: {msg}\n\n')
def log_error(self, msg: str, level: Levels = Levels.ERROR) -> None:
if self.stdout_isatty and self.quiet >= DISPLAY_THRESHOLDS[level]:
stderr = self.stderr # Not directly /dev/null, since stderr might be mocked
else:
stderr = self._orig_stderr

stderr.write(f'\n{self.program_name}: {level}: {msg}\n\n')

def apply_warnings_filter(self) -> None:
if self.quiet >= DISPLAY_THRESHOLDS[Levels.WARNING]:
warnings.simplefilter("ignore")
4 changes: 2 additions & 2 deletions httpie/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .cli.constants import OUT_REQ_BODY
from .cli.nested_json import HTTPieSyntaxError
from .client import collect_messages
from .context import Environment
from .context import Environment, Levels
from .downloads import Downloader
from .models import (
RequestsMessageKind,
Expand Down Expand Up @@ -221,7 +221,7 @@ def request_body_read_callback(chunk: bytes):
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 == 1):
env.log_error(f'HTTP {message.raw.status} {message.raw.reason}', level='warning')
env.log_error(f'HTTP {message.raw.status} {message.raw.reason}', level=Levels.WARNING)
write_message(requests_message=message, env=env, args=args, output_options=output_options._replace(
body=do_write_body
))
Expand Down
26 changes: 26 additions & 0 deletions tests/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import json
import os
import io
import warnings
from urllib.request import urlopen

import pytest
Expand Down Expand Up @@ -90,6 +91,31 @@ def test_quiet_quiet_with_check_status_non_zero_pipe(self, httpbin):
)
assert 'http: warning: HTTP 500' in r.stderr

@mock.patch('httpie.core.program')
@pytest.mark.parametrize('flags, expected_warnings', [
([], 1),
(['-q'], 1),
(['-qq'], 0),
])
def test_quiet_on_python_warnings(self, test_patch, httpbin, flags, expected_warnings):
def warn_and_run(*args, **kwargs):
warnings.warn('warning!!')
return ExitStatus.SUCCESS

test_patch.side_effect = warn_and_run
with pytest.warns(None) as record:
http(*flags, httpbin + '/get')

assert len(record) == expected_warnings

def test_double_quiet_on_error(self, httpbin):
r = http(
'-qq', '--check-status', '$$$this.does.not.exist$$$',
tolerate_error_exit_status=True,
)
assert not r
assert 'Couldn’t resolve the given hostname' in r.stderr

@pytest.mark.parametrize('quiet_flags', QUIET_SCENARIOS)
@mock.patch('httpie.cli.argtypes.AuthCredentials._getpass',
new=lambda self, prompt: 'password')
Expand Down
2 changes: 2 additions & 0 deletions tests/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import time
import json
import tempfile
import warnings
from io import BytesIO
from pathlib import Path
from typing import Any, Optional, Union, List, Iterable
Expand Down Expand Up @@ -96,6 +97,7 @@ def create_temp_config_dir(self):
def cleanup(self):
self.stdout.close()
self.stderr.close()
warnings.resetwarnings()
if self._delete_config_dir:
assert self._temp_dir in self.config_dir.parents
from shutil import rmtree
Expand Down

0 comments on commit 55087a9

Please sign in to comment.