diff --git a/httpie/input.py b/httpie/input.py index 1efa4f41..c05fa9b8 100644 --- a/httpie/input.py +++ b/httpie/input.py @@ -8,6 +8,7 @@ import json import mimetypes import getpass from io import BytesIO +from collections import namedtuple #noinspection PyCompatibility from argparse import ArgumentParser, ArgumentTypeError, ArgumentError @@ -560,6 +561,10 @@ class ParamDict(OrderedDict): self[key].append(value) +RequestItems = namedtuple('RequestItems', + ['headers', 'data', 'files', 'params']) + + def parse_items(items, data=None, headers=None, files=None, params=None): """Parse `KeyValue` `items` into `data`, `headers`, `files`, and `params`. @@ -617,7 +622,7 @@ def parse_items(items, data=None, headers=None, files=None, params=None): target[item.key] = value - return headers, data, files, params + return RequestItems(headers, data, files, params) def readable_file_arg(filename): diff --git a/setup.py b/setup.py index 3e2917c4..4e93a6d5 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,5 @@ +# This is purely the result of trial and error. + import sys import codecs @@ -26,7 +28,7 @@ class PyTest(TestCommand): tests_require = [ # Pytest needs to come last. - # + # https://bitbucket.org/pypa/setuptools/issue/196/ 'pytest-httpbin', 'pytest', ] @@ -36,15 +38,30 @@ install_requires = [ 'requests>=2.3.0', 'Pygments>=1.5' ] -try: - #noinspection PyUnresolvedReferences - import argparse -except ImportError: - install_requires.append('argparse>=1.2.1') -if 'win32' in str(sys.platform).lower(): - # Terminal colors for Windows - install_requires.append('colorama>=0.2.4') +### Conditional dependencies: + +# sdist +if not 'bdist_wheel' in sys.argv: + try: + #noinspection PyUnresolvedReferences + import argparse + except ImportError: + install_requires.append('argparse>=1.2.1') + + if 'win32' in str(sys.platform).lower(): + # Terminal colors for Windows + install_requires.append('colorama>=0.2.4') + + +# bdist_wheel +extras_require = { + # http://wheel.readthedocs.org/en/latest/#defining-conditional-dependencies + ':python_version == "2.6"' + ' or python_version == "3.0"' + ' or python_version == "3.1" ': ['argparse>=1.2.1'], + ':sys_platform == "win32"': ['colorama>=0.2.4'], +} def long_description(): @@ -67,6 +84,7 @@ setup( 'http = httpie.__main__:main', ], }, + extras_require=extras_require, install_requires=install_requires, tests_require=tests_require, cmdclass={'test': PyTest}, diff --git a/tests/test_cli.py b/tests/test_cli.py index 103d9543..f8009153 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -27,32 +27,32 @@ class TestItemParsing: self.key_value_type, item) def test_escape(self): - headers, data, files, params = input.parse_items([ + items = input.parse_items([ # headers - self.key_value_type('foo\\:bar:baz'), - self.key_value_type('jack\\@jill:hill'), + self.key_value_type(r'foo\:bar:baz'), + self.key_value_type(r'jack\@jill:hill'), # data - self.key_value_type('baz\\=bar=foo'), + self.key_value_type(r'baz\=bar=foo'), # files - self.key_value_type('bar\\@baz@%s' % FILE_PATH_ARG) + self.key_value_type(r'bar\@baz@%s' % FILE_PATH_ARG) ]) # `requests.structures.CaseInsensitiveDict` => `dict` - headers = dict(headers._store.values()) + headers = dict(items.headers._store.values()) assert headers == { 'foo:bar': 'baz', 'jack@jill': 'hill', } - assert data == {'baz=bar': 'foo'} - assert 'bar@baz' in files + assert items.data == {'baz=bar': 'foo'} + assert 'bar@baz' in items.files def test_escape_longsep(self): - headers, data, files, params = input.parse_items([ - self.key_value_type('bob\\:==foo'), + items = input.parse_items([ + self.key_value_type(r'bob\:==foo'), ]) - assert params == {'bob:': 'foo'} + assert items.params == {'bob:': 'foo'} def test_valid_items(self): - headers, data, files, params = input.parse_items([ + items = input.parse_items([ self.key_value_type('string=value'), self.key_value_type('header:value'), self.key_value_type('list:=["a", 1, {}, false]'), @@ -68,14 +68,14 @@ class TestItemParsing: # Parsed headers # `requests.structures.CaseInsensitiveDict` => `dict` - headers = dict(headers._store.values()) + headers = dict(items.headers._store.values()) assert headers == {'header': 'value', 'eh': ''} # Parsed data - raw_json_embed = data.pop('raw-json-embed') + raw_json_embed = items.data.pop('raw-json-embed') assert raw_json_embed == json.loads(JSON_FILE_CONTENT) - data['string-embed'] = data['string-embed'].strip() - assert dict(data) == { + items.data['string-embed'] = items.data['string-embed'].strip() + assert dict(items.data) == { "ed": "", "string": "value", "bool": True, @@ -85,11 +85,12 @@ class TestItemParsing: } # Parsed query string parameters - assert params == {'query': 'value'} + assert items.params == {'query': 'value'} # Parsed file fields - assert 'file' in files - assert files['file'][1].read().strip().decode('utf8') == FILE_CONTENT + assert 'file' in items.files + assert (items.files['file'][1].read().strip().decode('utf8') + == FILE_CONTENT) class TestQuerystring: