forked from extern/httpie-cli
Merge branch 'mgsloan-allow-closed-stdin'
This commit is contained in:
commit
d998013655
@ -7,7 +7,6 @@ env:
|
||||
global:
|
||||
- NEWEST_PYTHON=3.7
|
||||
python:
|
||||
- 3.5
|
||||
- 3.6
|
||||
# - 3.7 # is done in the matrix below as described in travis-ci/travis-ci#9069
|
||||
# pypy3 currently fails because of a Flask issue
|
||||
|
@ -14,6 +14,7 @@ This project adheres to `Semantic Versioning <http://semver.org/>`_.
|
||||
* Added ``--max-headers`` to allow setting the max header limit.
|
||||
* Added ``--compress``.
|
||||
* Added ``https`` alias command with ``https://`` as the default scheme.
|
||||
* Fixed an exception when ``stdin`` was a closed fd.
|
||||
|
||||
|
||||
`1.0.3`_ (2019-08-26)
|
||||
|
@ -126,7 +126,7 @@ and always provides the latest version) is to use `pip`_:
|
||||
Python version
|
||||
--------------
|
||||
|
||||
Starting with version 2.0.0 (currently under development) Python 3.5+ is required.
|
||||
Starting with version 2.0.0 (currently under development) Python 3.6+ is required.
|
||||
|
||||
|
||||
Unstable version
|
||||
|
@ -1,4 +1,7 @@
|
||||
import sys
|
||||
from typing import Union, IO, Optional
|
||||
|
||||
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
@ -22,8 +25,8 @@ class Environment(object):
|
||||
"""
|
||||
is_windows = is_windows
|
||||
config_dir = DEFAULT_CONFIG_DIR
|
||||
stdin = sys.stdin
|
||||
stdin_isatty = stdin.isatty()
|
||||
stdin: Optional[IO] = sys.stdin # `None` when closed fd (#791)
|
||||
stdin_isatty = stdin.isatty() if stdin else False
|
||||
stdin_encoding = None
|
||||
stdout = sys.stdout
|
||||
stdout_isatty = stdout.isatty()
|
||||
@ -61,7 +64,7 @@ class Environment(object):
|
||||
self.__dict__.update(**kwargs)
|
||||
|
||||
# Keyword arguments > stream.encoding > default utf8
|
||||
if self.stdin_encoding is None:
|
||||
if self.stdin and self.stdin_encoding is None:
|
||||
self.stdin_encoding = getattr(
|
||||
self.stdin, 'encoding', None) or 'utf8'
|
||||
if self.stdout_encoding is None:
|
||||
|
@ -134,6 +134,7 @@ class HTTPieArgumentParser(ArgumentParser):
|
||||
super(HTTPieArgumentParser, self).__init__(*args, **kwargs)
|
||||
self.env = None
|
||||
self.args = None
|
||||
self.has_stdin_data = False
|
||||
|
||||
# noinspection PyMethodOverriding
|
||||
def parse_args(self, env, program_name='http', args=None, namespace=None):
|
||||
@ -144,6 +145,12 @@ class HTTPieArgumentParser(ArgumentParser):
|
||||
if self.args.debug:
|
||||
self.args.traceback = True
|
||||
|
||||
self.has_stdin_data = (
|
||||
self.env.stdin
|
||||
and not self.args.ignore_stdin
|
||||
and not self.env.stdin_isatty
|
||||
)
|
||||
|
||||
# Arguments processing and environment setup.
|
||||
self._apply_no_options(no_options)
|
||||
self._validate_download_options()
|
||||
@ -152,7 +159,8 @@ class HTTPieArgumentParser(ArgumentParser):
|
||||
self._process_pretty_options()
|
||||
self._guess_method()
|
||||
self._parse_items()
|
||||
if not self.args.ignore_stdin and not env.stdin_isatty:
|
||||
|
||||
if self.has_stdin_data:
|
||||
self._body_from_file(self.env.stdin)
|
||||
if not URL_SCHEME_RE.match(self.args.url):
|
||||
if os.path.basename(program_name) == 'https':
|
||||
@ -320,7 +328,7 @@ class HTTPieArgumentParser(ArgumentParser):
|
||||
if self.args.method is None:
|
||||
# Invoked as `http URL'.
|
||||
assert not self.args.items
|
||||
if not self.args.ignore_stdin and not self.env.stdin_isatty:
|
||||
if self.has_stdin_data:
|
||||
self.args.method = HTTP_POST
|
||||
else:
|
||||
self.args.method = HTTP_GET
|
||||
@ -344,7 +352,7 @@ class HTTPieArgumentParser(ArgumentParser):
|
||||
self.args.url = self.args.method
|
||||
# Infer the method
|
||||
has_data = (
|
||||
(not self.args.ignore_stdin and not self.env.stdin_isatty)
|
||||
self.has_stdin_data
|
||||
or any(
|
||||
item.sep in SEP_GROUP_DATA_ITEMS
|
||||
for item in self.args.items
|
||||
|
@ -310,7 +310,7 @@ class TestNoOptions:
|
||||
assert 'GET /get HTTP/1.1' not in r
|
||||
|
||||
|
||||
class TestIgnoreStdin:
|
||||
class TestStdin:
|
||||
|
||||
def test_ignore_stdin(self, httpbin):
|
||||
with open(FILE_PATH) as f:
|
||||
@ -327,6 +327,10 @@ class TestIgnoreStdin:
|
||||
assert r.exit_status == ExitStatus.ERROR
|
||||
assert 'because --ignore-stdin' in r.stderr
|
||||
|
||||
def test_stdin_closed(self, httpbin):
|
||||
r = http(httpbin + '/get', env=MockEnvironment(stdin=None))
|
||||
assert HTTP_OK in r
|
||||
|
||||
|
||||
class TestSchemes:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user