diff --git a/.travis.yml b/.travis.yml index b5b2acae..8d447e03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,9 @@ language: python python: - 2.6 - 2.7 - # TODO: Python 3 - #- 3.2 + - 3.1 + - 3.2 + - 3.3 script: python tests/tests.py install: - pip install requests pygments diff --git a/README.rst b/README.rst index 0e814b65..d3b68351 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ HTTPie does so by providing an ``http`` command that allows for issuing arbitrar .. image:: https://github.com/jkbr/httpie/raw/master/httpie.png :alt: HTTPie compared to cURL -Under the hood, HTTPie uses the excellent `Requests `_ and `Pygments `_ Python libraries. +Under the hood, HTTPie uses the excellent `Requests `_ and `Pygments `_ Python libraries. Python >= 2.6 is supported (including Python 3.x). Installation ------------ diff --git a/httpie/__main__.py b/httpie/__main__.py index 7a8a994a..cd9e2de6 100644 --- a/httpie/__main__.py +++ b/httpie/__main__.py @@ -1,19 +1,19 @@ #!/usr/bin/env python -import os import sys import json -from urlparse import urlparse -import requests try: from collections import OrderedDict except ImportError: OrderedDict = dict +import requests +from requests.compat import urlparse, str from requests.structures import CaseInsensitiveDict from . import cli from . import pretty from . import __version__ as version +NEW_LINE = str('\n') DEFAULT_UA = 'HTTPie/%s' % version TYPE_FORM = 'application/x-www-form-urlencoded; charset=utf-8' TYPE_JSON = 'application/json; charset=utf-8' @@ -40,15 +40,14 @@ def format_http_message(message, prettifier=None, bits.append(message.line) bits.append(message.headers) if with_body and message.body: - bits.append('\n') + bits.append(NEW_LINE) if with_body and message.body: if prettifier and message.content_type: bits.append(prettifier.body(message.body, message.content_type)) else: bits.append(message.body) - bits = [bit.strip() for bit in bits] - bits.append('') - return '\n'.join(bits) + bits.append(NEW_LINE) + return NEW_LINE.join(bit.strip() for bit in bits) def make_request_message(request): @@ -61,9 +60,9 @@ def make_request_message(request): line='{method} {path} HTTP/1.1'.format( method=request.method, path=url.path or '/'), - headers='\n'.join('%s: %s' % (name, value) + headers=NEW_LINE.join(str('%s: %s') % (name, value) for name, value - in request_headers.iteritems()), + in request_headers.items()), body=request._enc_data, content_type=request_headers.get('Content-Type') ) @@ -78,8 +77,8 @@ def make_response_message(response): line='HTTP/{version} {status} {reason}'.format( version='.'.join(str(original.version)), status=original.status, reason=original.reason,), - headers=str(original.msg).decode(encoding), - body=response.content.decode(encoding) if response.content else u'', + headers=str(original.msg), + body=response.content.decode(encoding) if response.content else '', content_type=response_headers.get('Content-Type')) @@ -123,7 +122,6 @@ def main(args=None, 'data (key=value) cannot be mixed.') data = stdin.read() - # JSON/Form content type. if args.json or (not args.form and data): if stdin_isatty: @@ -148,12 +146,12 @@ def main(args=None, allow_redirects=args.allow_redirects, ) except (KeyboardInterrupt, SystemExit): - sys.stderr.write('\n') + sys.stderr.write(NEW_LINE) sys.exit(1) except Exception as e: if args.traceback: raise - sys.stderr.write(str(e.message) + '\n') + sys.stderr.write(str(e.message) + NEW_LINE) sys.exit(1) prettifier = pretty.PrettyHttp(args.style) if do_prettify else None @@ -170,9 +168,9 @@ def main(args=None, prettifier=prettifier, with_headers=cli.OUT_REQUEST_HEADERS in args.output_options, with_body=cli.OUT_REQUEST_BODY in args.output_options - ).encode('utf-8')) + )) if output_response: - stdout.write('\n') + stdout.write(NEW_LINE) if output_response: stdout.write(format_http_message( @@ -180,8 +178,8 @@ def main(args=None, prettifier=prettifier, with_headers=cli.OUT_RESPONSE_HEADERS in args.output_options, with_body=cli.OUT_RESPONSE_BODY in args.output_options - ).encode('utf-8')) - stdout.write('\n') + )) + stdout.write(NEW_LINE) if __name__ == '__main__': diff --git a/httpie/pretty.py b/httpie/pretty.py index 2b111810..7fea7969 100644 --- a/httpie/pretty.py +++ b/httpie/pretty.py @@ -13,7 +13,7 @@ from . import solarized DEFAULT_STYLE = 'solarized' -AVAILABLE_STYLES = [DEFAULT_STYLE] + STYLE_MAP.keys() +AVAILABLE_STYLES = [DEFAULT_STYLE] + list(STYLE_MAP.keys()) FORMATTER = (Terminal256Formatter if '256color' in os.environ.get('TERM', '') else TerminalFormatter) diff --git a/setup.py b/setup.py index e1ef6381..b7d0337c 100644 --- a/setup.py +++ b/setup.py @@ -36,10 +36,9 @@ setup( 'Programming Language :: Python', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', - # TODO: Python 3 - # 'Programming Language :: Python :: 3.1' - # 'Programming Language :: Python :: 3.2' - # 'Programming Language :: Python :: 3.3' + 'Programming Language :: Python :: 3.1' + 'Programming Language :: Python :: 3.2' + 'Programming Language :: Python :: 3.3' 'Environment :: Console', 'Intended Audience :: Developers', 'Intended Audience :: System Administrators', diff --git a/tests/tests.py b/tests/tests.py index 98c290e8..a8504760 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,9 +1,10 @@ -# coding:utf8 +# coding:utf-8 import os import sys import unittest import argparse -from StringIO import StringIO +from requests.compat import StringIO, is_py26, str + TESTS_ROOT = os.path.dirname(__file__) sys.path.insert(0, os.path.realpath(os.path.join(TESTS_ROOT, '..'))) @@ -12,9 +13,7 @@ from httpie import cli TEST_FILE = os.path.join(TESTS_ROOT, 'file.txt') - - -TERMINAL_COLOR_CHECK = '\x1b[' +TERMINAL_COLOR_PRESENCE_CHECK = '\x1b[' def http(*args, **kwargs): @@ -30,7 +29,7 @@ def http(*args, **kwargs): class BaseTest(unittest.TestCase): - if sys.version < (2, 7): + if is_py26: def assertIn(self, member, container, msg=None): self.assert_(member in container, msg) @@ -88,6 +87,10 @@ class TestHTTPie(BaseTest): def test_get(self): http('GET', 'http://httpbin.org/get') + def test_verbose(self): + r = http('--verbose', 'GET', 'http://httpbin.org/get', 'test-header:__test__') + self.assertEqual(r.count('__test__'), 2) + def test_json(self): response = http('POST', 'http://httpbin.org/post', 'foo=bar') self.assertIn('"foo": "bar"', response) @@ -107,19 +110,19 @@ class TestPrettyFlag(BaseTest): def test_pretty_enabled_by_default(self): r = http('GET', 'http://httpbin.org/get', stdout_isatty=True) - self.assertIn(TERMINAL_COLOR_CHECK, r) + self.assertIn(TERMINAL_COLOR_PRESENCE_CHECK, r) def test_pretty_enabled_by_default_unless_stdin_redirected(self): r = http('GET', 'http://httpbin.org/get', stdout_isatty=False) - self.assertNotIn(TERMINAL_COLOR_CHECK, r) + self.assertNotIn(TERMINAL_COLOR_PRESENCE_CHECK, r) def test_force_pretty(self): r = http('--pretty', 'GET', 'http://httpbin.org/get', stdout_isatty=False) - self.assertIn(TERMINAL_COLOR_CHECK, r) + self.assertIn(TERMINAL_COLOR_PRESENCE_CHECK, r) def test_force_ugly(self): r = http('--ugly', 'GET', 'http://httpbin.org/get', stdout_isatty=True) - self.assertNotIn(TERMINAL_COLOR_CHECK, r) + self.assertNotIn(TERMINAL_COLOR_PRESENCE_CHECK, r) class TestFileUpload(BaseTest):