Skip to content

Commit

Permalink
Merge pull request #507 from jdufresne/py26
Browse files Browse the repository at this point in the history
Drop support for Python 2.6
  • Loading branch information
timothycrosley authored Jun 1, 2017
2 parents df3a4a0 + 8559b53 commit 363b67a
Show file tree
Hide file tree
Showing 10 changed files with 23 additions and 206 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ language: python
matrix:
include:
- env: TOXENV=isort-check
- python: 2.6
env: TOXENV=py26
- python: 2.7
env: TOXENV=py27
- python: 3.3
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ isort your python imports for you so you don't have to.

isort is a Python utility / library to sort imports alphabetically, and automatically separated into sections.
It provides a command line utility, Python library and `plugins for various editors <https://github.com/timothycrosley/isort/wiki/isort-Plugins>`_ to quickly sort all your imports.
It currently cleanly supports Python 2.6 - 3.5 without any dependencies.
It currently cleanly supports Python 2.7 - 3.6 without any dependencies.

.. image:: https://raw.github.com/timothycrosley/isort/develop/example.gif
:alt: Example Usage
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ install:
- pip install tox

test_script:
- tox -e isort-check,py26,py27,py33,py34,py35,py36
- tox -e isort-check,py27,py33,py34,py35,py36
21 changes: 5 additions & 16 deletions isort/isort.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@
import os
import re
import sys
from collections import namedtuple
import sysconfig
from collections import OrderedDict, namedtuple
from datetime import datetime
from difflib import unified_diff
from fnmatch import fnmatch
from glob import glob

from . import settings
from .natural import nsorted
from .pie_slice import OrderedDict, OrderedSet, itemsview
from .pie_slice import OrderedSet, itemsview

KNOWN_SECTION_MAPPING = {
'STDLIB': 'STANDARD_LIBRARY',
Expand Down Expand Up @@ -261,7 +262,7 @@ def place_module(self, module_name):
virtual_env_src = '{0}/src/'.format(virtual_env)

# handle case-insensitive paths on windows
stdlib_lib_prefix = os.path.normcase(get_stdlib_path())
stdlib_lib_prefix = os.path.normcase(sysconfig.get_paths()['stdlib'])

for prefix in paths:
module_path = "/".join((prefix, module_name.replace(".", "/")))
Expand Down Expand Up @@ -486,7 +487,7 @@ def _multi_line_reformat(self, import_start, from_imports, comments):
lines = import_statement.split("\n")
line_count = len(lines)
if len(lines) > 1:
minimum_length = min([len(line) for line in lines[:-1]])
minimum_length = min(len(line) for line in lines[:-1])
else:
minimum_length = 0
new_import_statement = import_statement
Expand Down Expand Up @@ -939,18 +940,6 @@ def coding_check(fname, default='utf-8'):
return coding


def get_stdlib_path():
"""Returns the path to the standard lib for the current path installation.
This function can be dropped and "sysconfig.get_paths()" used directly once Python 2.6 support is dropped.
"""
if sys.version_info >= (2, 7):
import sysconfig
return sysconfig.get_paths()['stdlib']
else:
return os.path.join(sys.prefix, 'lib')


def exists_case_sensitive(path):
"""
Returns if the given path exists and also matches the case on Windows.
Expand Down
2 changes: 1 addition & 1 deletion isort/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def create_parser():
parser.add_argument('-up', '--use-parentheses', dest='use_parentheses', action='store_true',
help='Use parenthesis for line continuation on lenght limit instead of slashes.')

arguments = dict((key, value) for (key, value) in itemsview(vars(parser.parse_args())) if value)
arguments = {key: value for key, value in itemsview(vars(parser.parse_args())) if value}
if 'dont_order_by_type' in arguments:
arguments['order_by_type'] = False
return arguments
Expand Down
192 changes: 11 additions & 181 deletions isort/pie_slice.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

common = ['native_dict', 'native_round', 'native_filter', 'native_map', 'native_range', 'native_str', 'native_chr',
'native_input', 'PY2', 'PY3', 'u', 'itemsview', 'valuesview', 'keysview', 'execute', 'integer_types',
'native_next', 'native_object', 'with_metaclass', 'OrderedDict', 'lru_cache']
'native_next', 'native_object', 'with_metaclass', 'lru_cache']


def with_metaclass(meta, *bases):
Expand Down Expand Up @@ -85,32 +85,12 @@ def unmodified_isinstance(*bases):
"""
class UnmodifiedIsInstance(type):
if sys.version_info[0] == 2 and sys.version_info[1] <= 6:

@classmethod
def __instancecheck__(cls, instance):
if cls.__name__ in (str(base.__name__) for base in bases):
return isinstance(instance, bases)

subclass = getattr(instance, '__class__', None)
subtype = type(instance)
instance_type = getattr(abc, '_InstanceType', None)
if not instance_type:
class test_object:
pass
instance_type = type(test_object)
if subtype is instance_type:
subtype = subclass
if subtype is subclass or subclass is None:
return cls.__subclasscheck__(subtype)
return (cls.__subclasscheck__(subclass) or cls.__subclasscheck__(subtype))
else:
@classmethod
def __instancecheck__(cls, instance):
if cls.__name__ in (str(base.__name__) for base in bases):
return isinstance(instance, bases)
@classmethod
def __instancecheck__(cls, instance):
if cls.__name__ in (str(base.__name__) for base in bases):
return isinstance(instance, bases)

return type.__instancecheck__(cls, instance)
return type.__instancecheck__(cls, instance)

return with_metaclass(UnmodifiedIsInstance, *bases)

Expand Down Expand Up @@ -280,167 +260,17 @@ def __new__(cls, name, bases, dct):
dct['__str__'] = lambda self: self.__unicode__().encode('utf-8')
return type.__new__(cls, name, bases, dct)

if sys.version_info[1] <= 6:
def __instancecheck__(cls, instance):
if cls.__name__ == "object":
return isinstance(instance, native_object)

subclass = getattr(instance, '__class__', None)
subtype = type(instance)
instance_type = getattr(abc, '_InstanceType', None)
if not instance_type:
class test_object:
pass
instance_type = type(test_object)
if subtype is instance_type:
subtype = subclass
if subtype is subclass or subclass is None:
return cls.__subclasscheck__(subtype)
return (cls.__subclasscheck__(subclass) or cls.__subclasscheck__(subtype))
else:
def __instancecheck__(cls, instance):
if cls.__name__ == "object":
return isinstance(instance, native_object)
return type.__instancecheck__(cls, instance)
def __instancecheck__(cls, instance):
if cls.__name__ == "object":
return isinstance(instance, native_object)
return type.__instancecheck__(cls, instance)

class object(with_metaclass(FixStr, object)):
pass

__all__ = common + ['round', 'dict', 'apply', 'cmp', 'coerce', 'execfile', 'raw_input', 'unpacks', 'str', 'chr',
'input', 'range', 'filter', 'map', 'zip', 'object']

if sys.version_info[0] == 2 and sys.version_info[1] < 7:
# OrderedDict
# 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.

from UserDict import DictMixin

class OrderedDict(dict, DictMixin):

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 = []
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:
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)

@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
else:
from collections import OrderedDict


if sys.version_info < (3, 2):
try:
Expand Down Expand Up @@ -487,7 +317,7 @@ def wrapper(*args, **kwds):
misses[0] += 1
return result
else:
CACHE = OrderedDict()
CACHE = collections.OrderedDict()

@wraps(user_function)
def wrapper(*args, **kwds):
Expand Down
3 changes: 2 additions & 1 deletion isort/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from __future__ import absolute_import, division, print_function, unicode_literals

import fnmatch
import io
import os
import posixpath
from collections import namedtuple
Expand Down Expand Up @@ -191,7 +192,7 @@ def _as_list(value):

@lru_cache()
def _get_config_data(file_path, sections):
with open(file_path, 'rU') as config_file:
with io.open(file_path, 'r') as config_file:
if file_path.endswith('.editorconfig'):
line = '\n'
last_position = config_file.tell()
Expand Down
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ def run(self):
'License :: OSI Approved :: MIT License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
Expand Down
2 changes: 1 addition & 1 deletion test_isort.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ def test_settings_combine_instead_of_overwrite():
set(SortImports().config['known_standard_library'] + ['not_std_library'])

assert set(SortImports(not_known_standard_library=['thread']).config['known_standard_library']) == \
set(item for item in SortImports().config['known_standard_library'] if item != 'thread')
{item for item in SortImports().config['known_standard_library'] if item != 'thread'}


def test_combined_from_and_as_imports():
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[tox]
envlist =
isort-check,
py26, py27, py33, py34, py35, py36, pypy
py27, py33, py34, py35, py36, pypy

[testenv]
commands =
Expand Down

0 comments on commit 363b67a

Please sign in to comment.