mirror of
https://github.com/httpie/cli.git
synced 2024-11-25 01:03:27 +01:00
Introduce a mode to suppress all warnings (#1283)
This commit is contained in:
parent
c901e70463
commit
55087a901e
@ -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 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))
|
- 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))
|
- 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)
|
## [3.0.2](https://github.com/httpie/httpie/compare/3.0.1...3.0.2) (2022-01-24)
|
||||||
|
|
||||||
|
@ -230,9 +230,11 @@ class HTTPieArgumentParser(BaseHTTPieArgumentParser):
|
|||||||
self.env.stdout_isatty = False
|
self.env.stdout_isatty = False
|
||||||
|
|
||||||
if self.args.quiet:
|
if self.args.quiet:
|
||||||
|
self.env.quiet = self.args.quiet
|
||||||
self.env.stderr = self.env.devnull
|
self.env.stderr = self.env.devnull
|
||||||
if not (self.args.output_file_specified and not self.args.download):
|
if not (self.args.output_file_specified and not self.args.download):
|
||||||
self.env.stdout = self.env.devnull
|
self.env.stdout = self.env.devnull
|
||||||
|
self.env.apply_warnings_filter()
|
||||||
|
|
||||||
def _process_auth(self):
|
def _process_auth(self):
|
||||||
# TODO: refactor & simplify this method.
|
# TODO: refactor & simplify this method.
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import warnings
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Iterator, IO, Optional
|
from typing import Iterator, IO, Optional
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -17,6 +19,17 @@ from .encoding import UTF8
|
|||||||
from .utils import repr_dict
|
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:
|
class Environment:
|
||||||
"""
|
"""
|
||||||
Information about the execution context
|
Information about the execution context
|
||||||
@ -87,6 +100,8 @@ class Environment:
|
|||||||
self.stdout_encoding = getattr(
|
self.stdout_encoding = getattr(
|
||||||
actual_stdout, 'encoding', None) or UTF8
|
actual_stdout, 'encoding', None) or UTF8
|
||||||
|
|
||||||
|
self.quiet = kwargs.pop('quiet', 0)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
defaults = dict(type(self).__dict__)
|
defaults = dict(type(self).__dict__)
|
||||||
actual = dict(defaults)
|
actual = dict(defaults)
|
||||||
@ -134,6 +149,14 @@ class Environment:
|
|||||||
self.stdout = original_stdout
|
self.stdout = original_stdout
|
||||||
self.stderr = original_stderr
|
self.stderr = original_stderr
|
||||||
|
|
||||||
def log_error(self, msg, level='error'):
|
def log_error(self, msg: str, level: Levels = Levels.ERROR) -> None:
|
||||||
assert level in ['error', 'warning']
|
if self.stdout_isatty and self.quiet >= DISPLAY_THRESHOLDS[level]:
|
||||||
self._orig_stderr.write(f'\n{self.program_name}: {level}: {msg}\n\n')
|
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")
|
||||||
|
@ -13,7 +13,7 @@ from . import __version__ as httpie_version
|
|||||||
from .cli.constants import OUT_REQ_BODY
|
from .cli.constants import OUT_REQ_BODY
|
||||||
from .cli.nested_json import HTTPieSyntaxError
|
from .cli.nested_json import HTTPieSyntaxError
|
||||||
from .client import collect_messages
|
from .client import collect_messages
|
||||||
from .context import Environment
|
from .context import Environment, Levels
|
||||||
from .downloads import Downloader
|
from .downloads import Downloader
|
||||||
from .models import (
|
from .models import (
|
||||||
RequestsMessageKind,
|
RequestsMessageKind,
|
||||||
@ -221,7 +221,7 @@ def program(args: argparse.Namespace, env: Environment) -> ExitStatus:
|
|||||||
if args.check_status or downloader:
|
if args.check_status or downloader:
|
||||||
exit_status = http_status_to_exit_status(http_status=message.status_code, follow=args.follow)
|
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):
|
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(
|
write_message(requests_message=message, env=env, args=args, output_options=output_options._replace(
|
||||||
body=do_write_body
|
body=do_write_body
|
||||||
))
|
))
|
||||||
|
@ -5,6 +5,7 @@ from unittest import mock
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import io
|
import io
|
||||||
|
import warnings
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -90,6 +91,31 @@ class TestQuietFlag:
|
|||||||
)
|
)
|
||||||
assert 'http: warning: HTTP 500' in r.stderr
|
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)
|
@pytest.mark.parametrize('quiet_flags', QUIET_SCENARIOS)
|
||||||
@mock.patch('httpie.cli.argtypes.AuthCredentials._getpass',
|
@mock.patch('httpie.cli.argtypes.AuthCredentials._getpass',
|
||||||
new=lambda self, prompt: 'password')
|
new=lambda self, prompt: 'password')
|
||||||
|
@ -5,6 +5,7 @@ import sys
|
|||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import warnings
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Optional, Union, List, Iterable
|
from typing import Any, Optional, Union, List, Iterable
|
||||||
@ -96,6 +97,7 @@ class MockEnvironment(Environment):
|
|||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
self.stdout.close()
|
self.stdout.close()
|
||||||
self.stderr.close()
|
self.stderr.close()
|
||||||
|
warnings.resetwarnings()
|
||||||
if self._delete_config_dir:
|
if self._delete_config_dir:
|
||||||
assert self._temp_dir in self.config_dir.parents
|
assert self._temp_dir in self.config_dir.parents
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
|
Loading…
Reference in New Issue
Block a user