summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeth M Morton <seth.m.morton@gmail.com>2016-05-03 20:17:32 -0700
committerSeth M Morton <seth.m.morton@gmail.com>2016-05-03 22:10:55 -0700
commit987ad2bda796a72b402573dbdabeba01f49b893a (patch)
tree5184ddec4ab699f261e5a8e3edd16141676f5aa3
parent70a13171557b6f6a6d750dae08396e595234858d (diff)
downloadnatsort-987ad2bda796a72b402573dbdabeba01f49b893a.tar.gz
Ensured numbers won't break with LOCALE and CAPITALFIRST or PATH.
PATH or LOCALE and CAPITALFIRST modify the output. The output will be modified appropriately for numbers. Improved ns enum documentation.
-rw-r--r--natsort/ns_enum.py17
-rw-r--r--natsort/utils.py12
-rw-r--r--test_natsort/test_natsort_keygen.py2
-rw-r--r--test_natsort/test_natsorted.py18
-rw-r--r--test_natsort/test_parse_number_function.py27
5 files changed, 66 insertions, 10 deletions
diff --git a/natsort/ns_enum.py b/natsort/ns_enum.py
index 4644b15..a4e1c44 100644
--- a/natsort/ns_enum.py
+++ b/natsort/ns_enum.py
@@ -29,6 +29,10 @@ class ns(object):
`PyICU <https://pypi.python.org/pypi/PyICU>`_ before
filing a bug report to ``natsort``.
+ .. warning:: It is recommended that you recreate your key with
+ :func:`natsort_keygen` each time you change locale
+ if you use the ``ns.LOCALE`` option.
+
Attributes
----------
INT, I (default)
@@ -43,14 +47,6 @@ class ns(object):
Tell `natsort` to take into account any sign (i.e. "-" or "+")
to the immediate left of a number. It is the same as setting
the old `signed` option to `True`.
- VERSION, V
- This is a shortcut for ``ns.INT | ns.UNSIGNED``, which is useful
- when attempting to sort version numbers. It is the same as
- setting the old `number_type` option to `None`. Since
- ``ns.INT | ns.UNSIGNED`` is default, this is is
- unnecessary.
- DIGIT, D
- Same as `VERSION` above.
REAL, R
This is a shortcut for ``ns.FLOAT | ns.SIGNED``, which is useful
when attempting to sort real numbers.
@@ -112,6 +108,11 @@ class ns(object):
TYPESAFE, T
Deprecated as of `natsort` version 5.0.0; this option is now
a no-op because it is always true.
+ VERSION, V
+ Deprecated as of `natsort` version 5.0.0; this option is now
+ a no-op because it is the default.
+ DIGIT, D
+ Same as `VERSION` above.
Notes
-----
diff --git a/natsort/utils.py b/natsort/utils.py
index d47c747..67be2f6 100644
--- a/natsort/utils.py
+++ b/natsort/utils.py
@@ -120,6 +120,8 @@ def _natsort_key(val, key, string_func, bytes_func, num_func):
def _parse_bytes_function(alg):
"""Create a function that will format a bytes string in a tuple."""
+ # We don't worry about ns.UNGROUPLETTERS | ns.LOCALE because
+ # bytes cannot be compared to strings.
if alg & ns.PATH and alg & ns.IGNORECASE:
return lambda x: ((x.lower(),),)
elif alg & ns.PATH:
@@ -139,7 +141,15 @@ def _parse_number_function(alg, sep):
return (sep, nan_replace if val != val else val)
# Return the function, possibly wrapping in tuple if PATH is selected.
- return (lambda x: (func(x),)) if alg & ns.PATH else func
+ null_sep = b'' if use_pyicu else ''
+ if alg & ns.PATH and alg & ns.UNGROUPLETTERS and alg & ns.LOCALE:
+ return lambda x: (((null_sep,), func(x)),)
+ elif alg & ns.UNGROUPLETTERS and alg & ns.LOCALE:
+ return lambda x: ((null_sep,), func(x))
+ elif alg & ns.PATH:
+ return lambda x: (func(x),)
+ else:
+ return func
def _parse_string_function(alg, sep, splitter, pre, post, after):
diff --git a/test_natsort/test_natsort_keygen.py b/test_natsort/test_natsort_keygen.py
index b7be41e..60b139c 100644
--- a/test_natsort/test_natsort_keygen.py
+++ b/test_natsort/test_natsort_keygen.py
@@ -84,7 +84,7 @@ def test_natsort_keygen_splits_input_with_locale():
def test_natsort_keygen_splits_input_with_locale_and_capitalfirst():
strxfrm = get_strxfrm()
with patch('natsort.compat.locale.dumb_sort', return_value=False):
- assert natsort_keygen(alg=ns.L | ns.C)(INPUT) == (((null_string,), (null_string, 6, strxfrm('A-'), 5, strxfrm('.'), 34, strxfrm('e+'), 1)), (('/',), (strxfrm('/Folder ('), 1, strxfrm(')/Foo'))), (null_string, 56.7))
+ assert natsort_keygen(alg=ns.L | ns.C)(INPUT) == (((null_string,), (null_string, 6, strxfrm('A-'), 5, strxfrm('.'), 34, strxfrm('e+'), 1)), (('/',), (strxfrm('/Folder ('), 1, strxfrm(')/Foo'))), ((null_string,), (null_string, 56.7)))
if IS_PY3: assert natsort_keygen(alg=ns.L | ns.C)(b'6A-5.034e+1') == (b'6A-5.034e+1',)
diff --git a/test_natsort/test_natsorted.py b/test_natsort/test_natsorted.py
index 301c4a3..921aa60 100644
--- a/test_natsort/test_natsorted.py
+++ b/test_natsort/test_natsorted.py
@@ -244,3 +244,21 @@ def test_natsorted_with_LOCALE_and_mixed_input_returns_sorted_results_without_er
a = ['2', 'ä', 'b', 1.5, 3]
assert natsorted(a, alg=ns.LOCALE) == [1.5, '2', 3, 'ä', 'b']
locale.setlocale(locale.LC_ALL, str(''))
+
+
+def test_natsorted_with_LOCALE_and_UNGROUPLETTERS_and_mixed_input_returns_sorted_results_without_error():
+ load_locale('en_US')
+ a = ['0', 'Á', '2', 'Z']
+ assert natsorted(a, alg=ns.LOCALE | ns.UNGROUPLETTERS) == ['0', '2', 'Z', 'Á']
+ a = ['2', 'ä', 'b', 1.5, 3]
+ assert natsorted(a, alg=ns.LOCALE | ns.UNGROUPLETTERS) == [1.5, '2', 3, 'b', 'ä']
+ locale.setlocale(locale.LC_ALL, str(''))
+
+
+def test_natsorted_with_PATH_and_LOCALE_and_UNGROUPLETTERS_and_mixed_input_returns_sorted_results_without_error():
+ load_locale('en_US')
+ a = ['0', 'Á', '2', 'Z']
+ assert natsorted(a, alg=ns.PATH | ns.LOCALE | ns.UNGROUPLETTERS) == ['0', '2', 'Z', 'Á']
+ a = ['2', 'ä', 'b', 1.5, 3]
+ assert natsorted(a, alg=ns.PATH | ns.LOCALE | ns.UNGROUPLETTERS) == [1.5, '2', 3, 'b', 'ä']
+ locale.setlocale(locale.LC_ALL, str(''))
diff --git a/test_natsort/test_parse_number_function.py b/test_natsort/test_parse_number_function.py
index 2a899d2..0023e66 100644
--- a/test_natsort/test_parse_number_function.py
+++ b/test_natsort/test_parse_number_function.py
@@ -6,6 +6,7 @@ import pytest
from math import isnan
from natsort.ns_enum import ns
from natsort.utils import _parse_number_function
+from natsort.compat.locale import use_pyicu
from compat.hypothesis import (
assume,
given,
@@ -41,3 +42,29 @@ def test_parse_number_function_with_PATH_makes_function_that_returns_nested_tupl
def test_parse_number_function_with_PATH_makes_function_that_returns_nested_tuple(x):
assume(not isnan(x))
assert _parse_number_function(ns.PATH, '')(x) == (('', x), )
+
+
+def test_parse_number_function_with_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple_example():
+ null_sep = b'' if use_pyicu else ''
+ assert _parse_number_function(ns.UNGROUPLETTERS | ns.LOCALE, '')(57) == ((null_sep,), ('', 57))
+
+
+@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater')
+@given(floats() | integers())
+def test_parse_number_function_with_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple(x):
+ assume(not isnan(x))
+ null_sep = b'' if use_pyicu else ''
+ assert _parse_number_function(ns.UNGROUPLETTERS | ns.LOCALE, '')(x) == ((null_sep,), ('', x))
+
+
+def test_parse_number_function_with_PATH_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple_example():
+ null_sep = b'' if use_pyicu else ''
+ assert _parse_number_function(ns.PATH | ns.UNGROUPLETTERS | ns.LOCALE, '')(57) == (((null_sep,), ('', 57)),)
+
+
+@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater')
+@given(floats() | integers())
+def test_parse_number_function_with_PATH_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple(x):
+ assume(not isnan(x))
+ null_sep = b'' if use_pyicu else ''
+ assert _parse_number_function(ns.PATH | ns.UNGROUPLETTERS | ns.LOCALE, '')(x) == (((null_sep,), ('', x)),)