diff options
author | Seth Morton <seth.m.morton@gmail.com> | 2018-11-18 10:38:06 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-18 10:38:06 -0800 |
commit | d32e5a854ebc23229cbedd5697f397357deed008 (patch) | |
tree | ef16d4ecb5e2ef7ca72ca2c595f5afffd057273b | |
parent | 916a92d39eaf5ef282b421c4772a7ec831750c4c (diff) | |
parent | f7fdb6219e0e4211b969685f0cd96511242134f1 (diff) | |
download | natsort-d32e5a854ebc23229cbedd5697f397357deed008.tar.gz |
Merge pull request #83 from SethMMorton/formal-deprecation-notices
Formal deprecation notices
-rw-r--r-- | README.rst | 48 | ||||
-rw-r--r-- | docs/changelog.rst | 2 | ||||
-rw-r--r-- | docs/intro.rst | 45 | ||||
-rw-r--r-- | natsort/__init__.py | 7 | ||||
-rw-r--r-- | natsort/natsort.py | 18 | ||||
-rw-r--r-- | natsort/ns_enum.py | 47 | ||||
-rw-r--r-- | natsort/utils.py | 20 | ||||
-rw-r--r-- | test_natsort/test_natsorted.py | 9 | ||||
-rw-r--r-- | test_natsort/test_natsorted_convenience.py | 6 | ||||
-rw-r--r-- | test_natsort/test_utils.py | 12 |
10 files changed, 177 insertions, 37 deletions
@@ -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 |