summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Dufresne <jon.dufresne@gmail.com>2018-11-07 21:36:35 -0800
committerJon Dufresne <jon.dufresne@gmail.com>2018-11-10 10:50:33 -0800
commit36cd8f38e1f1725dfc0078b6f42e35855372bb93 (patch)
tree8ec58e60db64787752dc13fb55b97bddb1956cc6
parent1374b6d2de18e11c0ce6e8aab1fcd09cc70a83dd (diff)
downloadnatsort-36cd8f38e1f1725dfc0078b6f42e35855372bb93.tar.gz
Drop support for EOL Pythons
Support matrix now matches the test matrix from 6233f07bf303d442b39ac677fa6079acc64834a6. By matching these, helps to ensure all supported Python do indeed work. Python 2.6 and 3.3 are end of life. They are no longer receiving bug fixes, including for security issues. Python 2.6 went EOL on 2013-10-29 and on 2017-09-29. For additional details on support Python versions, see: Supported: https://devguide.python.org/#status-of-python-branches EOL: https://devguide.python.org/devcycle/#end-of-life-branches Removing support for EOL Pythons will reduce testing and maintenance resources while allowing the library to move towards a modern Python 3 style. Using pypinfo, we can show the PyPI download statistics, show very low numbers for EOL Pythons. | python_version | percent | download_count | | -------------- | ------: | -------------: | | 2.7 | 48.94% | 37,036 | | 3.6 | 26.58% | 20,113 | | 3.5 | 15.38% | 11,642 | | 3.4 | 5.93% | 4,488 | | 3.7 | 3.13% | 2,365 | | 3.3 | 0.03% | 21 | | 2.6 | 0.01% | 9 | | Total | | 75,674 |
-rw-r--r--README.rst3
-rw-r--r--docs/examples.rst2
-rw-r--r--docs/howitworks.rst5
-rw-r--r--docs/intro.rst3
-rw-r--r--natsort/__init__.py3
-rw-r--r--natsort/__main__.py2
-rw-r--r--natsort/compat/locale.py3
-rw-r--r--natsort/compat/py23.py37
-rw-r--r--natsort/natsort.py4
-rw-r--r--natsort/ns_enum.py27
-rw-r--r--natsort/unicode_numeric_hex.py2
-rw-r--r--setup.cfg2
-rw-r--r--setup.py4
-rw-r--r--test_natsort/conftest.py4
-rw-r--r--test_natsort/test_ns_enum.py50
-rw-r--r--test_natsort/test_unicode_numbers.py2
16 files changed, 79 insertions, 74 deletions
diff --git a/README.rst b/README.rst
index 7ed0bc8..6426572 100644
--- a/README.rst
+++ b/README.rst
@@ -321,8 +321,7 @@ from the command line with ``python -m natsort``.
Requirements
------------
-``natsort`` requires Python version 2.6 or greater or Python 3.3 or greater.
-It may run on (but is not tested against) Python 3.2.
+``natsort`` requires Python version 2.7 or Python 3.4 or greater.
Optional Dependencies
---------------------
diff --git a/docs/examples.rst b/docs/examples.rst
index e30df91..01f78ee 100644
--- a/docs/examples.rst
+++ b/docs/examples.rst
@@ -221,7 +221,7 @@ sort key so that:
... def __init__(self, bar):
... self.bar = bar
... def __repr__(self):
- ... return "Foo('{0}')".format(self.bar)
+ ... return "Foo('{}')".format(self.bar)
>>> b = [Foo('num3'), Foo('num5'), Foo('num2')]
>>> natsorted(b, key=attrgetter('bar'))
[Foo('num2'), Foo('num3'), Foo('num5')]
diff --git a/docs/howitworks.rst b/docs/howitworks.rst
index 12bf569..1138c86 100644
--- a/docs/howitworks.rst
+++ b/docs/howitworks.rst
@@ -895,10 +895,7 @@ It turns out the there is a bug in the legacy Python implementation of
input (https://bugs.python.org/issue2481). :func:`locale.strcoll` works,
but is intended for use with ``cmp``, which does not exist in current Python
implementations. Luckily, the :func:`functools.cmp_to_key` function
-makes :func:`locale.strcoll` behave like :func:`locale.strxfrm` (that is, of course,
-unless you are on Python 2.6 where :func:`functools.cmp_to_key` doesn't exist,
-in which case you simply copy-paste the implementation from Python 2.7
-directly into your code ☹).
+makes :func:`locale.strcoll` behave like :func:`locale.strxfrm`.
Handling Broken Locale On OSX
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/intro.rst b/docs/intro.rst
index 52d31f8..8174e10 100644
--- a/docs/intro.rst
+++ b/docs/intro.rst
@@ -317,8 +317,7 @@ from the command line with ``python -m natsort``.
Requirements
------------
-:mod:`natsort` requires Python version 2.6 or greater or Python 3.3 or greater.
-It may run on (but is not tested against) Python 3.2.
+:mod:`natsort` requires Python version 2.7 or Python 3.4 or greater.
Optional Dependencies
---------------------
diff --git a/natsort/__init__.py b/natsort/__init__.py
index 679fa90..395bbbf 100644
--- a/natsort/__init__.py
+++ b/natsort/__init__.py
@@ -48,5 +48,4 @@ __all__ = [
]
# Add the ns keys to this namespace for convenience.
-# A dict comprehension is not used for Python 2.6 compatibility.
-globals().update(dict((k, getattr(ns, k)) for k in dir(ns) if k.isupper()))
+globals().update(ns._asdict())
diff --git a/natsort/__main__.py b/natsort/__main__.py
index c06c9b8..70d9572 100644
--- a/natsort/__main__.py
+++ b/natsort/__main__.py
@@ -24,7 +24,7 @@ def main(*arguments):
parser.add_argument(
"--version",
action="version",
- version="%(prog)s {0}".format(natsort.__version__),
+ version="%(prog)s {}".format(natsort.__version__),
)
parser.add_argument(
"-p",
diff --git a/natsort/compat/locale.py b/natsort/compat/locale.py
index 1629ba0..41abea6 100644
--- a/natsort/compat/locale.py
+++ b/natsort/compat/locale.py
@@ -7,9 +7,10 @@ from __future__ import absolute_import, division, print_function, unicode_litera
# Std. lib imports.
import sys
+from functools import cmp_to_key
# Local imports.
-from natsort.compat.py23 import PY_VERSION, cmp_to_key, py23_unichr
+from natsort.compat.py23 import PY_VERSION, py23_unichr
# This string should be sorted after any other byte string because
# it contains the max unicode character repeated 20 times.
diff --git a/natsort/compat/py23.py b/natsort/compat/py23.py
index ba9abd9..58f7487 100644
--- a/natsort/compat/py23.py
+++ b/natsort/compat/py23.py
@@ -56,43 +56,6 @@ else:
py23_map = itertools.imap
py23_filter = itertools.ifilter
-# cmp_to_key was not created till 2.7, so require this for 2.6
-try:
- from functools import cmp_to_key
-except ImportError: # pragma: no cover
-
- def cmp_to_key(mycmp):
- """Convert a cmp= function into a key= function"""
-
- class K(object):
- __slots__ = ["obj"]
-
- def __init__(self, obj):
- self.obj = obj
-
- def __lt__(self, other):
- return mycmp(self.obj, other.obj) < 0
-
- def __gt__(self, other):
- return mycmp(self.obj, other.obj) > 0
-
- def __eq__(self, other):
- return mycmp(self.obj, other.obj) == 0
-
- def __le__(self, other):
- return mycmp(self.obj, other.obj) <= 0
-
- def __ge__(self, other):
- return mycmp(self.obj, other.obj) >= 0
-
- def __ne__(self, other):
- return mycmp(self.obj, other.obj) != 0
-
- def __hash__(self):
- raise TypeError("hash not implemented")
-
- return K
-
# This function is intended to decorate other functions that will modify
# either a string directly, or a function's docstring.
diff --git a/natsort/natsort.py b/natsort/natsort.py
index 27f532d..c833ab8 100644
--- a/natsort/natsort.py
+++ b/natsort/natsort.py
@@ -159,7 +159,7 @@ def natsort_keygen(key=None, alg=ns.DEFAULT, **_kwargs):
alg = utils.args_to_enum(**_kwargs) | alg
except TypeError:
msg = "natsort_keygen: 'alg' argument must be from the enum 'ns'"
- raise ValueError(msg + ", got {0}".format(py23_str(alg)))
+ raise ValueError(msg + ", got {}".format(py23_str(alg)))
# Add the _DUMB option if the locale library is broken.
if alg & ns.LOCALEALPHA and natsort.compat.locale.dumb_sort():
@@ -683,7 +683,7 @@ if float(sys.version[:3]) < 3:
alg = utils.args_to_enum(**kwargs) | alg
except TypeError:
msg = "natsort_keygen: 'alg' argument must be " "from the enum 'ns'"
- raise ValueError(msg + ", got {0}".format(py23_str(alg)))
+ raise ValueError(msg + ", got {}".format(py23_str(alg)))
# Add the _DUMB option if the locale library is broken.
if alg & ns.LOCALEALPHA and natsort.compat.locale.dumb_sort():
diff --git a/natsort/ns_enum.py b/natsort/ns_enum.py
index 0e98ee6..5d15985 100644
--- a/natsort/ns_enum.py
+++ b/natsort/ns_enum.py
@@ -7,8 +7,6 @@ from __future__ import absolute_import, division, print_function, unicode_litera
import collections
-# NOTE: OrderedDict is not used below for compatibility with Python 2.6.
-
# The below are the base ns options. The values will be stored as powers
# of two so bitmasks can be used to extract the user's requested options.
enum_options = [
@@ -60,26 +58,25 @@ enum_aliases = [
]
# Construct the list of bitwise distinct enums with their fields.
-enum_fields = [(name, 1 << i) for i, name in enumerate(enum_options)]
-enum_fields.extend((name, 0) for name in enum_do_nothing)
+enum_fields = collections.OrderedDict(
+ (name, 1 << i) for i, name in enumerate(enum_options)
+)
+enum_fields.update((name, 0) for name in enum_do_nothing)
for name, combo in enum_combos:
- current_mapping = dict(enum_fields)
- combined_value = current_mapping[combo[0]]
+ combined_value = enum_fields[combo[0]]
for combo_name in combo[1:]:
- combined_value |= current_mapping[combo_name]
- enum_fields.append((name, combined_value))
-
-current_mapping = dict(enum_fields)
-enum_fields.extend((alias, current_mapping[name]) for alias, name in enum_aliases)
+ combined_value |= enum_fields[combo_name]
+ enum_fields[name] = combined_value
-# Finally, extract out the enum field names and their values.
-enum_field_names, enum_field_values = zip(*enum_fields)
+enum_fields.update(
+ (alias, enum_fields[name]) for alias, name in enum_aliases
+)
# Subclass the namedtuple to improve the docstring.
# noinspection PyUnresolvedReferences
-class _NSEnum(collections.namedtuple("_NSEnum", enum_field_names)):
+class _NSEnum(collections.namedtuple("_NSEnum", enum_fields.keys())):
"""
Enum to control the `natsort` algorithm.
@@ -205,7 +202,7 @@ class _NSEnum(collections.namedtuple("_NSEnum", enum_field_names)):
# Here is where the instance of the ns enum that will be exported is created.
# It is a poor-man's singleton.
-ns = _NSEnum(*enum_field_values)
+ns = _NSEnum(*enum_fields.values())
# The below is private for internal use only.
ns_DUMB = 1 << 31
diff --git a/natsort/unicode_numeric_hex.py b/natsort/unicode_numeric_hex.py
index 56c69d6..de28f3b 100644
--- a/natsort/unicode_numeric_hex.py
+++ b/natsort/unicode_numeric_hex.py
@@ -1743,7 +1743,7 @@ if __name__ == "__main__":
a = py23_unichr(i)
except ValueError:
break
- if a in set("0123456789"):
+ if a in "0123456789":
continue
if unicodedata.numeric(a, None) is not None:
hex_chars.append(i)
diff --git a/setup.cfg b/setup.cfg
index 58287b4..1667a6b 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -22,8 +22,8 @@ classifiers =
Operating System :: OS Independent
License :: OSI Approved :: MIT License
Natural Language :: English
+ 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.4
diff --git a/setup.py b/setup.py
index bef9357..963c483 100644
--- a/setup.py
+++ b/setup.py
@@ -5,10 +5,10 @@ setup(
name='natsort',
version='5.4.1',
packages=find_packages(),
- install_requires=["argparse; python_version < '2.7'"],
entry_points={'console_scripts': ['natsort = natsort.__main__:main']},
+ python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
extras_require={
- 'fast': ["fastnumbers >= 2.0.0; python_version > '2.6'"],
+ 'fast': ["fastnumbers >= 2.0.0"],
'icu': ["PyICU >= 1.0.0"]
}
)
diff --git a/test_natsort/conftest.py b/test_natsort/conftest.py
index 79a8aaa..8a7412b 100644
--- a/test_natsort/conftest.py
+++ b/test_natsort/conftest.py
@@ -10,9 +10,9 @@ import pytest
def load_locale(x):
"""Convenience to load a locale, trying ISO8859-1 first."""
try:
- locale.setlocale(locale.LC_ALL, str("{0}.ISO8859-1".format(x)))
+ locale.setlocale(locale.LC_ALL, str("{}.ISO8859-1".format(x)))
except locale.Error:
- locale.setlocale(locale.LC_ALL, str("{0}.UTF-8".format(x)))
+ locale.setlocale(locale.LC_ALL, str("{}.UTF-8".format(x)))
@pytest.fixture()
diff --git a/test_natsort/test_ns_enum.py b/test_natsort/test_ns_enum.py
new file mode 100644
index 0000000..f8d64df
--- /dev/null
+++ b/test_natsort/test_ns_enum.py
@@ -0,0 +1,50 @@
+from natsort import ns
+
+
+def test_ns_enum():
+ enum_name_values = [
+ ("FLOAT", 0x0001),
+ ("SIGNED", 0x0002),
+ ("NOEXP", 0x0004),
+ ("PATH", 0x0008),
+ ("LOCALEALPHA", 0x0010),
+ ("LOCALENUM", 0x0020),
+ ("IGNORECASE", 0x0040),
+ ("LOWERCASEFIRST", 0x0080),
+ ("GROUPLETTERS", 0x0100),
+ ("UNGROUPLETTERS", 0x0200),
+ ("NANLAST", 0x0400),
+ ("COMPATIBILITYNORMALIZE", 0x0800),
+ ("NUMAFTER", 0x1000),
+ ("DEFAULT", 0x0000),
+ ("TYPESAFE", 0x0000),
+ ("INT", 0x0000),
+ ("VERSION", 0x0000),
+ ("DIGIT", 0x0000),
+ ("UNSIGNED", 0x0000),
+ ("REAL", 0x0003),
+ ("LOCALE", 0x0030),
+ ("T", 0x0000),
+ ("I", 0x0000),
+ ("V", 0x0000),
+ ("D", 0x0000),
+ ("U", 0x0000),
+ ("F", 0x0001),
+ ("S", 0x0002),
+ ("R", 0x0003),
+ ("N", 0x0004),
+ ("P", 0x0008),
+ ("LA", 0x0010),
+ ("LN", 0x0020),
+ ("L", 0x0030),
+ ("IC", 0x0040),
+ ("LF", 0x0080),
+ ("G", 0x0100),
+ ("UG", 0x0200),
+ ("C", 0x0200),
+ ("CAPITALFIRST", 0x0200),
+ ("NL", 0x0400),
+ ("CN", 0x0800),
+ ("NA", 0x1000),
+ ]
+ assert list(ns._asdict().items()) == enum_name_values
diff --git a/test_natsort/test_unicode_numbers.py b/test_natsort/test_unicode_numbers.py
index 484fbb2..582a8f0 100644
--- a/test_natsort/test_unicode_numbers.py
+++ b/test_natsort/test_unicode_numbers.py
@@ -45,7 +45,7 @@ def test_numeric_chars_contains_all_valid_unicode_numeric_and_digit_characters()
a = py23_unichr(i)
except ValueError:
break
- if a in set("0123456789"):
+ if a in "0123456789":
continue
if unicodedata.numeric(a, None) is not None:
assert i in set_numeric_hex