summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeth Morton <seth.m.morton@gmail.com>2018-11-18 10:38:06 -0800
committerGitHub <noreply@github.com>2018-11-18 10:38:06 -0800
commitd32e5a854ebc23229cbedd5697f397357deed008 (patch)
treeef16d4ecb5e2ef7ca72ca2c595f5afffd057273b
parent916a92d39eaf5ef282b421c4772a7ec831750c4c (diff)
parentf7fdb6219e0e4211b969685f0cd96511242134f1 (diff)
downloadnatsort-d32e5a854ebc23229cbedd5697f397357deed008.tar.gz
Merge pull request #83 from SethMMorton/formal-deprecation-notices
Formal deprecation notices
-rw-r--r--README.rst48
-rw-r--r--docs/changelog.rst2
-rw-r--r--docs/intro.rst45
-rw-r--r--natsort/__init__.py7
-rw-r--r--natsort/natsort.py18
-rw-r--r--natsort/ns_enum.py47
-rw-r--r--natsort/utils.py20
-rw-r--r--test_natsort/test_natsorted.py9
-rw-r--r--test_natsort/test_natsorted_convenience.py6
-rw-r--r--test_natsort/test_utils.py12
10 files changed, 177 insertions, 37 deletions
diff --git a/README.rst b/README.rst
index 59d981a..2d4b4bb 100644
--- a/README.rst
+++ b/README.rst
@@ -35,6 +35,9 @@ Simple yet flexible natural sorting in Python.
- `fastnumbers <https://pypi.org/project/fastnumbers>`_ >= 2.0.0
- `PyICU <https://pypi.org/project/PyICU>`_ >= 1.0.0
+**NOTE**: Please see the `Deprecation Schedule`_ section for changes in the upcoming
+``natsort`` version 6.0.0 (early 2019) and then version 7.0.0.
+
Quick Description
-----------------
@@ -403,6 +406,51 @@ makes it easy for you to install the testing dependencies:
Note that above I invoked ``python -m pytest`` instead of just ``pytest`` - this is because
`the former puts the CWD on sys.path <https://docs.pytest.org/en/latest/usage.html#calling-pytest-through-python-m-pytest>`_.
+Deprecation Schedule
+--------------------
+
+Deprecated APIs
+===============
+
+In ``natsort`` version 6.0.0, the following APIs and functions will be removed
+
+ - ``number_type`` keyword argument (deprecated since 3.4.0)
+ - ``signed`` keyword argument (deprecated since 3.4.0)
+ - ``exp`` keyword argument (deprecated since 3.4.0)
+ - ``as_path`` keyword argument (deprecated since 3.4.0)
+ - ``py3_safe`` keyword argument (deprecated since 3.4.0)
+ - ``ns.TYPESAFE`` (deprecated since version 5.0.0)
+ - ``ns.DIGIT`` (deprecated since version 5.0.0)
+ - ``ns.VERSION`` (deprecated since version 5.0.0)
+ - ``versorted()`` (discouraged since version 4.0.0, officially deprecated since version 5.5.0)
+ - ``index_versorted()`` (discouraged since version 4.0.0, officially deprecated since version 5.5.0)
+
+If you want to determine if you are using any of the deprecated APIs, run your
+code with the following flag
+
+.. code-block:: console
+
+ $ python -Wdefault::DeprecationWarning my-code.py
+
+By default ``DeprecationWarnings`` are not shown, but this will cause them to be shown.
+Alternatively, you can just set the environment variable ``PYTHONWARNINGS`` to
+"default::DeprecationWarning" and then run your code.
+
+Dropping Python 2.6 and 3.3 Support
+===================================
+
+``natsort`` version 6.0.0 will drop support for Python 2.6 and Python 3.3.
+
+Dropping Python 2.7 Support
+===========================
+
+``natsort`` version 7.0.0 will drop support for Python 2.7.
+
+The version 6.X branch will remain as a "long term support" branch where bug fixes
+are applied so that users who cannot update from Python 2.7 will not be forced to
+use a buggy ``natsort`` version. Once version 7.0.0 is released, new features
+will not be added to version 6.X, only bug fixes.
+
Author
------
diff --git a/docs/changelog.rst b/docs/changelog.rst
index d8df0ea..09ed024 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -6,7 +6,7 @@ Changelog
XX-XX-XXXX v. X.X.X
+++++++++++++++++++
- - Removal of Python 2.6 and 3.3 compatibility (thanks @jdufresne)
+ - Formally deprecated old or misleading APIs
- Documentation, packaging, and CI cleanup (thanks @jdufresne)
- Consolidate API documentation into a single page
diff --git a/docs/intro.rst b/docs/intro.rst
index 03625a1..03434f2 100644
--- a/docs/intro.rst
+++ b/docs/intro.rst
@@ -14,6 +14,9 @@ Simple yet flexible natural sorting in Python.
- `fastnumbers <https://pypi.org/project/fastnumbers>`_ >= 2.0.0
- `PyICU <https://pypi.org/project/PyICU>`_ >= 1.0.0
+**NOTE**: Please see the `Deprecation Schedule`_ section for changes in the upcoming
+:mod:`natsort` version 6.0.0 (early 2019) and then version 7.0.0.
+
:mod:`natsort` is a general utility for sorting lists *naturally*; the definition
of "naturally" is not well-defined, but the most common definition is that numbers
contained within the string should be sorted as numbers and not as you would
@@ -397,3 +400,45 @@ makes it easy for you to install the testing dependencies:
Note that above I invoked ``python -m pytest`` instead of just ``pytest`` - this is because
`the former puts the CWD on sys.path <https://docs.pytest.org/en/latest/usage.html#calling-pytest-through-python-m-pytest>`_.
+
+Deprecation Schedule
+--------------------
+
+In :mod:`natsort` version 6.0.0, the following APIs and functions will be removed
+
+ - ``number_type`` keyword argument (deprecated since 3.4.0)
+ - ``signed`` keyword argument (deprecated since 3.4.0)
+ - ``exp`` keyword argument (deprecated since 3.4.0)
+ - ``as_path`` keyword argument (deprecated since 3.4.0)
+ - ``py3_safe`` keyword argument (deprecated since 3.4.0)
+ - ``ns.TYPESAFE`` (deprecated since version 5.0.0)
+ - ``ns.DIGIT`` (deprecated since version 5.0.0)
+ - ``ns.VERSION`` (deprecated since version 5.0.0)
+ - :func:`~natsort.versorted` (discouraged since version 4.0.0, officially deprecated since version 5.5.0)
+ - :func:`~natsort.index_versorted` (discouraged since version 4.0.0, officially deprecated since version 5.5.0)
+
+If you want to determine if you are using any of the deprecated APIs, run your
+code with the following flag
+
+.. code-block:: console
+
+ $ python -Wdefault::DeprecationWarning my-code.py
+
+By default :exc:`DeprecationWarnings` are not shown, but this will cause them to be shown.
+Alternatively, you can just set the environment variable ``PYTHONWARNINGS`` to
+"default::DeprecationWarning" and then run your code.
+
+Dropping Python 2.6 and 3.3 Support
+===================================
+
+:mod:`natsort` version 6.0.0 will drop support for Python 2.6 and Python 3.3.
+
+Dropping Python 2.7 Support
+===========================
+
+:mod:`natsort` version 7.0.0 will drop support for Python 2.7.
+
+The version 6.X branch will remain as a "long term support" branch where bug fixes
+are applied so that users who cannot update from Python 2.7 will not be forced to
+use a buggy :mod:`natsort` version. Once version 7.0.0 is released, new features
+will not be added to version 6.X, only bug fixes.
diff --git a/natsort/__init__.py b/natsort/__init__.py
index 679fa90..200f9d2 100644
--- a/natsort/__init__.py
+++ b/natsort/__init__.py
@@ -2,6 +2,7 @@
from __future__ import absolute_import, division, print_function, unicode_literals
import sys
+import warnings
from natsort.natsort import (
as_ascii,
@@ -49,4 +50,8 @@ __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()))
+# We catch warnings from the deprecated ns enum values when adding
+# them to natsort's main namespace.
+with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ globals().update(dict((k, getattr(ns, k)) for k in dir(ns) if k.isupper()))
diff --git a/natsort/natsort.py b/natsort/natsort.py
index 27f532d..47cc9f1 100644
--- a/natsort/natsort.py
+++ b/natsort/natsort.py
@@ -10,6 +10,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
import sys
from functools import partial
from operator import itemgetter
+from warnings import warn
import natsort.compat.locale
from natsort import utils
@@ -273,14 +274,17 @@ def versorted(seq, key=None, reverse=False, alg=ns.DEFAULT, **_kwargs):
"""
Identical to :func:`natsorted`.
- This function exists for backwards compatibility with `natsort`
- version < 4.0.0. Future development should use :func:`natsorted`.
+ This function is deprecated as of :mod:`natsort` 5.5.0, and will be
+ removed in 6.0.0.
See Also
--------
natsorted
"""
+ msg = "versorted is deprecated as of 5.5.0 and will be removed in 6.0.0, "
+ msg += "please use natsorted instead."
+ warn(msg, DeprecationWarning, stacklevel=2)
return natsorted(seq, key, reverse, alg, **_kwargs)
@@ -466,17 +470,17 @@ def index_versorted(seq, key=None, reverse=False, alg=ns.DEFAULT, **_kwargs):
"""
Identical to :func:`index_natsorted`.
- This function exists for backwards compatibility with
- ``index_natsort`` version < 4.0.0. Future development should use
- :func:`index_natsorted`.
-
- Please see the :func:`index_natsorted` documentation for use.
+ This function is deprecated as of :mod:`natsort` 5.5.0, and will be
+ removed in 6.0.0.
See Also
--------
index_natsorted
"""
+ msg = "index_versorted is deprecated as of 5.5.0 and will be removed in 6.0.0, "
+ msg += "please use index_natsorted instead."
+ warn(msg, DeprecationWarning, stacklevel=2)
return index_natsorted(seq, key, reverse, alg, **_kwargs)
diff --git a/natsort/ns_enum.py b/natsort/ns_enum.py
index 0e98ee6..29f8d87 100644
--- a/natsort/ns_enum.py
+++ b/natsort/ns_enum.py
@@ -6,6 +6,7 @@ what algorithm natsort uses.
from __future__ import absolute_import, division, print_function, unicode_literals
import collections
+import warnings
# NOTE: OrderedDict is not used below for compatibility with Python 2.6.
@@ -28,17 +29,14 @@ enum_options = [
]
# Following were previously options but are now defaults.
-enum_do_nothing = ["DEFAULT", "TYPESAFE", "INT", "VERSION", "DIGIT", "UNSIGNED"]
+enum_do_nothing = ["DEFAULT", "INT", "UNSIGNED"]
# The following are bitwise-OR combinations of other fields.
enum_combos = [("REAL", ("FLOAT", "SIGNED")), ("LOCALE", ("LOCALEALPHA", "LOCALENUM"))]
# The following are aliases for other fields.
enum_aliases = [
- ("T", "TYPESAFE"),
("I", "INT"),
- ("V", "VERSION"),
- ("D", "DIGIT"),
("U", "UNSIGNED"),
("F", "FLOAT"),
("S", "SIGNED"),
@@ -182,12 +180,14 @@ class _NSEnum(collections.namedtuple("_NSEnum", enum_field_names)):
By default, an NaN be treated as -Infinity and be placed first.
TYPESAFE, T
Deprecated as of `natsort` version 5.0.0; this option is now
- a no-op because it is always true.
+ a no-op because it is always true. It will be removed in `natsort`
+ version 6.0.0.
VERSION, V
Deprecated as of `natsort` version 5.0.0; this option is now
- a no-op because it is the default.
+ a no-op because it is the default. It will be removed in `natsort`
+ version 6.0.0.
DIGIT, D
- Same as `VERSION` above.
+ Same as `VERSION` above. It will be removed in `natsort` version 6.0.0.
Notes
-----
@@ -202,6 +202,39 @@ class _NSEnum(collections.namedtuple("_NSEnum", enum_field_names)):
"""
+ _msg = "ns.{0} is deprecated and will be removed in natsort 6.0.0, "
+ _msg += "this option does nothing so please simply remove its use."
+
+ @property
+ def V(self): # noqa: N802
+ warnings.warn(self._msg.format("V"), DeprecationWarning, stacklevel=2)
+ return 0
+
+ @property
+ def VERSION(self): # noqa: N802
+ warnings.warn(self._msg.format("VERSION"), DeprecationWarning, stacklevel=2)
+ return 0
+
+ @property
+ def T(self): # noqa: N802
+ warnings.warn(self._msg.format("T"), DeprecationWarning, stacklevel=2)
+ return 0
+
+ @property
+ def TYPESAFE(self): # noqa: N802
+ warnings.warn(self._msg.format("TYPESAFE"), DeprecationWarning, stacklevel=2)
+ return 0
+
+ @property
+ def D(self): # noqa: N802
+ warnings.warn(self._msg.format("D"), DeprecationWarning, stacklevel=2)
+ return 0
+
+ @property
+ def DIGIT(self): # noqa: N802
+ warnings.warn(self._msg.format("DIGIT"), DeprecationWarning, stacklevel=2)
+ return 0
+
# Here is where the instance of the ns enum that will be exported is created.
# It is a poor-man's singleton.
diff --git a/natsort/utils.py b/natsort/utils.py
index 496904a..8eafd76 100644
--- a/natsort/utils.py
+++ b/natsort/utils.py
@@ -801,25 +801,29 @@ def args_to_enum(**kwargs):
x = set(kwargs) - set(keys)
raise TypeError("Invalid argument(s): " + ", ".join(x))
if "number_type" in kwargs and kwargs["number_type"] is not int:
- msg = "The 'number_type' argument is deprecated as of 3.5.0, "
+ msg = "The 'number_type' argument is deprecated as of 3.5.0 "
+ msg += "and will be removed in 6.0.0, "
msg += "please use 'alg=ns.FLOAT', 'alg=ns.INT', or 'alg=ns.VERSION'"
- warn(msg, DeprecationWarning)
+ warn(msg, DeprecationWarning, stacklevel=3)
alg |= ns.FLOAT * bool(kwargs["number_type"] is float)
alg |= ns.INT * bool(kwargs["number_type"] in (int, None))
alg |= ns.SIGNED * (kwargs["number_type"] not in (float, None))
if "signed" in kwargs and kwargs["signed"] is not None:
- msg = "The 'signed' argument is deprecated as of 3.5.0, "
+ msg = "The 'signed' argument is deprecated as of 3.5.0 "
+ msg += "and will be removed in 6.0.0, "
msg += "please use 'alg=ns.SIGNED'."
- warn(msg, DeprecationWarning)
+ warn(msg, DeprecationWarning, stacklevel=3)
alg |= ns.SIGNED * bool(kwargs["signed"])
if "exp" in kwargs and kwargs["exp"] is not None:
- msg = "The 'exp' argument is deprecated as of 3.5.0, "
+ msg = "The 'exp' argument is deprecated as of 3.5.0 "
+ msg += "and will be removed in 6.0.0, "
msg += "please use 'alg=ns.NOEXP'."
- warn(msg, DeprecationWarning)
+ warn(msg, DeprecationWarning, stacklevel=3)
alg |= ns.NOEXP * (not kwargs["exp"])
if "as_path" in kwargs and kwargs["as_path"] is not None:
- msg = "The 'as_path' argument is deprecated as of 3.5.0, "
+ msg = "The 'as_path' argument is deprecated as of 3.5.0 "
+ msg += "and will be removed in 6.0.0, "
msg += "please use 'alg=ns.PATH'."
- warn(msg, DeprecationWarning)
+ warn(msg, DeprecationWarning, stacklevel=3)
alg |= ns.PATH * kwargs["as_path"]
return alg
diff --git a/test_natsort/test_natsorted.py b/test_natsort/test_natsorted.py
index 5a80772..f21cec8 100644
--- a/test_natsort/test_natsorted.py
+++ b/test_natsort/test_natsorted.py
@@ -49,8 +49,8 @@ def test_natsorted_can_sort_as_unsigned_and_ignore_exponents(float_list, alg):
assert natsorted(float_list, alg=alg) == expected
-# INT, DIGIT, and VERSION are all equivalent.
-@pytest.mark.parametrize("alg", [ns.DEFAULT, ns.INT, ns.DIGIT, ns.VERSION])
+# DEFAULT and INT are all equivalent.
+@pytest.mark.parametrize("alg", [ns.DEFAULT, ns.INT])
def test_natsorted_can_sort_as_unsigned_ints_which_is_default(float_list, alg):
expected = ["a5.034e1", "a50", "a50.4", "a50.31", "a50.300", "a51.", "a-50"]
assert natsorted(float_list, alg=alg) == expected
@@ -70,11 +70,10 @@ def test_natsorted_can_sort_with_or_without_accounting_for_sign(alg, expected):
assert natsorted(given, alg=alg) == expected
-@pytest.mark.parametrize("alg", [ns.DEFAULT, ns.VERSION])
-def test_natsorted_can_sort_as_version_numbers(alg):
+def test_natsorted_can_sort_as_version_numbers():
given = ["1.9.9a", "1.11", "1.9.9b", "1.11.4", "1.10.1"]
expected = ["1.9.9a", "1.9.9b", "1.10.1", "1.11", "1.11.4"]
- assert natsorted(given, alg=alg) == expected
+ assert natsorted(given) == expected
@pytest.mark.parametrize(
diff --git a/test_natsort/test_natsorted_convenience.py b/test_natsort/test_natsorted_convenience.py
index 70fcf79..3c26be0 100644
--- a/test_natsort/test_natsorted_convenience.py
+++ b/test_natsort/test_natsorted_convenience.py
@@ -68,7 +68,8 @@ def test_as_utf8_converts_bytes_to_utf8():
def test_versorted_is_identical_to_natsorted(version_list):
# versorted is retained for backwards compatibility
- assert versorted(version_list) == natsorted(version_list)
+ with pytest.warns(DeprecationWarning, match="use natsorted instead"):
+ assert versorted(version_list) == natsorted(version_list)
def test_realsorted_is_identical_to_natsorted_with_real_alg(float_list):
@@ -102,7 +103,8 @@ def test_index_natsorted_applies_key_function_before_sorting():
def test_index_versorted_is_identical_to_index_natsorted(version_list):
# index_versorted is retained for backwards compatibility
- assert index_versorted(version_list) == index_natsorted(version_list)
+ with pytest.warns(DeprecationWarning, match="use index_natsorted instead"):
+ assert index_versorted(version_list) == index_natsorted(version_list)
def test_index_realsorted_is_identical_to_index_natsorted_with_real_alg(float_list):
diff --git a/test_natsort/test_utils.py b/test_natsort/test_utils.py
index 663a682..0413d48 100644
--- a/test_natsort/test_utils.py
+++ b/test_natsort/test_utils.py
@@ -67,16 +67,10 @@ def test_regex_chooser_returns_correct_regular_expression_object(alg, expected):
[
# Defaults
(ns.DEFAULT, 0),
- (ns.TYPESAFE, 0),
(ns.INT, 0),
- (ns.VERSION, 0),
- (ns.DIGIT, 0),
(ns.UNSIGNED, 0),
# Aliases
- (ns.TYPESAFE, ns.T),
(ns.INT, ns.I),
- (ns.VERSION, ns.V),
- (ns.DIGIT, ns.D),
(ns.UNSIGNED, ns.U),
(ns.FLOAT, ns.F),
(ns.SIGNED, ns.S),
@@ -103,6 +97,12 @@ def test_ns_enum_values_and_aliases(alg, value_or_alias):
assert alg == value_or_alias
+@pytest.mark.parametrize("alg", ["V", "VERSION", "T", "TYPESAFE", "D", "DIGIT"])
+def test_deprecated_ns_enum_values_and_aliases_produce_warning(alg):
+ with pytest.warns(DeprecationWarning, match="please simply remove"):
+ assert getattr(ns, alg) == 0
+
+
def test_chain_functions_is_a_no_op_if_no_functions_are_given():
x = 2345
assert utils.chain_functions([])(x) is x