diff options
author | Seth M Morton <seth.m.morton@gmail.com> | 2016-05-03 20:17:32 -0700 |
---|---|---|
committer | Seth M Morton <seth.m.morton@gmail.com> | 2016-05-03 22:10:55 -0700 |
commit | 987ad2bda796a72b402573dbdabeba01f49b893a (patch) | |
tree | 5184ddec4ab699f261e5a8e3edd16141676f5aa3 | |
parent | 70a13171557b6f6a6d750dae08396e595234858d (diff) | |
download | natsort-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.py | 17 | ||||
-rw-r--r-- | natsort/utils.py | 12 | ||||
-rw-r--r-- | test_natsort/test_natsort_keygen.py | 2 | ||||
-rw-r--r-- | test_natsort/test_natsorted.py | 18 | ||||
-rw-r--r-- | test_natsort/test_parse_number_function.py | 27 |
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)),) |