mirror of
https://github.com/httpie/cli.git
synced 2025-01-10 00:28:12 +02:00
Removed Python 2.6 support
* Travis CI doesn't support it anymore. * It had EOL more than 4 years ago
This commit is contained in:
parent
4d3b4fa0be
commit
ec899d70b7
@ -8,9 +8,12 @@ This project adheres to `Semantic Versioning <http://semver.org/>`_.
|
|||||||
|
|
||||||
`1.0.0-dev`_ (unreleased)
|
`1.0.0-dev`_ (unreleased)
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
* Removed Python 2.6 support.
|
||||||
* ``--verify`` now accepts ``true``/``false`` in addition to ``yes``/``no``
|
* ``--verify`` now accepts ``true``/``false`` in addition to ``yes``/``no``
|
||||||
and the boolean value is case-insensitive.
|
and the boolean value is case-insensitive.
|
||||||
|
|
||||||
|
|
||||||
`0.9.8`_ (2016-12-08)
|
`0.9.8`_ (2016-12-08)
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
10
README.rst
10
README.rst
@ -41,7 +41,7 @@ Main features
|
|||||||
* Custom headers
|
* Custom headers
|
||||||
* Persistent sessions
|
* Persistent sessions
|
||||||
* Wget-like downloads
|
* Wget-like downloads
|
||||||
* Python 2.6, 2.7 and 3.x support
|
* Python 2.7 and 3.x support
|
||||||
* Linux, macOS and Windows support
|
* Linux, macOS and Windows support
|
||||||
* Plugins
|
* Plugins
|
||||||
* Documentation
|
* Documentation
|
||||||
@ -119,10 +119,10 @@ and always provides the latest version) is to use `pip`_:
|
|||||||
Python version
|
Python version
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Although Python 2.6 and 2.7 are supported as well, it is recommended to install
|
Although Python 2.7 is supported as well, it is strongly recommended to
|
||||||
HTTPie against the latest Python 3.x whenever possible. That will ensure that
|
install HTTPie against the latest Python 3.x whenever possible. That will
|
||||||
some of the newer HTTP features, such as `SNI (Server Name Indication)`_,
|
ensure that some of the newer HTTP features, such as
|
||||||
work out of the box.
|
`SNI (Server Name Indication)`_, work out of the box.
|
||||||
Python 3 is the default for Homebrew installations starting with version 0.9.4.
|
Python 3 is the default for Homebrew installations starting with version 0.9.4.
|
||||||
To see which version HTTPie uses, run ``http --debug``.
|
To see which version HTTPie uses, run ``http --debug``.
|
||||||
|
|
||||||
|
141
httpie/compat.py
141
httpie/compat.py
@ -1,12 +1,11 @@
|
|||||||
"""
|
"""
|
||||||
Python 2.6, 2.7, and 3.x compatibility.
|
Python 2.7, and 3.x compatibility.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
is_py2 = sys.version_info[0] == 2
|
is_py2 = sys.version_info[0] == 2
|
||||||
is_py26 = sys.version_info[:2] == (2, 6)
|
|
||||||
is_py27 = sys.version_info[:2] == (2, 7)
|
is_py27 = sys.version_info[:2] == (2, 7)
|
||||||
is_py3 = sys.version_info[0] == 3
|
is_py3 = sys.version_info[0] == 3
|
||||||
is_pypy = 'pypy' in sys.version.lower()
|
is_pypy = 'pypy' in sys.version.lower()
|
||||||
@ -38,141 +37,3 @@ try: # pragma: no cover
|
|||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
# noinspection PyCompatibility,PyUnresolvedReferences
|
# noinspection PyCompatibility,PyUnresolvedReferences
|
||||||
from urllib2 import urlopen
|
from urllib2 import urlopen
|
||||||
|
|
||||||
try: # pragma: no cover
|
|
||||||
from collections import OrderedDict
|
|
||||||
except ImportError: # pragma: no cover
|
|
||||||
# Python 2.6 OrderedDict class, needed for headers, parameters, etc .###
|
|
||||||
# <https://pypi.python.org/pypi/ordereddict/1.1>
|
|
||||||
# noinspection PyCompatibility,PyUnresolvedReferences
|
|
||||||
from UserDict import DictMixin
|
|
||||||
|
|
||||||
# noinspection PyShadowingBuiltins,PyCompatibility
|
|
||||||
class OrderedDict(dict, DictMixin):
|
|
||||||
# Copyright (c) 2009 Raymond Hettinger
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person
|
|
||||||
# obtaining a copy of this software and associated documentation files
|
|
||||||
# (the "Software"), to deal in the Software without restriction,
|
|
||||||
# including without limitation the rights to use, copy, modify, merge,
|
|
||||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
|
||||||
# and to permit persons to whom the Software is furnished to do so,
|
|
||||||
# subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be
|
|
||||||
# included in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
# OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
# noinspection PyMissingConstructor
|
|
||||||
def __init__(self, *args, **kwds):
|
|
||||||
if len(args) > 1:
|
|
||||||
raise TypeError('expected at most 1 arguments, got %d'
|
|
||||||
% len(args))
|
|
||||||
try:
|
|
||||||
self.__end
|
|
||||||
except AttributeError:
|
|
||||||
self.clear()
|
|
||||||
self.update(*args, **kwds)
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self.__end = end = []
|
|
||||||
# noinspection PyUnusedLocal
|
|
||||||
end += [None, end, end] # sentinel node for doubly linked list
|
|
||||||
self.__map = {} # key --> [key, prev, next]
|
|
||||||
dict.clear(self)
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
if key not in self:
|
|
||||||
end = self.__end
|
|
||||||
curr = end[1]
|
|
||||||
curr[2] = end[1] = self.__map[key] = [key, curr, end]
|
|
||||||
dict.__setitem__(self, key, value)
|
|
||||||
|
|
||||||
def __delitem__(self, key):
|
|
||||||
dict.__delitem__(self, key)
|
|
||||||
key, prev, next = self.__map.pop(key)
|
|
||||||
prev[2] = next
|
|
||||||
next[1] = prev
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
end = self.__end
|
|
||||||
curr = end[2]
|
|
||||||
while curr is not end:
|
|
||||||
yield curr[0]
|
|
||||||
curr = curr[2]
|
|
||||||
|
|
||||||
def __reversed__(self):
|
|
||||||
end = self.__end
|
|
||||||
curr = end[1]
|
|
||||||
while curr is not end:
|
|
||||||
yield curr[0]
|
|
||||||
curr = curr[1]
|
|
||||||
|
|
||||||
def popitem(self, last=True):
|
|
||||||
if not self:
|
|
||||||
raise KeyError('dictionary is empty')
|
|
||||||
if last:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
key = reversed(self).next()
|
|
||||||
else:
|
|
||||||
key = iter(self).next()
|
|
||||||
value = self.pop(key)
|
|
||||||
return key, value
|
|
||||||
|
|
||||||
def __reduce__(self):
|
|
||||||
items = [[k, self[k]] for k in self]
|
|
||||||
tmp = self.__map, self.__end
|
|
||||||
del self.__map, self.__end
|
|
||||||
inst_dict = vars(self).copy()
|
|
||||||
self.__map, self.__end = tmp
|
|
||||||
if inst_dict:
|
|
||||||
return self.__class__, (items,), inst_dict
|
|
||||||
return self.__class__, (items,)
|
|
||||||
|
|
||||||
def keys(self):
|
|
||||||
return list(self)
|
|
||||||
|
|
||||||
setdefault = DictMixin.setdefault
|
|
||||||
update = DictMixin.update
|
|
||||||
pop = DictMixin.pop
|
|
||||||
values = DictMixin.values
|
|
||||||
items = DictMixin.items
|
|
||||||
iterkeys = DictMixin.iterkeys
|
|
||||||
itervalues = DictMixin.itervalues
|
|
||||||
iteritems = DictMixin.iteritems
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if not self:
|
|
||||||
return '%s()' % (self.__class__.__name__,)
|
|
||||||
return '%s(%r)' % (self.__class__.__name__, self.items())
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
return self.__class__(self)
|
|
||||||
|
|
||||||
# noinspection PyMethodOverriding
|
|
||||||
@classmethod
|
|
||||||
def fromkeys(cls, iterable, value=None):
|
|
||||||
d = cls()
|
|
||||||
for key in iterable:
|
|
||||||
d[key] = value
|
|
||||||
return d
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if isinstance(other, OrderedDict):
|
|
||||||
if len(self) != len(other):
|
|
||||||
return False
|
|
||||||
for p, q in zip(self.items(), other.items()):
|
|
||||||
if p != q:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
return dict.__eq__(self, other)
|
|
||||||
|
|
||||||
def __ne__(self, other):
|
|
||||||
return not self == other
|
|
||||||
|
@ -9,7 +9,7 @@ import errno
|
|||||||
import mimetypes
|
import mimetypes
|
||||||
import getpass
|
import getpass
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from collections import namedtuple, Iterable
|
from collections import namedtuple, Iterable, OrderedDict
|
||||||
# noinspection PyCompatibility
|
# noinspection PyCompatibility
|
||||||
from argparse import ArgumentParser, ArgumentTypeError, ArgumentError
|
from argparse import ArgumentParser, ArgumentTypeError, ArgumentError
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ from argparse import ArgumentParser, ArgumentTypeError, ArgumentError
|
|||||||
from httpie.plugins import plugin_manager
|
from httpie.plugins import plugin_manager
|
||||||
from requests.structures import CaseInsensitiveDict
|
from requests.structures import CaseInsensitiveDict
|
||||||
|
|
||||||
from httpie.compat import OrderedDict, urlsplit, str, is_pypy, is_py27
|
from httpie.compat import urlsplit, str, is_pypy, is_py27
|
||||||
from httpie.sessions import VALID_SESSION_NAME_PATTERN
|
from httpie.sessions import VALID_SESSION_NAME_PATTERN
|
||||||
from httpie.utils import load_json_preserve_order
|
from httpie.utils import load_json_preserve_order
|
||||||
|
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
from __future__ import division
|
from __future__ import division
|
||||||
import json
|
import json
|
||||||
|
from collections import OrderedDict
|
||||||
from httpie.compat import is_py26, OrderedDict
|
|
||||||
|
|
||||||
|
|
||||||
def load_json_preserve_order(s):
|
def load_json_preserve_order(s):
|
||||||
if is_py26:
|
|
||||||
return json.loads(s)
|
|
||||||
return json.loads(s, object_pairs_hook=OrderedDict)
|
return json.loads(s, object_pairs_hook=OrderedDict)
|
||||||
|
|
||||||
|
|
||||||
|
2
setup.py
2
setup.py
@ -93,8 +93,6 @@ setup(
|
|||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 5 - Production/Stable',
|
'Development Status :: 5 - Production/Stable',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 2',
|
|
||||||
'Programming Language :: Python :: 2.6',
|
|
||||||
'Programming Language :: Python :: 2.7',
|
'Programming Language :: Python :: 2.7',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.1',
|
'Programming Language :: Python :: 3.1',
|
||||||
|
@ -6,7 +6,6 @@ from utils import TestEnvironment, http, HTTP_OK
|
|||||||
from fixtures import FILE_PATH, FILE_CONTENT
|
from fixtures import FILE_PATH, FILE_CONTENT
|
||||||
|
|
||||||
import httpie
|
import httpie
|
||||||
from httpie.compat import is_py26
|
|
||||||
|
|
||||||
|
|
||||||
def test_debug():
|
def test_debug():
|
||||||
@ -107,10 +106,6 @@ def test_headers_empty_value_with_value_gives_error(httpbin):
|
|||||||
http('GET', httpbin + '/headers', 'Accept;SYNTAX_ERROR')
|
http('GET', httpbin + '/headers', 'Accept;SYNTAX_ERROR')
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(
|
|
||||||
is_py26,
|
|
||||||
reason='the `object_pairs_hook` arg for `json.loads()` is Py>2.6 only'
|
|
||||||
)
|
|
||||||
def test_json_input_preserve_order(httpbin_both):
|
def test_json_input_preserve_order(httpbin_both):
|
||||||
r = http('PATCH', httpbin_both + '/patch',
|
r = http('PATCH', httpbin_both + '/patch',
|
||||||
'order:={"map":{"1":"first","2":"second"}}')
|
'order:={"map":{"1":"first","2":"second"}}')
|
||||||
|
Loading…
Reference in New Issue
Block a user