1
0
mirror of https://github.com/httpie/cli.git synced 2025-02-13 13:18:45 +02:00

Build fixes and clean-up

* reflect Python 3.7 release
* fix `pycodestyle` errors
* update `pycodestyle` config
* move `pytest` and `pycodestyle` config to `setup.cfg`
* add `make pycodestyle`
* add `make coveralls`
* etc.
This commit is contained in:
Jakub Roztocil 2018-07-12 21:16:16 +02:00
parent a50660cc70
commit 7917f1b40c
18 changed files with 175 additions and 145 deletions

View File

@ -1 +0,0 @@
; needs to exist otherwise `$ coveralls` fails

4
.gitignore vendored
View File

@ -2,12 +2,12 @@
.idea/
__pycache__/
dist/
httpie.egg-info/
build/
*.egg-info
.cache/
.tox
.tox/
.coverage
*.pyc
*.egg
htmlcov
.pytest_cache/

View File

@ -1,95 +1,77 @@
# https://travis-ci.org/jakubroztocil/httpie
# <https://travis-ci.org/jakubroztocil/httpie>
sudo: false
language: python
os:
- linux
env:
global:
- NEWEST_PYTHON=3.6
- NEWEST_PYTHON=3.7
python:
- 2.7
- pypy
- 3.4
- 3.5
- 3.6
# Currently fails because of a Flask issue
# - pypy3
- 3.7
- pypy
# pypy3 currently fails because of a Flask issue
# - pypy3
cache: pip
matrix:
include:
# Manually defined OS X builds
# https://docs.travis-ci.com/user/multi-os/#Python-example-(unsupported-languages)
# Stock OSX Python
# Add manually defined OS X builds
# <https://docs.travis-ci.com/user/multi-os/#Python-example-(unsupported-languages)>
- os: osx
language: generic
env:
# Stock OSX Python
- TOXENV=py27
# Latest Python 2.x from Homebrew
- BREW_PYTHON_PACKAGE=
- os: osx
language: generic
env:
# Latest Python 2.7 from Homebrew
- TOXENV=py27
- BREW_INSTALL=python
# Latest Python 3.x from Homebrew
- BREW_PYTHON_PACKAGE=python@2
- os: osx
language: generic
env:
- TOXENV=py36
- BREW_INSTALL=python3
# Python Codestyle
# Latest Python 3.x from Homebrew
- TOXENV=py37 # <= needs to be kept up-to-date to reflect latest minor version
- BREW_PYTHON_PACKAGE=python@3
# Add a codestyle-only build
- os: linux
python: 3.6
env: CODESTYLE=true
env: CODESTYLE_ONLY=true
install:
- |
- |
if [[ $TRAVIS_OS_NAME == 'osx' ]]; then
if [[ -n "$BREW_INSTALL" ]]; then
brew update
brew install "$BREW_INSTALL"
fi
sudo pip install tox
sudo pip install tox
if [[ -n "$BREW_PYTHON_PACKAGE" ]]; then
brew install "$BREW_PYTHON_PACKAGE"
fi
fi
if [[ $CODESTYLE ]]; then
pip install pycodestyle
fi
script:
- |
- |
if [[ $TRAVIS_OS_NAME == 'linux' ]]; then
if [[ $CODESTYLE ]]; then
# 241 - multiple spaces after ‘,’
# 501 - line too long
pycodestyle --ignore=E241,E501
else
make
fi
if [[ $CODESTYLE_ONLY ]]; then
make pycodestyle
else
make test
fi
else
PATH="/usr/local/bin:$PATH" tox -e "$TOXENV"
PATH="/usr/local/bin:$PATH" tox -e "$TOXENV"
fi
after_success:
- |
- |
if [[ $TRAVIS_PYTHON_VERSION == $NEWEST_PYTHON && $TRAVIS_OS_NAME == 'linux' ]]; then
pip install python-coveralls && coveralls
make coveralls
fi
notifications:
webhooks:
# options: [always|never|change] default: always
on_success: always
on_failure: always
on_start: always
urls:
# https://gitter.im/jkbrzt/httpie
- https://webhooks.gitter.im/e/c42fcd359a110d02830b
on_success: always # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: always # options: [always|never|change] default: always

View File

@ -53,7 +53,8 @@ Go to https://github.com/jakubroztocil/httpie and fork the project repository.
Making Changes
--------------
Please make sure your changes conform to `Style Guide for Python Code`_ (PEP8).
Please make sure your changes conform to `Style Guide for Python Code`_ (PEP8)
and that ``make pycodestyle`` passes.
Testing
@ -80,6 +81,9 @@ Running all tests:
# Run all tests for code as well as packaging, etc.
make test-all
# Test PEP8 compliance
make pycodestyle
Running specific tests:
***********************
@ -92,11 +96,11 @@ Running specific tests:
py.test tests/test_uploads.py::TestMultipartFormDataFileUpload::test_upload_ok
# Run specific tests on the on all Pythons via Tox
# (change to `tox -e py37' to limit Python version)
tox -- tests/test_uploads.py --verbose
tox -- tests/test_uploads.py::TestMultipartFormDataFileUpload --verbose
tox -- tests/test_uploads.py::TestMultipartFormDataFileUpload::test_upload_ok --verbose
-----
See `Makefile`_ for additional development utilities.

View File

@ -1,6 +1,6 @@
#
###############################################################################
# See ./CONTRIBUTING.rst
#
###############################################################################
VERSION=$(shell grep __version__ httpie/__init__.py)
REQUIREMENTS="requirements-dev.txt"
@ -20,6 +20,17 @@ init: uninstall-httpie
@echo
clean:
@echo $(TAG)Cleaning up$(END)
rm -rf .tox *.egg dist build .coverage .cache .pytest_cache httpie.egg-info
find . -name '__pycache__' -delete -print -o -name '*.pyc' -delete -print
@echo
###############################################################################
# Testing
###############################################################################
test: init
@echo $(TAG)Running tests on the current Python interpreter with coverage $(END)
@ -27,9 +38,8 @@ test: init
@echo
test-tox: init
@echo $(TAG)Running tests on all Pythons via Tox$(END)
tox
# test-all is meant to test everything — even this Makefile
test-all: uninstall-all clean init test test-tox test-dist pycodestyle
@echo
@ -37,6 +47,12 @@ test-dist: test-sdist test-bdist-wheel
@echo
test-tox: init
@echo $(TAG)Running tests on all Pythons via Tox$(END)
tox
@echo
test-sdist: clean uninstall-httpie
@echo $(TAG)Testing sdist build an installation$(END)
python setup.py sdist
@ -53,12 +69,26 @@ test-bdist-wheel: clean uninstall-httpie
@echo
# This tests everything, even this Makefile.
test-all: uninstall-all clean init test test-tox test-dist
pycodestyle:
which pycodestyle || pip install pycodestyle
pycodestyle
@echo
coveralls:
which coveralls || pip install python-coveralls
coveralls
@echo
###############################################################################
# Publishing to PyPi
###############################################################################
publish: test-all publish-no-test
publish-no-test:
@echo $(TAG)Testing wheel build an installation$(END)
@echo "$(VERSION)"
@ -69,12 +99,10 @@ publish-no-test:
@echo
clean:
@echo $(TAG)Cleaning up$(END)
rm -rf .tox *.egg dist build .coverage
find . -name '__pycache__' -delete -print -o -name '*.pyc' -delete -print
@echo
###############################################################################
# Uninstalling
###############################################################################
uninstall-httpie:
@echo $(TAG)Uninstalling httpie$(END)
@ -96,5 +124,10 @@ uninstall-all: uninstall-httpie
- pip uninstall --yes -r $(REQUIREMENTS)
###############################################################################
# Utils
###############################################################################
homebrew-formula-vars:
extras/get-homebrew-formula-vars.py

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
Generate URLs and file hashes to be included in the Homebrew formula
after a new release of HTTPie is published on PyPi.
after a new release of HTTPie has been published on PyPi.
https://github.com/Homebrew/homebrew-core/blob/master/Formula/httpie.rb
@ -17,7 +17,7 @@ PACKAGES = [
]
def get_info(package_name):
def get_package_meta(package_name):
api_url = 'https://pypi.python.org/pypi/{}/json'.format(package_name)
resp = requests.get(api_url).json()
hasher = hashlib.sha256()
@ -35,21 +35,23 @@ def get_info(package_name):
'{}: download not found: {}'.format(package_name, resp))
packages = {
package_name: get_info(package_name) for package_name in PACKAGES
}
def main():
package_meta_map = {
package_name: get_package_meta(package_name)
for package_name in PACKAGES
}
httpie_meta = package_meta_map.pop('httpie')
print()
print(' url "{url}"'.format(url=httpie_meta['url']))
print(' sha256 "{sha256}"'.format(sha256=httpie_meta['sha256']))
print()
for dep_meta in package_meta_map.values():
print(' resource "{name}" do'.format(name=dep_meta['name']))
print(' url "{url}"'.format(url=dep_meta['url']))
print(' sha256 "{sha256}"'.format(sha256=dep_meta['sha256']))
print(' end')
print()
httpie_info = packages.pop('httpie')
print("""
url "{url}"
sha256 "{sha256}"
""".format(**httpie_info))
for package_info in packages.values():
print("""
resource "{name}" do
url "{url}"
sha256 "{sha256}"
end""".format(**package_info))
if __name__ == '__main__':
main()

View File

@ -164,8 +164,8 @@ def program(args, env, log_error):
if downloader and not downloader.finished:
downloader.failed()
if (not isinstance(args, list) and args.output_file and
args.output_file_specified):
if (not isinstance(args, list) and args.output_file
and args.output_file_specified):
args.output_file.close()

View File

@ -54,8 +54,8 @@ def parse_content_range(content_range, resumed_from):
raise ContentRangeError('Missing Content-Range')
pattern = (
'^bytes (?P<first_byte_pos>\d+)-(?P<last_byte_pos>\d+)'
'/(\*|(?P<instance_length>\d+))$'
r'^bytes (?P<first_byte_pos>\d+)-(?P<last_byte_pos>\d+)'
r'/(\*|(?P<instance_length>\d+))$'
)
match = re.match(pattern, content_range)
@ -78,15 +78,15 @@ def parse_content_range(content_range, resumed_from):
# last-byte-pos value, is invalid. The recipient of an invalid
# byte-content-range- spec MUST ignore it and any content
# transferred along with it."
if (first_byte_pos >= last_byte_pos or
(instance_length is not None and
instance_length <= last_byte_pos)):
if (first_byte_pos >= last_byte_pos
or (instance_length is not None
and instance_length <= last_byte_pos)):
raise ContentRangeError(
'Invalid Content-Range returned: %r' % content_range)
if (first_byte_pos != resumed_from or
(instance_length is not None and
last_byte_pos + 1 != instance_length)):
if (first_byte_pos != resumed_from
or (instance_length is not None
and last_byte_pos + 1 != instance_length)):
# Not what we asked for.
raise ContentRangeError(
'Unexpected Content-Range returned (%r)'
@ -308,9 +308,9 @@ class Downloader(object):
@property
def interrupted(self):
return (
self.finished and
self.status.total_size and
self.status.total_size != self.status.downloaded
self.finished
and self.status.total_size
and self.status.total_size != self.status.downloaded
)
def chunk_downloaded(self, chunk):
@ -399,8 +399,8 @@ class ProgressReporterThread(threading.Thread):
if now - self._prev_time >= self._update_interval:
downloaded = self.status.downloaded
try:
speed = ((downloaded - self._prev_bytes) /
(now - self._prev_time))
speed = ((downloaded - self._prev_bytes)
/ (now - self._prev_time))
except ZeroDivisionError:
speed = 0
@ -434,11 +434,11 @@ class ProgressReporterThread(threading.Thread):
self._prev_bytes = downloaded
self.output.write(
CLEAR_LINE +
' ' +
SPINNER[self._spinner_pos] +
' ' +
self._status_line
CLEAR_LINE
+ ' '
+ SPINNER[self._spinner_pos]
+ ' '
+ self._status_line
)
self.output.flush()
@ -463,8 +463,8 @@ class ProgressReporterThread(threading.Thread):
self.output.write(SUMMARY.format(
downloaded=humanize_bytes(actually_downloaded),
total=(self.status.total_size and
humanize_bytes(self.status.total_size)),
total=(self.status.total_size
and humanize_bytes(self.status.total_size)),
speed=humanize_bytes(speed),
time=time_taken,
))

View File

@ -254,8 +254,8 @@ class HTTPieArgumentParser(ArgumentParser):
else:
credentials = parse_auth(self.args.auth)
if (not credentials.has_password() and
plugin.prompt_password):
if (not credentials.has_password()
and plugin.prompt_password):
if self.args.ignore_stdin:
# Non-tty stdin read by now
self.error(
@ -338,10 +338,11 @@ 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) or
any(item.sep in SEP_GROUP_DATA_ITEMS
for item in self.args.items)
(not self.args.ignore_stdin and not self.env.stdin_isatty)
or any(
item.sep in SEP_GROUP_DATA_ITEMS
for item in self.args.items
)
)
self.args.method = HTTP_POST if has_data else HTTP_GET
@ -426,8 +427,8 @@ class HTTPieArgumentParser(ArgumentParser):
if self.args.prettify == PRETTY_STDOUT_TTY_ONLY:
self.args.prettify = PRETTY_MAP[
'all' if self.env.stdout_isatty else 'none']
elif (self.args.prettify and self.env.is_windows and
self.args.output_file):
elif (self.args.prettify and self.env.is_windows
and self.args.output_file):
self.error('Only terminal output can be colorized on Windows.')
else:
# noinspection PyTypeChecker
@ -469,8 +470,8 @@ class SessionNameValidator(object):
def __call__(self, value):
# Session name can be a path or just a name.
if (os.path.sep not in value and
not VALID_SESSION_NAME_PATTERN.search(value)):
if (os.path.sep not in value
and not VALID_SESSION_NAME_PATTERN.search(value)):
raise ArgumentError(None, self.error_message)
return value
@ -505,7 +506,7 @@ class KeyValueArgType(object):
"""Represents an escaped character."""
def tokenize(string):
"""Tokenize `string`. There are only two token types - strings
r"""Tokenize `string`. There are only two token types - strings
and escaped characters:
tokenize(r'foo\=bar\\baz')

View File

@ -15,8 +15,8 @@ class JSONFormatter(FormatterPlugin):
'javascript',
'text',
]
if (self.kwargs['explicit_json'] or
any(token in mime for token in maybe_json)):
if (self.kwargs['explicit_json']
or any(token in mime for token in maybe_json)):
try:
obj = json.loads(body)
except ValueError:

View File

@ -30,8 +30,8 @@ def get_response(requests_session, session_name,
if os.path.sep in session_name:
path = os.path.expanduser(session_name)
else:
hostname = (args.headers.get('Host', None) or
urlsplit(args.url).netloc.split('@')[-1])
hostname = (args.headers.get('Host', None)
or urlsplit(args.url).netloc.split('@')[-1])
if not hostname:
# HACK/FIXME: httpie-unixsocket's URLs have no hostname.
hostname = 'localhost'

View File

@ -1,2 +0,0 @@
[pytest]
norecursedirs = tests/fixtures

View File

@ -5,3 +5,4 @@ pytest-cov
pytest-httpbin>=0.0.6
docutils
wheel
pycodestyle

View File

@ -1,2 +1,19 @@
[wheel]
universal = 1
[tool:pytest]
# <https://docs.pytest.org/en/latest/customize.html>
norecursedirs = tests/fixtures
[pycodestyle]
# <http://pycodestyle.pycqa.org/en/latest/intro.html#configuration>
exclude = .git,.idea,__pycache__,build,dist,.tox,.pytest_cache,*.egg-info
# <http://pycodestyle.pycqa.org/en/latest/intro.html#error-codes>
# E241 - multiple spaces after ‘,’
# E501 - line too long
# W503 - line break before binary operator
ignore = E241,E501,W503

View File

@ -49,9 +49,9 @@ class TestItemParsing:
assert 'bar@baz' in items.files
@pytest.mark.parametrize(('string', 'key', 'sep', 'value'), [
('path=c:\windows', 'path', '=', 'c:\windows'),
('path=c:\windows\\', 'path', '=', 'c:\windows\\'),
('path\==c:\windows', 'path=', '=', 'c:\windows'),
('path=c:\\windows', 'path', '=', 'c:\\windows'),
('path=c:\\windows\\', 'path', '=', 'c:\\windows\\'),
('path\\==c:\\windows', 'path=', '=', 'c:\\windows'),
])
def test_backslash_before_non_special_character_does_not_escape(
self, string, key, sep, value):

View File

@ -81,8 +81,8 @@ class TestSessionFlow(SessionTestBase):
assert HTTP_OK in r4
assert r4.json['headers']['Hello'] == 'World2'
assert r4.json['headers']['Cookie'] == 'hello=world2'
assert (r2.json['headers']['Authorization'] !=
r4.json['headers']['Authorization'])
assert (r2.json['headers']['Authorization']
!= r4.json['headers']['Authorization'])
def test_session_read_only(self, httpbin):
self.start_session(httpbin)
@ -157,8 +157,8 @@ class TestSession(SessionTestBase):
assert HTTP_OK in r2
# FIXME: Authorization *sometimes* is not present on Python3
assert (r2.json['headers']['Authorization'] ==
HTTPBasicAuth.make_header(u'test', UNICODE))
assert (r2.json['headers']['Authorization']
== HTTPBasicAuth.make_header(u'test', UNICODE))
# httpbin doesn't interpret utf8 headers
assert UNICODE in r2

View File

@ -119,8 +119,8 @@ class StrCLIResponse(str, BaseCLIResponse):
elif self.strip().startswith('{'):
# Looks like JSON body.
self._json = json.loads(self)
elif (self.count('Content-Type:') == 1 and
'application/json' in self):
elif (self.count('Content-Type:') == 1
and 'application/json' in self):
# Looks like a whole JSON HTTP message,
# try to extract its body.
try:

11
tox.ini
View File

@ -3,7 +3,8 @@
[tox]
envlist = py27, py35, py36, pypy, codestyle
# pypy3 currently fails because of a Flask issue
envlist = py27, py37, pypy
[testenv]
@ -20,11 +21,3 @@ commands =
--verbose \
--doctest-modules \
{posargs:./httpie ./tests}
[testenv:codestyle]
deps = pycodestyle
commands =
pycodestyle \
--ignore=E241,E501
# 241 - multiple spaces after ‘,’
# 501 - line too long