You've already forked httpie-cli
							
							
				mirror of
				https://github.com/httpie/cli.git
				synced 2025-10-30 23:47:52 +02:00 
			
		
		
		
	| @@ -5,8 +5,6 @@ python: | |||||||
|   - pypy |   - pypy | ||||||
|   - 3.1 |   - 3.1 | ||||||
|   - 3.2 |   - 3.2 | ||||||
| script: python tests/tests.py | script: python setup.py test | ||||||
| install: | install: | ||||||
|   - pip install requests pygments |   - pip install . --use-mirrors | ||||||
|   - "if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]] || [[ $TRAVIS_PYTHON_VERSION == '3.1' ]]; then pip install argparse; fi" |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								README.rst
									
									
									
									
									
								
							| @@ -104,28 +104,28 @@ Flags | |||||||
| Most of the flags mirror the arguments understood by ``requests.request``. See ``http -h`` for more details:: | Most of the flags mirror the arguments understood by ``requests.request``. See ``http -h`` for more details:: | ||||||
|  |  | ||||||
|     usage: http [-h] [--version] [--json | --form] [--traceback] |     usage: http [-h] [--version] [--json | --form] [--traceback] | ||||||
|                        [--pretty | --ugly] |                 [--pretty | --ugly] | ||||||
|                        [--print OUTPUT_OPTIONS | --verbose | --headers | --body] |                 [--print OUTPUT_OPTIONS | --verbose | --headers | --body] | ||||||
|                        [--style STYLE] [--auth AUTH] [--auth-type {basic,digest}] |                 [--style STYLE] [--auth AUTH] [--auth-type {basic,digest}] | ||||||
|                        [--verify VERIFY] [--proxy PROXY] [--allow-redirects] |                 [--verify VERIFY] [--proxy PROXY] [--allow-redirects] | ||||||
|                        [--timeout TIMEOUT] |                 [--timeout TIMEOUT] | ||||||
|                        [METHOD] URL [ITEM [ITEM ...]] |                 [METHOD] URL [ITEM [ITEM ...]] | ||||||
|  |  | ||||||
|     HTTPie - cURL for humans. <http://httpie.org> |     HTTPie - cURL for humans. <http://httpie.org> | ||||||
|  |  | ||||||
|     positional arguments: |     positional arguments: | ||||||
|       METHOD                The HTTP method to be used for the request (GET, POST, |       METHOD                The HTTP method to be used for the request (GET, POST, | ||||||
|                             PUT, DELETE, PATCH, ...). If this argument is omitted |                             PUT, DELETE, PATCH, ...). If this argument is omitted, | ||||||
|                             then httpie will guess HTTP method. If there is either |                             then HTTPie will guess the HTTP method. If there is | ||||||
|                             simple data field or JSON data field or file field |                             some data to be sent, then it will be POST, otherwise | ||||||
|                             presents then method is POST otherwise it is GET. |                             GET. | ||||||
|       URL                   The protocol defaults to http:// if the URL does not |       URL                   The protocol defaults to http:// if the URL does not | ||||||
|                             include one. |                             include one. | ||||||
|       ITEM                  A key-value pair whose type is defined by the |       ITEM                  A key-value pair whose type is defined by the | ||||||
|                             separator used. It can be an HTTP header |                             separator used. It can be an HTTP header | ||||||
|                             (header:value), a data field to be used in the request |                             (header:value), a data field to be used in the request | ||||||
|                             body (field_name=value), a raw JSON data field |                             body (field_name=value), a raw JSON data field | ||||||
|                             (field_name:=value) or a file field |                             (field_name:=value), or a file field | ||||||
|                             (field_name@/path/to/file). You can use a backslash to |                             (field_name@/path/to/file). You can use a backslash to | ||||||
|                             escape a colliding separator in the field name. |                             escape a colliding separator in the field name. | ||||||
|  |  | ||||||
| @@ -159,12 +159,12 @@ Most of the flags mirror the arguments understood by ``requests.request``. See ` | |||||||
|       --style STYLE, -s STYLE |       --style STYLE, -s STYLE | ||||||
|                             Output coloring style, one of autumn, borland, bw, |                             Output coloring style, one of autumn, borland, bw, | ||||||
|                             colorful, default, emacs, friendly, fruity, manni, |                             colorful, default, emacs, friendly, fruity, manni, | ||||||
|                             monokai, murphy, native, pastie, perldoc, solarized, |                             monokai, murphy, native, pastie, perldoc, rrt, | ||||||
|                             tango, trac, vim, vs. Defaults to solarized. For this |                             solarized, tango, trac, vim, vs. Defaults to | ||||||
|                             option to work properly, please make sure that the |                             solarized. For this option to work properly, please | ||||||
|                             $TERM environment variable is set to "xterm-256color" |                             make sure that the $TERM environment variable is set | ||||||
|                             or similar (e.g., via `export TERM=xterm-256color' in |                             to "xterm-256color" or similar (e.g., via `export TERM | ||||||
|                             your ~/.bashrc). |                             =xterm-256color' in your ~/.bashrc). | ||||||
|       --auth AUTH, -a AUTH  username:password |       --auth AUTH, -a AUTH  username:password | ||||||
|       --auth-type {basic,digest} |       --auth-type {basic,digest} | ||||||
|                             The authentication mechanism to be used. Defaults to |                             The authentication mechanism to be used. Defaults to | ||||||
| @@ -189,7 +189,7 @@ Contribute | |||||||
|  |  | ||||||
| If you have found a bug or have a feature request, the `issue tracker <https://github.com/jkbr/httpie/issues?state=open>`_ is the place to start a discussion about it. | If you have found a bug or have a feature request, the `issue tracker <https://github.com/jkbr/httpie/issues?state=open>`_ is the place to start a discussion about it. | ||||||
|  |  | ||||||
| To contribute code or documentation, please first browse the exsiting issues to see if the feature/bug has previously been discussed. Then fork `the repository <https://github.com/jkbr/httpie>`_, make changes in your develop branch and submit a pull request. Note: Pull requests with tests and documentation are 53.6%  more awesome :) | To contribute code or documentation, please first browse the existing issues to see if the feature/bug has previously been discussed. Then fork `the repository <https://github.com/jkbr/httpie>`_, make changes in your develop branch and submit a pull request. Note: Pull requests with tests and documentation are 53.6%  more awesome :) | ||||||
|  |  | ||||||
| Before a pull requests is submitted, it's a good idea to run the existing suite of tests:: | Before a pull requests is submitted, it's a good idea to run the existing suite of tests:: | ||||||
|  |  | ||||||
| @@ -206,7 +206,9 @@ Before a pull requests is submitted, it's a good idea to run the existing suite | |||||||
| Changelog | Changelog | ||||||
| --------- | --------- | ||||||
|  |  | ||||||
| * `New in development version <https://github.com/jkbr/httpie/compare/0.2.1...master>`_ | * `0.2.2dev <https://github.com/jkbr/httpie/compare/0.2.1...master>`_ | ||||||
|  |     * The ``METHOD`` positional argument can now be omitted (defaults to ``GET``, or to ``POST`` with data). | ||||||
|  |     * Fixed --verbose --form. | ||||||
| * `0.2.1 <https://github.com/jkbr/httpie/compare/0.2.0...0.2.1>`_ (2012-06-13) | * `0.2.1 <https://github.com/jkbr/httpie/compare/0.2.0...0.2.1>`_ (2012-06-13) | ||||||
|     * Added compatibility with ``requests-0.12.1``. |     * Added compatibility with ``requests-0.12.1``. | ||||||
|     * Dropped custom JSON and HTTP lexers in favor of the ones newly included in ``pygments-1.5``. |     * Dropped custom JSON and HTTP lexers in favor of the ones newly included in ``pygments-1.5``. | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ def _(text): | |||||||
|  |  | ||||||
|  |  | ||||||
| desc = '%s <http://httpie.org>' | desc = '%s <http://httpie.org>' | ||||||
| parser = cliparse.HTTPieArgumentParser(description=desc % __doc__.strip(),) | parser = cliparse.Parser(description=desc % __doc__.strip(),) | ||||||
| parser.add_argument('--version', action='version', version=__version__) | parser.add_argument('--version', action='version', version=__version__) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -176,8 +176,8 @@ parser.add_argument( | |||||||
|     help=_(''' |     help=_(''' | ||||||
|         The HTTP method to be used for the request |         The HTTP method to be used for the request | ||||||
|         (GET, POST, PUT, DELETE, PATCH, ...). |         (GET, POST, PUT, DELETE, PATCH, ...). | ||||||
|         If this argument is omitted then httpie will guess the HTTP method. |         If this argument is omitted, then HTTPie will guess the HTTP method. | ||||||
|         If there is any data to be sent then method is POST otherwise it is GET. |         If there is some data to be sent, then it will be POST, otherwise GET. | ||||||
|     ''') |     ''') | ||||||
| ) | ) | ||||||
| parser.add_argument( | parser.add_argument( | ||||||
| @@ -200,7 +200,7 @@ parser.add_argument( | |||||||
|         A key-value pair whose type is defined by the separator used. It can be an |         A key-value pair whose type is defined by the separator used. It can be an | ||||||
|         HTTP header (header:value), |         HTTP header (header:value), | ||||||
|         a data field to be used in the request body (field_name=value), |         a data field to be used in the request body (field_name=value), | ||||||
|         a raw JSON data field (field_name:=value) |         a raw JSON data field (field_name:=value), | ||||||
|         or a file field (field_name@/path/to/file). |         or a file field (field_name@/path/to/file). | ||||||
|         You can use a backslash to escape a colliding separator in the field name. |         You can use a backslash to escape a colliding separator in the field name. | ||||||
|     ''') |     ''') | ||||||
|   | |||||||
| @@ -25,11 +25,11 @@ SEP_HEADERS = SEP_COMMON | |||||||
| SEP_DATA = '=' | SEP_DATA = '=' | ||||||
| SEP_DATA_RAW_JSON = ':=' | SEP_DATA_RAW_JSON = ':=' | ||||||
| SEP_FILES = '@' | SEP_FILES = '@' | ||||||
| DATA_ITEM_SEPARATORS = { | DATA_ITEM_SEPARATORS = [ | ||||||
|     SEP_DATA, |     SEP_DATA, | ||||||
|     SEP_DATA_RAW_JSON, |     SEP_DATA_RAW_JSON, | ||||||
|     SEP_FILES |     SEP_FILES | ||||||
| } | ] | ||||||
|  |  | ||||||
|  |  | ||||||
| OUT_REQ_HEADERS = 'H' | OUT_REQ_HEADERS = 'H' | ||||||
| @@ -47,12 +47,12 @@ PRETTIFY_STDOUT_TTY_ONLY = object() | |||||||
| DEFAULT_UA = 'HTTPie/%s' % __version__ | DEFAULT_UA = 'HTTPie/%s' % __version__ | ||||||
|  |  | ||||||
|  |  | ||||||
| class HTTPieArgumentParser(argparse.ArgumentParser): | class Parser(argparse.ArgumentParser): | ||||||
|  |  | ||||||
|     def parse_args(self, args=None, namespace=None, |     def parse_args(self, args=None, namespace=None, | ||||||
|                    stdin=sys.stdin, |                    stdin=sys.stdin, | ||||||
|                    stdin_isatty=sys.stdin.isatty()): |                    stdin_isatty=sys.stdin.isatty()): | ||||||
|         args = super(HTTPieArgumentParser, self).parse_args(args, namespace) |         args = super(Parser, self).parse_args(args, namespace) | ||||||
|         self._validate_output_options(args) |         self._validate_output_options(args) | ||||||
|         self._validate_auth_options(args) |         self._validate_auth_options(args) | ||||||
|         self._guess_method(args, stdin_isatty) |         self._guess_method(args, stdin_isatty) | ||||||
| @@ -68,28 +68,9 @@ class HTTPieArgumentParser(argparse.ArgumentParser): | |||||||
|         args.data = stdin.read() |         args.data = stdin.read() | ||||||
|  |  | ||||||
|     def _guess_method(self, args, stdin_isatty=sys.stdin.isatty()): |     def _guess_method(self, args, stdin_isatty=sys.stdin.isatty()): | ||||||
|         """Suggests HTTP method by positional argument values. |         """ | ||||||
|  |         Set `args.method`, if not specified, to either POST or GET | ||||||
|         In following description by data item it means one of: |         based on whether the request has data or not. | ||||||
|         * simple data item (key=value) |  | ||||||
|         * JSON raw item (key:=value) |  | ||||||
|         * file item (key@value) |  | ||||||
|  |  | ||||||
|         If METHOD argument is omitted and no data ITEM is given then method is GET: |  | ||||||
|         http http://example.com/ |  | ||||||
|             - is shortcut for - |  | ||||||
|         http GET http://example.com. |  | ||||||
|  |  | ||||||
|         If METHOD argument is omitted but at least one data ITEM |  | ||||||
|         is present then method is POST: |  | ||||||
|         http http://example.com/ hello=world |  | ||||||
|             - is shortcut for - |  | ||||||
|         http POST http://example.com hello=world. |  | ||||||
|  |  | ||||||
|         If METHOD is specified then http behaves as it is now. |  | ||||||
|  |  | ||||||
|         The first argument should be treated as method |  | ||||||
|         if it matches ^[a-zA-Z]+$ regexp. Otherwise it is url. |  | ||||||
|  |  | ||||||
|         """ |         """ | ||||||
|         if args.method is None: |         if args.method is None: | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								setup.py
									
									
									
									
									
								
							| @@ -5,12 +5,14 @@ import httpie | |||||||
|  |  | ||||||
|  |  | ||||||
| if sys.argv[-1] == 'test': | if sys.argv[-1] == 'test': | ||||||
|     os.system('python tests/tests.py') |     sys.exit(os.system('python tests/tests.py')) | ||||||
|     sys.exit() |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Debian has only requests==0.10.1 and httpie.deb depends on that. | requirements = [ | ||||||
| requirements = ['requests>=0.10.1', 'Pygments>=1.5'] |     # Debian has only requests==0.10.1 and httpie.deb depends on that. | ||||||
|  |     'requests>=0.10.1', | ||||||
|  |     'Pygments>=1.5' | ||||||
|  | ] | ||||||
| if sys.version_info[:2] in ((2, 6), (3, 1)): | if sys.version_info[:2] in ((2, 6), (3, 1)): | ||||||
|     # argparse has been added in Python 3.2 / 2.7 |     # argparse has been added in Python 3.2 / 2.7 | ||||||
|     requirements.append('argparse>=1.2.1') |     requirements.append('argparse>=1.2.1') | ||||||
|   | |||||||
| @@ -1,75 +0,0 @@ | |||||||
| import unittest |  | ||||||
| from argparse import Namespace |  | ||||||
| from httpie.cliparse import HTTPieArgumentParser, KeyValue |  | ||||||
|  |  | ||||||
|  |  | ||||||
| __author__ = 'vladimir' |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class HTTPieArgumentParserTestCase(unittest.TestCase): |  | ||||||
|  |  | ||||||
|     def setUp(self): |  | ||||||
|         self.HTTPieArgumentParserStub = type(HTTPieArgumentParser.__name__, (HTTPieArgumentParser,), {}) |  | ||||||
|         self.HTTPieArgumentParserStub.__init__ = lambda self: None |  | ||||||
|         self.parser = HTTPieArgumentParser() |  | ||||||
|  |  | ||||||
|     def test_guess_when_method_set_and_valid(self): |  | ||||||
|         args = Namespace() |  | ||||||
|         args.method = 'GET' |  | ||||||
|         args.url = 'http://example.com/' |  | ||||||
|         args.items = [] |  | ||||||
|  |  | ||||||
|         self.parser._guess_method(args) |  | ||||||
|  |  | ||||||
|         self.assertEquals(args.method, 'GET') |  | ||||||
|         self.assertEquals(args.url, 'http://example.com/') |  | ||||||
|         self.assertEquals(args.items, []) |  | ||||||
|  |  | ||||||
|     def test_guess_when_method_not_set(self): |  | ||||||
|         args = Namespace() |  | ||||||
|         args.method = None |  | ||||||
|         args.url = 'http://example.com/' |  | ||||||
|         args.items = [] |  | ||||||
|  |  | ||||||
|         self.parser._guess_method(args) |  | ||||||
|  |  | ||||||
|         self.assertEquals(args.method, 'GET') |  | ||||||
|         self.assertEquals(args.url, 'http://example.com/') |  | ||||||
|         self.assertEquals(args.items, []) |  | ||||||
|  |  | ||||||
|     def test_guess_when_method_set_but_invalid_and_data_field(self): |  | ||||||
|         args = Namespace() |  | ||||||
|         args.method = 'http://example.com/' |  | ||||||
|         args.url = 'data=field' |  | ||||||
|         args.items = [] |  | ||||||
|  |  | ||||||
|         self.parser._guess_method(args) |  | ||||||
|  |  | ||||||
|         self.assertEquals(args.method, 'POST') |  | ||||||
|         self.assertEquals(args.url, 'http://example.com/') |  | ||||||
|         self.assertEquals(args.items, [KeyValue(key='data', value='field', sep='=', orig='data=field')]) |  | ||||||
|  |  | ||||||
|     def test_guess_when_method_set_but_invalid_and_header_field(self): |  | ||||||
|         args = Namespace() |  | ||||||
|         args.method = 'http://example.com/' |  | ||||||
|         args.url = 'test:header' |  | ||||||
|         args.items = [] |  | ||||||
|  |  | ||||||
|         self.parser._guess_method(args) |  | ||||||
|  |  | ||||||
|         self.assertEquals(args.method, 'GET') |  | ||||||
|         self.assertEquals(args.url, 'http://example.com/') |  | ||||||
|         self.assertEquals(args.items, [KeyValue(key='test', value='header', sep=':', orig='test:header')]) |  | ||||||
|  |  | ||||||
|     def test_guess_when_method_set_but_invalid_and_item_exists(self): |  | ||||||
|         args = Namespace() |  | ||||||
|         args.method = 'http://example.com/' |  | ||||||
|         args.url = 'new_item=a' |  | ||||||
|         args.items = [KeyValue(key='old_item', value='b', sep='=', orig='old_item=b')] |  | ||||||
|  |  | ||||||
|         self.parser._guess_method(args) |  | ||||||
|  |  | ||||||
|         self.assertEquals(args.items, [ |  | ||||||
|             KeyValue(key='new_item', value='a', sep='=', orig='new_item=a'), |  | ||||||
|             KeyValue(key='old_item', value='b', sep='=', orig='old_item=b'), |  | ||||||
|         ]) |  | ||||||
							
								
								
									
										321
									
								
								tests/tests.py
									
									
									
									
									
								
							
							
						
						
									
										321
									
								
								tests/tests.py
									
									
									
									
									
								
							| @@ -1,24 +1,36 @@ | |||||||
| # coding:utf-8 | """ | ||||||
| import os | High-level tests. | ||||||
| import sys |  | ||||||
|  | """ | ||||||
| import unittest | import unittest | ||||||
| import argparse | import argparse | ||||||
| from requests.compat import is_py26 | import os | ||||||
|  | import sys | ||||||
| import tempfile | import tempfile | ||||||
|  | from requests.compat import is_py26 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ################################################################# | ||||||
|  | # Utils/setup | ||||||
|  | ################################################################# | ||||||
|  |  | ||||||
|  | # HACK: Prepend ../ to PYTHONPATH so that we can import httpie form there. | ||||||
| TESTS_ROOT = os.path.dirname(__file__) | TESTS_ROOT = os.path.dirname(__file__) | ||||||
| sys.path.insert(0, os.path.realpath(os.path.join(TESTS_ROOT, '..'))) | sys.path.insert(0, os.path.realpath(os.path.join(TESTS_ROOT, '..'))) | ||||||
|  |  | ||||||
| from httpie import __main__ | from httpie import __main__, cliparse | ||||||
| from httpie import cliparse |  | ||||||
|  |  | ||||||
|  |  | ||||||
| TEST_FILE = os.path.join(TESTS_ROOT, 'file.txt') | TEST_FILE_PATH = os.path.join(TESTS_ROOT, 'file.txt') | ||||||
| TERMINAL_COLOR_PRESENCE_CHECK = '\x1b[' | TERMINAL_COLOR_PRESENCE_CHECK = '\x1b[' | ||||||
|  |  | ||||||
|  |  | ||||||
| def http(*args, **kwargs): | def http(*args, **kwargs): | ||||||
|  |     """ | ||||||
|  |     Invoke `httpie.__main__.main` with `args` and `kwargs`, | ||||||
|  |     and return a unicode response. | ||||||
|  |  | ||||||
|  |     """ | ||||||
|     http_kwargs = { |     http_kwargs = { | ||||||
|         'stdin_isatty': True, |         'stdin_isatty': True, | ||||||
|         'stdout_isatty': False |         'stdout_isatty': False | ||||||
| @@ -32,7 +44,7 @@ def http(*args, **kwargs): | |||||||
|     return response |     return response | ||||||
|  |  | ||||||
|  |  | ||||||
| class BaseTest(unittest.TestCase): | class BaseTestCase(unittest.TestCase): | ||||||
|  |  | ||||||
|     if is_py26: |     if is_py26: | ||||||
|         def assertIn(self, member, container, msg=None): |         def assertIn(self, member, container, msg=None): | ||||||
| @@ -46,7 +58,149 @@ class BaseTest(unittest.TestCase): | |||||||
|             self.assertEqual(sorted(d1.values()), sorted(d2.values()), msg) |             self.assertEqual(sorted(d1.values()), sorted(d2.values()), msg) | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestItemParsing(BaseTest): | ################################################################# | ||||||
|  | # High-level tests using httpbin.org. | ||||||
|  | ################################################################# | ||||||
|  |  | ||||||
|  | class HTTPieTest(BaseTestCase): | ||||||
|  |  | ||||||
|  |     def test_GET(self): | ||||||
|  |         r = http('GET', 'http://httpbin.org/get') | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |  | ||||||
|  |     def test_DELETE(self): | ||||||
|  |         r = http('DELETE', 'http://httpbin.org/delete') | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |  | ||||||
|  |     def test_PUT(self): | ||||||
|  |         r = http('PUT', 'http://httpbin.org/put', 'foo=bar') | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |         self.assertIn('"foo": "bar"', r) | ||||||
|  |  | ||||||
|  |     def test_POST_JSON_data(self): | ||||||
|  |         r = http('POST', 'http://httpbin.org/post', 'foo=bar') | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |         self.assertIn('"foo": "bar"', r) | ||||||
|  |  | ||||||
|  |     def test_GET_JSON_implicit_accept(self): | ||||||
|  |         r = http('-j', 'GET', 'http://httpbin.org/headers') | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |         self.assertIn('"Accept": "application/json"', r) | ||||||
|  |  | ||||||
|  |     def test_GET_JSON_explicit_accept(self): | ||||||
|  |         r = http('-j', 'GET', 'http://httpbin.org/headers', 'Accept:application/xml') | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |         self.assertIn('"Accept": "application/xml"', r) | ||||||
|  |  | ||||||
|  |     def test_POST_form(self): | ||||||
|  |         response = http('--form', 'POST', 'http://httpbin.org/post', 'foo=bar') | ||||||
|  |         self.assertIn('"foo": "bar"', response) | ||||||
|  |  | ||||||
|  |     def test_POST_stdin(self): | ||||||
|  |         r = http('--form', 'POST', 'http://httpbin.org/post', | ||||||
|  |                  stdin=open(TEST_FILE_PATH), stdin_isatty=False) | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |  | ||||||
|  |     def test_headers(self): | ||||||
|  |         response = http('GET', 'http://httpbin.org/headers', 'Foo:bar') | ||||||
|  |         self.assertIn('"User-Agent": "HTTPie', response) | ||||||
|  |         self.assertIn('"Foo": "bar"', response) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ImplicitHTTPMethodTest(BaseTestCase): | ||||||
|  |  | ||||||
|  |     def test_implicit_GET(self): | ||||||
|  |         r = http('http://httpbin.org/get') | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |  | ||||||
|  |     def test_implicit_GET_with_headers(self): | ||||||
|  |         r = http('http://httpbin.org/headers', 'Foo:bar') | ||||||
|  |         self.assertIn('"Foo": "bar"', r) | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |  | ||||||
|  |     def test_implicit_POST_json(self): | ||||||
|  |         r = http('http://httpbin.org/post', 'hello=world') | ||||||
|  |         self.assertIn('"hello": "world"', r) | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |  | ||||||
|  |     def test_implicit_POST_form(self): | ||||||
|  |         r = http('--form', 'http://httpbin.org/post', 'foo=bar') | ||||||
|  |         self.assertIn('"foo": "bar"', r) | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |  | ||||||
|  |     def test_implicit_POST_stdin(self): | ||||||
|  |         r = http('--form', 'http://httpbin.org/post', | ||||||
|  |                  stdin=open(TEST_FILE_PATH), stdin_isatty=False) | ||||||
|  |         self.assertIn('HTTP/1.1 200', r) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class PrettyFlagTest(BaseTestCase): | ||||||
|  |     """Test the --pretty / --ugly flag handling.""" | ||||||
|  |  | ||||||
|  |     def test_pretty_enabled_by_default(self): | ||||||
|  |         r = http('GET', 'http://httpbin.org/get', stdout_isatty=True) | ||||||
|  |         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_PRESENCE_CHECK, r) | ||||||
|  |  | ||||||
|  |     def test_force_pretty(self): | ||||||
|  |         r = http('--pretty', 'GET', 'http://httpbin.org/get', stdout_isatty=False) | ||||||
|  |         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_PRESENCE_CHECK, r) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class VerboseFlagTest(BaseTestCase): | ||||||
|  |  | ||||||
|  |     def test_verbose(self): | ||||||
|  |         r = http('--verbose', 'GET', 'http://httpbin.org/get', 'test-header:__test__') | ||||||
|  |         self.assertEqual(r.count('__test__'), 2) | ||||||
|  |  | ||||||
|  |     def test_verbose_form(self): | ||||||
|  |         # https://github.com/jkbr/httpie/issues/53 | ||||||
|  |         r = http('--verbose', '--form', 'POST', 'http://httpbin.org/post', 'foo=bar', 'baz=bar') | ||||||
|  |         self.assertIn('foo=bar&baz=bar', r) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class MultipartFormDataFileUploadTest(BaseTestCase): | ||||||
|  |  | ||||||
|  |     def test_non_existent_file_raises_parse_error(self): | ||||||
|  |         self.assertRaises(cliparse.ParseError, http, | ||||||
|  |             '--form', '--traceback', | ||||||
|  |             'POST', 'http://httpbin.org/post', | ||||||
|  |             'foo@/__does_not_exist__') | ||||||
|  |  | ||||||
|  |     def test_upload_ok(self): | ||||||
|  |         r = http('--form', 'POST', 'http://httpbin.org/post', | ||||||
|  |              'test-file@%s' % TEST_FILE_PATH, 'foo=bar') | ||||||
|  |         self.assertIn('"test-file": "__test_file_content__', r) | ||||||
|  |         self.assertIn('"foo": "bar"', r) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthTest(BaseTestCase): | ||||||
|  |  | ||||||
|  |     def test_basic_auth(self): | ||||||
|  |         r = http('--auth', 'user:password', | ||||||
|  |                  'GET', 'httpbin.org/basic-auth/user/password') | ||||||
|  |         self.assertIn('"authenticated": true', r) | ||||||
|  |         self.assertIn('"user": "user"', r) | ||||||
|  |  | ||||||
|  |     def test_digest_auth(self): | ||||||
|  |         r = http('--auth-type=digest', '--auth', 'user:password', | ||||||
|  |                  'GET', 'httpbin.org/digest-auth/auth/user/password') | ||||||
|  |         self.assertIn('"authenticated": true', r) | ||||||
|  |         self.assertIn('"user": "user"', r) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ################################################################# | ||||||
|  | # CLI argument parsing related tests. | ||||||
|  | ################################################################# | ||||||
|  |  | ||||||
|  | class ItemParsingTest(BaseTestCase): | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         self.key_value_type = cliparse.KeyValueType( |         self.key_value_type = cliparse.KeyValueType( | ||||||
| @@ -70,7 +224,7 @@ class TestItemParsing(BaseTest): | |||||||
|             # data |             # data | ||||||
|             self.key_value_type('baz\\=bar=foo'), |             self.key_value_type('baz\\=bar=foo'), | ||||||
|             # files |             # files | ||||||
|             self.key_value_type('bar\\@baz@%s' % TEST_FILE) |             self.key_value_type('bar\\@baz@%s' % TEST_FILE_PATH) | ||||||
|         ]) |         ]) | ||||||
|         self.assertDictEqual(headers, { |         self.assertDictEqual(headers, { | ||||||
|             'foo:bar': 'baz', |             'foo:bar': 'baz', | ||||||
| @@ -98,7 +252,7 @@ class TestItemParsing(BaseTest): | |||||||
|             self.key_value_type('eh:'), |             self.key_value_type('eh:'), | ||||||
|             self.key_value_type('ed='), |             self.key_value_type('ed='), | ||||||
|             self.key_value_type('bool:=true'), |             self.key_value_type('bool:=true'), | ||||||
|             self.key_value_type('test-file@%s' % TEST_FILE), |             self.key_value_type('test-file@%s' % TEST_FILE_PATH), | ||||||
|         ]) |         ]) | ||||||
|         self.assertDictEqual(headers, { |         self.assertDictEqual(headers, { | ||||||
|             'header': 'value', |             'header': 'value', | ||||||
| @@ -114,112 +268,77 @@ class TestItemParsing(BaseTest): | |||||||
|         self.assertIn('test-file', files) |         self.assertIn('test-file', files) | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestHTTPie(BaseTest): | class HTTPieArgumentParserTestCase(unittest.TestCase): | ||||||
|  |  | ||||||
|     def test_get(self): |     def setUp(self): | ||||||
|         http('GET', 'http://httpbin.org/get') |         self.parser = cliparse.Parser() | ||||||
|  |  | ||||||
|     def test_verbose(self): |     def test_guess_when_method_set_and_valid(self): | ||||||
|         r = http('--verbose', 'GET', 'http://httpbin.org/get', 'test-header:__test__') |         args = argparse.Namespace() | ||||||
|         self.assertEqual(r.count('__test__'), 2) |         args.method = 'GET' | ||||||
|  |         args.url = 'http://example.com/' | ||||||
|  |         args.items = [] | ||||||
|  |  | ||||||
|     def test_verbose_form(self): |         self.parser._guess_method(args) | ||||||
|         # https://github.com/jkbr/httpie/issues/53 |  | ||||||
|         r = http('--verbose', '--form', 'POST', 'http://httpbin.org/post', 'foo=bar', 'baz=bar') |  | ||||||
|         self.assertIn('foo=bar&baz=bar', r) |  | ||||||
|  |  | ||||||
|     def test_json(self): |         self.assertEquals(args.method, 'GET') | ||||||
|         response = http('POST', 'http://httpbin.org/post', 'foo=bar') |         self.assertEquals(args.url, 'http://example.com/') | ||||||
|         self.assertIn('"foo": "bar"', response) |         self.assertEquals(args.items, []) | ||||||
|         response2 = http('-j', 'GET', 'http://httpbin.org/headers') |  | ||||||
|         self.assertIn('"Accept": "application/json"', response2) |  | ||||||
|         response3 = http('-j', 'GET', 'http://httpbin.org/headers', 'Accept:application/xml') |  | ||||||
|         self.assertIn('"Accept": "application/xml"', response3) |  | ||||||
|  |  | ||||||
|     def test_form(self): |     def test_guess_when_method_not_set(self): | ||||||
|         response = http('--form', 'POST', 'http://httpbin.org/post', 'foo=bar') |         args = argparse.Namespace() | ||||||
|         self.assertIn('"foo": "bar"', response) |         args.method = None | ||||||
|  |         args.url = 'http://example.com/' | ||||||
|  |         args.items = [] | ||||||
|  |  | ||||||
|     def test_headers(self): |         self.parser._guess_method(args) | ||||||
|         response = http('GET', 'http://httpbin.org/headers', 'Foo:bar') |  | ||||||
|         self.assertIn('"User-Agent": "HTTPie', response) |  | ||||||
|         self.assertIn('"Foo": "bar"', response) |  | ||||||
|  |  | ||||||
|  |         self.assertEquals(args.method, 'GET') | ||||||
|  |         self.assertEquals(args.url, 'http://example.com/') | ||||||
|  |         self.assertEquals(args.items, []) | ||||||
|  |  | ||||||
| class TestImplicitHTTPMethod(BaseTest): |     def test_guess_when_method_set_but_invalid_and_data_field(self): | ||||||
|  |         args = argparse.Namespace() | ||||||
|  |         args.method = 'http://example.com/' | ||||||
|  |         args.url = 'data=field' | ||||||
|  |         args.items = [] | ||||||
|  |  | ||||||
|     def test_implicit_GET(self): |         self.parser._guess_method(args) | ||||||
|         r = http('http://httpbin.org/get') |  | ||||||
|         self.assertIn('HTTP/1.1 200', r) |  | ||||||
|  |  | ||||||
|     def test_implicit_GET_with_headers(self): |         self.assertEquals(args.method, 'POST') | ||||||
|         r = http('http://httpbin.org/headers', 'Foo:bar') |         self.assertEquals(args.url, 'http://example.com/') | ||||||
|         self.assertIn('"Foo": "bar"', r) |         self.assertEquals( | ||||||
|         self.assertIn('HTTP/1.1 200', r) |             args.items, | ||||||
|  |             [cliparse.KeyValue(key='data', value='field', sep='=', orig='data=field')]) | ||||||
|  |  | ||||||
|     def test_implicit_POST_json(self): |     def test_guess_when_method_set_but_invalid_and_header_field(self): | ||||||
|         r = http('http://httpbin.org/post', 'hello=world') |         args = argparse.Namespace() | ||||||
|         self.assertIn('"hello": "world"', r) |         args.method = 'http://example.com/' | ||||||
|         self.assertIn('HTTP/1.1 200', r) |         args.url = 'test:header' | ||||||
|  |         args.items = [] | ||||||
|  |  | ||||||
|     def test_implicit_POST_form(self): |         self.parser._guess_method(args) | ||||||
|         r = http('--form', 'http://httpbin.org/post', 'foo=bar') |  | ||||||
|         self.assertIn('"foo": "bar"', r) |  | ||||||
|         self.assertIn('HTTP/1.1 200', r) |  | ||||||
|  |  | ||||||
|     def test_implicit_POST_stdin(self): |         self.assertEquals(args.method, 'GET') | ||||||
|         r = http('--form', 'http://httpbin.org/post', |         self.assertEquals(args.url, 'http://example.com/') | ||||||
|                  stdin=open(TEST_FILE), stdin_isatty=False) |         self.assertEquals( | ||||||
|         self.assertIn('HTTP/1.1 200', r) |             args.items, | ||||||
|  |             [cliparse.KeyValue(key='test', value='header', sep=':', orig='test:header')]) | ||||||
|  |  | ||||||
|  |     def test_guess_when_method_set_but_invalid_and_item_exists(self): | ||||||
|  |         args = argparse.Namespace() | ||||||
|  |         args.method = 'http://example.com/' | ||||||
|  |         args.url = 'new_item=a' | ||||||
|  |         args.items = [ | ||||||
|  |             cliparse.KeyValue(key='old_item', value='b', sep='=', orig='old_item=b') | ||||||
|  |         ] | ||||||
|  |  | ||||||
| class TestPrettyFlag(BaseTest): |         self.parser._guess_method(args) | ||||||
|     """Test the --pretty / --ugly flag handling.""" |  | ||||||
|  |  | ||||||
|     def test_pretty_enabled_by_default(self): |         self.assertEquals(args.items, [ | ||||||
|         r = http('GET', 'http://httpbin.org/get', stdout_isatty=True) |             cliparse.KeyValue(key='new_item', value='a', sep='=', orig='new_item=a'), | ||||||
|         self.assertIn(TERMINAL_COLOR_PRESENCE_CHECK, r) |             cliparse.KeyValue(key='old_item', value='b', sep='=', orig='old_item=b'), | ||||||
|  |         ]) | ||||||
|     def test_pretty_enabled_by_default_unless_stdin_redirected(self): |  | ||||||
|         r = http('GET', 'http://httpbin.org/get', stdout_isatty=False) |  | ||||||
|         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_PRESENCE_CHECK, r) |  | ||||||
|  |  | ||||||
|     def test_force_ugly(self): |  | ||||||
|         r = http('--ugly', 'GET', 'http://httpbin.org/get', stdout_isatty=True) |  | ||||||
|         self.assertNotIn(TERMINAL_COLOR_PRESENCE_CHECK, r) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestFileUpload(BaseTest): |  | ||||||
|  |  | ||||||
|     def test_non_existent_file_raises_parse_error(self): |  | ||||||
|         self.assertRaises(cliparse.ParseError, http, |  | ||||||
|             '--form', '--traceback', |  | ||||||
|             'POST', 'http://httpbin.org/post', |  | ||||||
|             'foo@/__does_not_exist__') |  | ||||||
|  |  | ||||||
|     def test_upload_ok(self): |  | ||||||
|         r = http('--form', 'POST', 'http://httpbin.org/post', |  | ||||||
|              'test-file@%s' % TEST_FILE) |  | ||||||
|         self.assertIn('"test-file": "__test_file_content__', r) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestAuth(BaseTest): |  | ||||||
|  |  | ||||||
|     def test_basic_auth(self): |  | ||||||
|         r = http('--auth', 'user:password', |  | ||||||
|                  'GET', 'httpbin.org/basic-auth/user/password') |  | ||||||
|         self.assertIn('"authenticated": true', r) |  | ||||||
|         self.assertIn('"user": "user"', r) |  | ||||||
|  |  | ||||||
|     def test_digest_auth(self): |  | ||||||
|         r = http('--auth-type=digest', '--auth', 'user:password', |  | ||||||
|                  'GET', 'httpbin.org/digest-auth/auth/user/password') |  | ||||||
|         self.assertIn('"authenticated": true', r) |  | ||||||
|         self.assertIn('"user": "user"', r) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user