diff options
| author | Seth M Morton <seth.m.morton@gmail.com> | 2016-05-03 01:03:42 -0700 |
|---|---|---|
| committer | Seth M Morton <seth.m.morton@gmail.com> | 2016-05-03 01:03:42 -0700 |
| commit | 693683d7def174abbcde8d72c6e202d4143ade02 (patch) | |
| tree | 1013f0b8d620732748273f9cd282a5b384d5855a | |
| parent | 477f04262babd9fea8c0916127507c27195d348a (diff) | |
| download | natsort-693683d7def174abbcde8d72c6e202d4143ade02.tar.gz | |
Split tests into many more files.
The testing files were getting too long, so they have been split
into more targeted files. This will make further development less
daunting.
| -rw-r--r-- | setup.cfg | 12 | ||||
| -rw-r--r-- | test_natsort/test_natsort_key.py | 107 | ||||
| -rw-r--r-- | test_natsort/test_natsort_keygen.py | 51 | ||||
| -rw-r--r-- | test_natsort/test_natsorted.py (renamed from test_natsort/test_natsort.py) | 161 | ||||
| -rw-r--r-- | test_natsort/test_natsorted_convenience.py | 126 | ||||
| -rw-r--r-- | test_natsort/test_parse_bytes_function.py | 56 | ||||
| -rw-r--r-- | test_natsort/test_parse_number_function.py | 43 | ||||
| -rw-r--r-- | test_natsort/test_parse_string_function.py | 175 | ||||
| -rw-r--r-- | test_natsort/test_post_split_function.py | 120 | ||||
| -rw-r--r-- | test_natsort/test_post_string_parse_function.py | 66 | ||||
| -rw-r--r-- | test_natsort/test_pre_split_function.py | 96 | ||||
| -rw-r--r-- | test_natsort/test_unicode_numbers.py | 17 | ||||
| -rw-r--r-- | test_natsort/test_utils.py | 517 |
13 files changed, 860 insertions, 687 deletions
@@ -16,10 +16,20 @@ flakes-ignore = pep8ignore = natsort/ns_enum.py E126 E241 E123 E221 - test_natsort/test_natsort.py E501 E241 E221 + test_natsort/test_natsorted.py E501 E241 E221 + test_natsort/test_natsort_keygen.py E501 E241 E221 + test_natsort/test_natsorted_convenience.py E501 E241 E221 test_natsort/test_utils.py E501 E241 E221 + test_natsort/test_parse_string_function.py E501 E241 E221 + test_natsort/test_parse_number_function.py E501 E241 E221 + test_natsort/test_parse_bytes_function.py E501 E241 E221 + test_natsort/test_pre_split_function.py E501 E241 E221 + test_natsort/test_post_split_function.py E501 E241 E221 + test_natsort/test_post_string_parse_function.py E501 E241 E221 + test_natsort/test_natsort_key.py E501 E241 E221 test_natsort/test_locale_help.py E501 E241 E221 test_natsort/test_main.py E501 E241 E221 + test_natsort/test_unicode_numbers.py E501 test_natsort/profile_natsorted.py ALL docs/source/conf.py ALL diff --git a/test_natsort/test_natsort_key.py b/test_natsort/test_natsort_key.py new file mode 100644 index 0000000..62e258e --- /dev/null +++ b/test_natsort/test_natsort_key.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +"""These test the utils.py functions.""" +from __future__ import unicode_literals + +import sys +import pytest +from math import isnan +from natsort.ns_enum import ns +from natsort.utils import ( + _natsort_key, + _regex_chooser, + _parse_string_function, + _parse_path_function, + _parse_number_function, + _parse_bytes_function, + _pre_split_function, + _post_split_function, + _post_string_parse_function, +) +from compat.hypothesis import ( + assume, + given, + lists, + text, + floats, + integers, + binary, + use_hypothesis, +) + +if sys.version[0] == '3': + long = int + + +regex = _regex_chooser[ns.INT] +pre = _pre_split_function(ns.INT) +post = _post_split_function(ns.INT) +after = _post_string_parse_function(ns.INT, '') +string_func = _parse_string_function(ns.INT, '', regex.split, pre, post, after) +bytes_func = _parse_bytes_function(ns.INT) +num_func = _parse_number_function(ns.INT, '') + + +def test__natsort_key_with_numeric_input_and_PATH_returns_number_in_nested_tuple(): + # It gracefully handles as_path for numeric input by putting an extra tuple around it + # so it will sort against the other as_path results. + sfunc = _parse_path_function(string_func) + bytes_func = _parse_bytes_function(ns.PATH) + num_func = _parse_number_function(ns.PATH, '') + assert _natsort_key(10, None, sfunc, bytes_func, num_func) == (('', 10),) + + +if sys.version[0] == '3': + def test__natsort_key_with_bytes_input_and_PATH_returns_number_in_nested_tuple(): + # It gracefully handles as_path for numeric input by putting an extra tuple around it + # so it will sort against the other as_path results. + sfunc = _parse_path_function(string_func) + bytes_func = _parse_bytes_function(ns.PATH) + num_func = _parse_number_function(ns.PATH, '') + assert _natsort_key(b'/hello/world', None, sfunc, bytes_func, num_func) == ((b'/hello/world',),) + + +def test__natsort_key_with_tuple_of_paths_and_PATH_returns_triply_nested_tuple(): + # PATH also handles recursion well. + sfunc = _parse_path_function(string_func) + bytes_func = _parse_bytes_function(ns.PATH) + num_func = _parse_number_function(ns.PATH, '') + assert _natsort_key(('/Folder', '/Folder (1)'), None, sfunc, bytes_func, num_func) == ((('/',), ('Folder',)), (('/',), ('Folder (', 1, ')'))) + + +# The remaining tests provide no examples, just hypothesis tests. +# They only confirm that _natsort_key uses the above building blocks. + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(floats() | integers()) +def test__natsort_key_with_numeric_input_takes_number_path(x): + assume(not isnan(x)) + assert _natsort_key(x, None, string_func, bytes_func, num_func) == num_func(x) + + +if sys.version[0] == '3': + @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') + @given(binary()) + def test__natsort_key_with_bytes_input_takes_bytes_path(x): + assume(x) + assert _natsort_key(x, None, string_func, bytes_func, num_func) == bytes_func(x) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +def test__natsort_key_with_text_input_takes_string_path(x): + assume(not any(type(y) == float and isnan(y) for y in x)) + s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) + assert _natsort_key(s, None, string_func, bytes_func, num_func) == string_func(s) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(lists(elements=text(), min_size=1, max_size=10)) +def test__natsort_key_with_nested_input_takes_nested_path(x): + assert _natsort_key(x, None, string_func, bytes_func, num_func) == tuple(string_func(s) for s in x) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test__natsort_key_with_key_argument_applies_key_before_processing(x): + assert _natsort_key(x, len, string_func, bytes_func, num_func) == num_func(len(x)) diff --git a/test_natsort/test_natsort_keygen.py b/test_natsort/test_natsort_keygen.py new file mode 100644 index 0000000..7073851 --- /dev/null +++ b/test_natsort/test_natsort_keygen.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +"""\ +Here are a collection of examples of how this module can be used. +See the README or the natsort homepage for more details. +""" +from __future__ import unicode_literals, print_function +import warnings +from pytest import raises +from natsort import ( + natsorted, + natsort_key, + natsort_keygen, + ns, +) +# from natsort.utils import _natsort_key + + +def test_natsort_key_public_raises_DeprecationWarning_when_called(): + # Identical to _natsort_key + # But it raises a deprecation warning + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + assert natsort_key('a-5.034e2') == ('a-', 5, '.', 34, 'e', 2) + assert len(w) == 1 + assert "natsort_key is deprecated as of 3.4.0, please use natsort_keygen" in str(w[-1].message) + # It is called for each element in a list when sorting + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + a = ['a2', 'a5', 'a9', 'a1', 'a4', 'a10', 'a6'] + a.sort(key=natsort_key) + assert len(w) == 7 + + +def test_natsort_keygen_with_invalid_alg_input_raises_ValueError(): + # Invalid arguments give the correct response + with raises(ValueError) as err: + natsort_keygen(None, '1') + assert str(err.value) == "natsort_keygen: 'alg' argument must be from the enum 'ns', got 1" + + +def test_natsort_keygen_returns_natsort_key_that_parses_input(): + a = 'a-5.034e1' + assert natsort_keygen()(a) == ('a-', 5, '.', 34, 'e', 1) + assert natsort_keygen(alg=ns.F | ns.S)(a) == ('a', -50.34) + + +def test_natsort_keygen_returns_key_that_can_be_used_to_sort_list_in_place_with_same_result_as_natsorted(): + a = ['a50', 'a51.', 'a50.31', 'a50.4', 'a5.034e1', 'a50.300'] + b = a[:] + a.sort(key=natsort_keygen(alg=ns.F)) + assert a == natsorted(b, alg=ns.F) diff --git a/test_natsort/test_natsort.py b/test_natsort/test_natsorted.py index 8b4bf80..301c4a3 100644 --- a/test_natsort/test_natsort.py +++ b/test_natsort/test_natsorted.py @@ -4,88 +4,19 @@ Here are a collection of examples of how this module can be used. See the README or the natsort homepage for more details. """ from __future__ import unicode_literals, print_function -import pytest +# import pytest import sys -import warnings import locale from operator import itemgetter from pytest import raises from natsort import ( natsorted, - index_natsorted, - natsort_key, - versorted, - index_versorted, - humansorted, - index_humansorted, - natsort_keygen, - order_by_index, ns, - realsorted, - index_realsorted, - decoder, - as_ascii, - as_utf8, ) -from compat.locale import load_locale, has_locale_de_DE -from natsort.utils import _natsort_key - - -def test_decoder_returns_function_that_can_decode_bytes_but_return_non_bytes_as_is(): - f = decoder('latin1') - a = 'bytes' - b = 14 - assert f(b'bytes') == a - assert f(b) is b # returns as-is, same object ID - if sys.version[0] == '3': - assert f(a) is a # same object returned on Python3 b/c only bytes has decode - else: - assert f(a) is not a - assert f(a) == a # not same object on Python2 because str can decode - - -def test_as_ascii_returns_bytes_as_ascii(): - assert decoder('ascii')(b'bytes') == as_ascii(b'bytes') - - -def test_as_utf8_returns_bytes_as_utf8(): - assert decoder('utf8')(b'bytes') == as_utf8(b'bytes') - - -def test_natsort_key_public_raises_DeprecationWarning_when_called(): - # Identical to _natsort_key - # But it raises a deprecation warning - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - assert natsort_key('a-5.034e2') == ('a-', 5, '.', 34, 'e', 2) - assert len(w) == 1 - assert "natsort_key is deprecated as of 3.4.0, please use natsort_keygen" in str(w[-1].message) - # It is called for each element in a list when sorting - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - a = ['a2', 'a5', 'a9', 'a1', 'a4', 'a10', 'a6'] - a.sort(key=natsort_key) - assert len(w) == 7 - - -def test_natsort_keygen_with_invalid_alg_input_raises_ValueError(): - # Invalid arguments give the correct response - with raises(ValueError) as err: - natsort_keygen(None, '1') - assert str(err.value) == "natsort_keygen: 'alg' argument must be from the enum 'ns', got 1" - - -def test_natsort_keygen_returns_natsort_key_that_parses_input(): - a = 'a-5.034e1' - assert natsort_keygen()(a) == ('a-', 5, '.', 34, 'e', 1) - assert natsort_keygen(alg=ns.F | ns.S)(a) == ('a', -50.34) - - -def test_natsort_keygen_returns_key_that_can_be_used_to_sort_list_in_place_with_same_result_as_natsorted(): - a = ['a50', 'a51.', 'a50.31', 'a50.4', 'a5.034e1', 'a50.300'] - b = a[:] - a.sort(key=natsort_keygen(alg=ns.F)) - assert a == natsorted(b, alg=ns.F) +from compat.locale import ( + load_locale, + # has_locale_de_DE, +) def test_natsorted_returns_strings_with_numbers_in_ascending_order(): @@ -313,85 +244,3 @@ 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_versorted_returns_results_identical_to_natsorted(): - a = ['1.9.9a', '1.11', '1.9.9b', '1.11.4', '1.10.1'] - # versorted is retained for backwards compatibility - assert versorted(a) == natsorted(a) - - -def test_realsorted_returns_results_identical_to_natsorted_with_REAL(): - a = ['a50', 'a51.', 'a50.31', 'a-50', 'a50.4', 'a5.034e1', 'a50.300'] - assert realsorted(a) == natsorted(a, alg=ns.REAL) - - -def test_humansorted_returns_results_identical_to_natsorted_with_LOCALE(): - a = ['Apple', 'corn', 'Corn', 'Banana', 'apple', 'banana'] - assert humansorted(a) == natsorted(a, alg=ns.LOCALE) - - -def test_index_natsorted_returns_integer_list_of_sort_order_for_input_list(): - a = ['num3', 'num5', 'num2'] - b = ['foo', 'bar', 'baz'] - index = index_natsorted(a) - assert index == [2, 0, 1] - assert [a[i] for i in index] == ['num2', 'num3', 'num5'] - assert [b[i] for i in index] == ['baz', 'foo', 'bar'] - - -def test_index_natsorted_returns_reversed_integer_list_of_sort_order_for_input_list_with_reverse_option(): - a = ['num3', 'num5', 'num2'] - assert index_natsorted(a, reverse=True) == [1, 0, 2] - - -def test_index_natsorted_applies_key_function_before_sorting(): - c = [('a', 'num3'), ('b', 'num5'), ('c', 'num2')] - assert index_natsorted(c, key=itemgetter(1)) == [2, 0, 1] - - -def test_index_natsorted_handles_unorderable_types_error_on_Python3(): - a = [46, '5a5b2', 'af5', '5a5-4'] - assert index_natsorted(a) == [3, 1, 0, 2] - - -def test_index_natsorted_returns_integer_list_of_nested_input_list(): - data = [['a1', 'a5'], ['a1', 'a40'], ['a10', 'a1'], ['a2', 'a5']] - assert index_natsorted(data) == [0, 1, 3, 2] - - -def test_index_natsorted_returns_integer_list_in_proper_order_for_input_paths_with_PATH(): - a = ['/p/Folder (10)/', - '/p/Folder/', - '/p/Folder (1)/'] - assert index_natsorted(a, alg=ns.PATH) == [1, 2, 0] - - -def test_index_versorted_returns_results_identical_to_index_natsorted(): - a = ['1.9.9a', '1.11', '1.9.9b', '1.11.4', '1.10.1'] - # index_versorted is retained for backwards compatibility - assert index_versorted(a) == index_natsorted(a) - - -def test_index_realsorted_returns_results_identical_to_index_natsorted_with_REAL(): - a = ['a50', 'a51.', 'a50.31', 'a-50', 'a50.4', 'a5.034e1', 'a50.300'] - assert index_realsorted(a) == index_natsorted(a, alg=ns.REAL) - - -def test_index_humansorted_returns_results_identical_to_index_natsorted_with_LOCALE(): - a = ['Apple', 'corn', 'Corn', 'Banana', 'apple', 'banana'] - assert index_humansorted(a) == index_natsorted(a, alg=ns.LOCALE) - - -def test_order_by_index_sorts_list_according_to_order_of_integer_list(): - a = ['num3', 'num5', 'num2'] - index = [2, 0, 1] - assert order_by_index(a, index) == ['num2', 'num3', 'num5'] - assert order_by_index(a, index) == [a[i] for i in index] - - -def test_order_by_index_returns_generator_with_iter_True(): - a = ['num3', 'num5', 'num2'] - index = [2, 0, 1] - assert order_by_index(a, index, True) != [a[i] for i in index] - assert list(order_by_index(a, index, True)) == [a[i] for i in index] diff --git a/test_natsort/test_natsorted_convenience.py b/test_natsort/test_natsorted_convenience.py new file mode 100644 index 0000000..f094c0b --- /dev/null +++ b/test_natsort/test_natsorted_convenience.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +"""\ +Here are a collection of examples of how this module can be used. +See the README or the natsort homepage for more details. +""" +from __future__ import unicode_literals, print_function +import sys +from operator import itemgetter +from natsort import ( + natsorted, + index_natsorted, + versorted, + index_versorted, + humansorted, + index_humansorted, + realsorted, + index_realsorted, + order_by_index, + ns, + decoder, + as_ascii, + as_utf8, +) + + +def test_decoder_returns_function_that_can_decode_bytes_but_return_non_bytes_as_is(): + f = decoder('latin1') + a = 'bytes' + b = 14 + assert f(b'bytes') == a + assert f(b) is b # returns as-is, same object ID + if sys.version[0] == '3': + assert f(a) is a # same object returned on Python3 b/c only bytes has decode + else: + assert f(a) is not a + assert f(a) == a # not same object on Python2 because str can decode + + +def test_as_ascii_returns_bytes_as_ascii(): + assert decoder('ascii')(b'bytes') == as_ascii(b'bytes') + + +def test_as_utf8_returns_bytes_as_utf8(): + assert decoder('utf8')(b'bytes') == as_utf8(b'bytes') + + +def test_versorted_returns_results_identical_to_natsorted(): + a = ['1.9.9a', '1.11', '1.9.9b', '1.11.4', '1.10.1'] + # versorted is retained for backwards compatibility + assert versorted(a) == natsorted(a) + + +def test_realsorted_returns_results_identical_to_natsorted_with_REAL(): + a = ['a50', 'a51.', 'a50.31', 'a-50', 'a50.4', 'a5.034e1', 'a50.300'] + assert realsorted(a) == natsorted(a, alg=ns.REAL) + + +def test_humansorted_returns_results_identical_to_natsorted_with_LOCALE(): + a = ['Apple', 'corn', 'Corn', 'Banana', 'apple', 'banana'] + assert humansorted(a) == natsorted(a, alg=ns.LOCALE) + + +def test_index_natsorted_returns_integer_list_of_sort_order_for_input_list(): + a = ['num3', 'num5', 'num2'] + b = ['foo', 'bar', 'baz'] + index = index_natsorted(a) + assert index == [2, 0, 1] + assert [a[i] for i in index] == ['num2', 'num3', 'num5'] + assert [b[i] for i in index] == ['baz', 'foo', 'bar'] + + +def test_index_natsorted_returns_reversed_integer_list_of_sort_order_for_input_list_with_reverse_option(): + a = ['num3', 'num5', 'num2'] + assert index_natsorted(a, reverse=True) == [1, 0, 2] + + +def test_index_natsorted_applies_key_function_before_sorting(): + c = [('a', 'num3'), ('b', 'num5'), ('c', 'num2')] + assert index_natsorted(c, key=itemgetter(1)) == [2, 0, 1] + + +def test_index_natsorted_handles_unorderable_types_error_on_Python3(): + a = [46, '5a5b2', 'af5', '5a5-4'] + assert index_natsorted(a) == [3, 1, 0, 2] + + +def test_index_natsorted_returns_integer_list_of_nested_input_list(): + data = [['a1', 'a5'], ['a1', 'a40'], ['a10', 'a1'], ['a2', 'a5']] + assert index_natsorted(data) == [0, 1, 3, 2] + + +def test_index_natsorted_returns_integer_list_in_proper_order_for_input_paths_with_PATH(): + a = ['/p/Folder (10)/', + '/p/Folder/', + '/p/Folder (1)/'] + assert index_natsorted(a, alg=ns.PATH) == [1, 2, 0] + + +def test_index_versorted_returns_results_identical_to_index_natsorted(): + a = ['1.9.9a', '1.11', '1.9.9b', '1.11.4', '1.10.1'] + # index_versorted is retained for backwards compatibility + assert index_versorted(a) == index_natsorted(a) + + +def test_index_realsorted_returns_results_identical_to_index_natsorted_with_REAL(): + a = ['a50', 'a51.', 'a50.31', 'a-50', 'a50.4', 'a5.034e1', 'a50.300'] + assert index_realsorted(a) == index_natsorted(a, alg=ns.REAL) + + +def test_index_humansorted_returns_results_identical_to_index_natsorted_with_LOCALE(): + a = ['Apple', 'corn', 'Corn', 'Banana', 'apple', 'banana'] + assert index_humansorted(a) == index_natsorted(a, alg=ns.LOCALE) + + +def test_order_by_index_sorts_list_according_to_order_of_integer_list(): + a = ['num3', 'num5', 'num2'] + index = [2, 0, 1] + assert order_by_index(a, index) == ['num2', 'num3', 'num5'] + assert order_by_index(a, index) == [a[i] for i in index] + + +def test_order_by_index_returns_generator_with_iter_True(): + a = ['num3', 'num5', 'num2'] + index = [2, 0, 1] + assert order_by_index(a, index, True) != [a[i] for i in index] + assert list(order_by_index(a, index, True)) == [a[i] for i in index] diff --git a/test_natsort/test_parse_bytes_function.py b/test_natsort/test_parse_bytes_function.py new file mode 100644 index 0000000..7c3587e --- /dev/null +++ b/test_natsort/test_parse_bytes_function.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +"""These test the utils.py functions.""" +from __future__ import unicode_literals + +import pytest +from natsort.ns_enum import ns +from natsort.utils import _parse_bytes_function +from compat.hypothesis import ( + given, + binary, + use_hypothesis, +) + + +# Each test has an "example" version for demonstrative purposes, +# and a test that uses the hypothesis module. + + +def test_parse_bytes_function_makes_function_that_returns_tuple_example(): + assert _parse_bytes_function(0)(b'hello') == (b'hello', ) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(binary()) +def test_parse_bytes_function_makes_function_that_returns_tuple(x): + assert _parse_bytes_function(0)(x) == (x, ) + + +def test_parse_bytes_function_with_IGNORECASE_makes_function_that_returns_tuple_with_lowercase_example(): + assert _parse_bytes_function(ns.IGNORECASE)(b'HelLo') == (b'hello', ) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(binary()) +def test_parse_bytes_function_with_IGNORECASE_makes_function_that_returns_tuple_with_lowercase(x): + assert _parse_bytes_function(ns.IGNORECASE)(x) == (x.lower(), ) + + +def test_parse_bytes_function_with_PATH_makes_function_that_returns_nested_tuple_example(): + assert _parse_bytes_function(ns.PATH)(b'hello') == ((b'hello', ), ) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(binary()) +def test_parse_bytes_function_with_PATH_makes_function_that_returns_nested_tuple(x): + assert _parse_bytes_function(ns.PATH)(x) == ((x, ), ) + + +def test_parse_bytes_function_with_PATH_and_IGNORECASE_makes_function_that_returns_nested_tuple_with_lowercase_example(): + assert _parse_bytes_function(ns.PATH | ns.IGNORECASE)(b'HelLo') == ((b'hello', ), ) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(binary()) +def test_parse_bytes_function_with_PATH_and_IGNORECASE_makes_function_that_returns_nested_tuple_with_lowercase(x): + assert _parse_bytes_function(ns.PATH | ns.IGNORECASE)(x) == ((x.lower(), ), ) diff --git a/test_natsort/test_parse_number_function.py b/test_natsort/test_parse_number_function.py new file mode 100644 index 0000000..2a899d2 --- /dev/null +++ b/test_natsort/test_parse_number_function.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +"""These test the utils.py functions.""" +from __future__ import unicode_literals + +import pytest +from math import isnan +from natsort.ns_enum import ns +from natsort.utils import _parse_number_function +from compat.hypothesis import ( + assume, + given, + floats, + integers, + use_hypothesis, +) + + +# Each test has an "example" version for demonstrative purposes, +# and a test that uses the hypothesis module. + + +def test_parse_number_function_makes_function_that_returns_tuple_example(): + assert _parse_number_function(0, '')(57) == ('', 57) + assert _parse_number_function(0, '')(float('nan')) == ('', float('-inf')) + assert _parse_number_function(ns.NANLAST, '')(float('nan')) == ('', float('+inf')) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(floats() | integers()) +def test_parse_number_function_makes_function_that_returns_tuple(x): + assume(not isnan(x)) + assert _parse_number_function(0, '')(x) == ('', x) + + +def test_parse_number_function_with_PATH_makes_function_that_returns_nested_tuple_example(): + assert _parse_number_function(ns.PATH, '')(57) == (('', 57), ) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(floats() | integers()) +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), ) diff --git a/test_natsort/test_parse_string_function.py b/test_natsort/test_parse_string_function.py new file mode 100644 index 0000000..9c550d2 --- /dev/null +++ b/test_natsort/test_parse_string_function.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +"""These test the utils.py functions.""" +from __future__ import unicode_literals + +import sys +import pytest +from math import isnan +from pytest import raises +from natsort.ns_enum import ns +from natsort.utils import ( + _float_sign_exp_re, + _float_nosign_exp_re, + _float_sign_noexp_re, + _float_nosign_noexp_re, + _int_nosign_re, + _int_sign_re, + _parse_string_function, + _parse_path_function, +) +from natsort.compat.py23 import py23_str +from natsort.compat.fastnumbers import ( + fast_float, + fast_int, +) +from slow_splitters import ( + int_splitter, + float_splitter, +) +from compat.hypothesis import ( + assume, + given, + example, + lists, + text, + floats, + integers, + use_hypothesis, +) + +if sys.version[0] == '3': + long = int + + +def whitespace_check(x): + """Simplifies testing""" + try: + if x.isspace(): + return x in ' \t\n\r\f\v' + else: + return True + except (AttributeError, TypeError): + return True + + +def no_op(x): + """A function that does nothing.""" + return x + + +def tuple2(x, dummy): + """Make the input a tuple.""" + return tuple(x) + + +# Each test has an "example" version for demonstrative purposes, +# and a test that uses the hypothesis module. + + +def test_parse_string_function_raises_TypeError_if_given_a_number_example(): + with raises(TypeError): + assert _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)(50.0) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(floats()) +def test_parse_string_function_raises_TypeError_if_given_a_number(x): + with raises(TypeError): + assert _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)(x) + + +def test_parse_string_function_only_parses_digits_with_nosign_int_example(): + assert _parse_string_function(0, '', _int_nosign_re.split, no_op, fast_int, tuple2)('a5+5.034e-1') == ('a', 5, '+', 5, '.', 34, 'e-', 1) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +@example([10000000000000000000000000000000000000000000000000000000000000000000000000, + 100000000000000000000000000000000000000000000000000000000000000000000000000, + 100000000000000000000000000000000000000000000000000000000000000000000000000]) +def test_parse_string_function_only_parses_digits_with_nosign_int(x): + assume(all(whitespace_check(y) for y in x)) + s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) + assert _parse_string_function(0, '', _int_nosign_re.split, no_op, fast_int, tuple2)(s) == int_splitter(s, False, '') + + +def test_parse_string_function_parses_digit_with_sign_with_signed_int_example(): + assert _parse_string_function(0, '', _int_sign_re.split, no_op, fast_int, tuple2)('a5+5.034e-1') == ('a', 5, '', 5, '.', 34, 'e', -1) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +def test_parse_string_function_parses_digit_with_sign_with_signed_int(x): + assume(all(whitespace_check(y) for y in x)) + s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) + assert _parse_string_function(0, '', _int_sign_re.split, no_op, fast_int, tuple2)(s) == int_splitter(s, True, '') + + +def test_parse_string_function_only_parses_float_with_nosign_noexp_float_example(): + assert _parse_string_function(0, '', _float_nosign_noexp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '+', 5.034, 'e-', 1.0) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +def test_parse_string_function_only_parses_float_with_nosign_noexp_float(x): + assume(not any(type(y) == float and isnan(y) for y in x)) + assume(all(whitespace_check(y) for y in x)) + s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) + assert _parse_string_function(0, '', _float_nosign_noexp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, False, False, '') + + +def test_parse_string_function_only_parses_float_with_exponent_with_nosign_exp_float_example(): + assert _parse_string_function(0, '', _float_nosign_exp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '+', 0.5034) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +def test_parse_string_function_only_parses_float_with_exponent_with_nosign_exp_float(x): + assume(not any(type(y) == float and isnan(y) for y in x)) + assume(all(whitespace_check(y) for y in x)) + s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) + assert _parse_string_function(0, '', _float_nosign_exp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, False, True, '') + + +def test_parse_string_function_only_parses_float_with_sign_with_sign_noexp_float_example(): + assert _parse_string_function(0, '', _float_sign_noexp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '', 5.034, 'e', -1.0) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +def test_parse_string_function_only_parses_float_with_sign_with_sign_noexp_float(x): + assume(not any(type(y) == float and isnan(y) for y in x)) + assume(all(whitespace_check(y) for y in x)) + s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) + assert _parse_string_function(0, '', _float_sign_noexp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, True, False, '') + + +def test_parse_string_function_parses_float_with_sign_exp_float_example(): + assert _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '', 0.5034) + assert _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)('6a5+5.034e-1') == ('', 6.0, 'a', 5.0, '', 0.5034) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) +def test_parse_string_function_parses_float_with_sign_exp_float(x): + assume(not any(type(y) == float and isnan(y) for y in x)) + assume(all(whitespace_check(y) for y in x)) + s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) + assert _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, True, True, '') + + +def test_parse_string_function_selects_pre_function_value_if_not_dumb(): + def tuple2(x, orig): + """Make the input a tuple.""" + return (orig[0], tuple(x)) + assert _parse_string_function(0, '', _int_nosign_re.split, py23_str.upper, fast_float, tuple2)('a5+5.034e-1') == ('A', ('A', 5, '+', 5, '.', 34, 'E-', 1)) + assert _parse_string_function(ns._DUMB, '', _int_nosign_re.split, py23_str.upper, fast_float, tuple2)('a5+5.034e-1') == ('A', ('A', 5, '+', 5, '.', 34, 'E-', 1)) + assert _parse_string_function(ns.LOCALE, '', _int_nosign_re.split, py23_str.upper, fast_float, tuple2)('a5+5.034e-1') == ('A', ('A', 5, '+', 5, '.', 34, 'E-', 1)) + assert _parse_string_function(ns.LOCALE | ns._DUMB, '', _int_nosign_re.split, py23_str.upper, fast_float, tuple2)('a5+5.034e-1') == ('a', ('A', 5, '+', 5, '.', 34, 'E-', 1)) + + +def test_parse_path_function_parses_string_as_path_then_as_string(): + splt = _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2) + assert _parse_path_function(splt)('/p/Folder (10)/file34.5nm (2).tar.gz') == (('/',), ('p', ), ('Folder (', 10.0, ')',), ('file', 34.5, 'nm (', 2.0, ')'), ('.tar',), ('.gz',)) + assert _parse_path_function(splt)('../Folder (10)/file (2).tar.gz') == (('..', ), ('Folder (', 10.0, ')',), ('file (', 2.0, ')'), ('.tar',), ('.gz',)) + assert _parse_path_function(splt)('Folder (10)/file.f34.5nm (2).tar.gz') == (('Folder (', 10.0, ')',), ('file.f', 34.5, 'nm (', 2.0, ')'), ('.tar',), ('.gz',)) diff --git a/test_natsort/test_post_split_function.py b/test_natsort/test_post_split_function.py new file mode 100644 index 0000000..e4bffe2 --- /dev/null +++ b/test_natsort/test_post_split_function.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +"""These test the utils.py functions.""" +from __future__ import unicode_literals + +import pytest +from natsort.ns_enum import ns +from natsort.utils import _post_split_function +from natsort.locale_help import ( + locale_convert_function, + groupletters, +) +from natsort.compat.py23 import py23_str +from natsort.compat.fastnumbers import ( + fast_float, + fast_int, +) +from compat.hypothesis import ( + assume, + given, + text, + floats, + integers, + use_hypothesis, +) +from compat.locale import bad_uni_chars + + +# Each test has an "example" version for demonstrative purposes, +# and a test that uses the hypothesis module. + + +def test_post_split_function_returns_fast_int_example(): + x = 'hello' + assert _post_split_function(0)(x) is fast_int(x) + assert _post_split_function(0)('5007') == fast_int('5007') + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text() | floats() | integers()) +def test_post_split_function_returns_fast_int(x): + assume(x) + assert _post_split_function(0)(py23_str(x)) == fast_int(py23_str(x)) + + +def test_post_split_function_with_FLOAT_returns_fast_float_example(): + x = 'hello' + assert _post_split_function(ns.FLOAT)(x) is fast_float(x) + assert _post_split_function(ns.FLOAT)('5007') == fast_float('5007') + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text() | floats() | integers()) +def test_post_split_function_with_FLOAT_returns_fast_float(x): + assume(x) + assert _post_split_function(ns.FLOAT)(py23_str(x)) == fast_float(py23_str(x), nan=float('-inf')) + + +def test_post_split_function_with_FLOAT_returns_fast_float_with_neg_inf_replacing_nan(): + assert _post_split_function(ns.FLOAT)('nan') == fast_float('nan', nan=float('-inf')) + + +def test_post_split_function_with_FLOAT_and_NANLAST_returns_fast_float_with_pos_inf_replacing_nan(): + assert _post_split_function(ns.FLOAT | ns.NANLAST)('nan') == fast_float('nan', nan=float('+inf')) + + +def test_post_split_function_with_GROUPLETTERS_returns_fast_int_and_groupletters_example(): + x = 'hello' + assert _post_split_function(ns.GROUPLETTERS)(x) == fast_int(x, key=groupletters) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_post_split_function_with_GROUPLETTERS_returns_fast_int_and_groupletters(x): + assume(x) + assert _post_split_function(ns.GROUPLETTERS)(x) == fast_int(x, key=groupletters) + + +def test_post_split_function_with_LOCALE_returns_fast_int_and_groupletters_example(): + x = 'hello' + assert _post_split_function(ns.LOCALE)(x) == fast_int(x, key=locale_convert_function()) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_post_split_function_with_LOCALE_returns_fast_int_and_groupletters(x): + assume(x) + assume(not any(y in bad_uni_chars for y in x)) + assert _post_split_function(ns.LOCALE)(x) == fast_int(x, key=locale_convert_function()) + + +def test_post_split_function_with_LOCALE_and_GROUPLETTERS_returns_fast_int_and_groupletters_and_locale_convert_example(): + x = 'hello' + assert _post_split_function(ns.GROUPLETTERS | ns.LOCALE)(x) == fast_int(x, key=lambda x: locale_convert_function()(groupletters(x))) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_post_split_function_with_LOCALE_and_GROUPLETTERS_returns_fast_int_and_groupletters_and_locale_convert(x): + assume(x) + try: + assert _post_split_function(ns.GROUPLETTERS | ns.LOCALE)(x) == fast_int(x, key=lambda x: locale_convert_function()(groupletters(x))) + except ValueError as e: # handle broken locale lib on BSD. + if 'is not in range' not in str(e): + raise + + +def test_post_split_function_with_LOCALE_and_DUMB_returns_fast_int_and_groupletters_and_locale_convert_example(): + x = 'hello' + assert _post_split_function(ns._DUMB | ns.LOCALE)(x) == fast_int(x, key=lambda x: locale_convert_function()(groupletters(x))) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_post_split_function_with_LOCALE_and_DUMB_returns_fast_int_and_groupletters_and_locale_convert(x): + assume(x) + try: + assert _post_split_function(ns._DUMB | ns.LOCALE)(x) == fast_int(x, key=lambda x: locale_convert_function()(groupletters(x))) + except ValueError as e: # handle broken locale lib on BSD. + if 'is not in range' not in str(e): + raise diff --git a/test_natsort/test_post_string_parse_function.py b/test_natsort/test_post_string_parse_function.py new file mode 100644 index 0000000..0d6b433 --- /dev/null +++ b/test_natsort/test_post_string_parse_function.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +"""These test the utils.py functions.""" +from __future__ import unicode_literals + +import pytest +from math import isnan, isinf +from natsort.ns_enum import ns +from natsort.utils import _post_string_parse_function +from natsort.compat.py23 import py23_str +from natsort.compat.locale import use_pyicu +from compat.hypothesis import ( + assume, + given, + text, + floats, + integers, + use_hypothesis, +) + + +# Each test has an "example" version for demonstrative purposes, +# and a test that uses the hypothesis module. + + +def test_post_string_parse_function_with_iterable_returns_tuple_with_no_options_example(): + assert _post_string_parse_function(0, '')(iter([7]), '') == (7, ) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_post_string_parse_function_with_iterable_returns_tuple_with_no_options(x): + assert _post_string_parse_function(0, '')(iter([x]), '') == (x, ) + + +def test_post_string_parse_function_with_empty_tuple_returns_double_empty_tuple(): + assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS, '')((), '') == ((), ()) + + +def test_post_string_parse_function_with_null_string_first_element_adds_empty_string_on_first_tuple_element(): + assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS, '')(('', 60), '') == ((b'',) if use_pyicu else ('',), ('', 60)) + + +def test_post_string_parse_function_returns_first_element_in_first_tuple_element_example(): + assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS, '')(('this', 60), 'this60') == (('t',), ('this', 60)) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(x=text(), y=floats() | integers()) +def test_post_string_parse_function_returns_first_element_in_first_tuple_element(x, y): + assume(x) + assume(not isnan(y)) + assume(not isinf(y)) + assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS, '')((x, y), ''.join(map(py23_str, [x, y]))) == ((x[0],), (x, y)) + + +def test_post_string_parse_function_returns_first_element_in_first_tuple_element_caseswapped_with_DUMB_and_LOWERCASEFIRST_example(): + assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS | ns._DUMB | ns.LOWERCASEFIRST, '')(('this', 60), 'this60') == (('T',), ('this', 60)) + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(x=text(), y=floats() | integers()) +def test_post_string_parse_function_returns_first_element_in_first_tuple_element_caseswapped_with_DUMB_and_LOWERCASEFIRST(x, y): + assume(x) + assume(not isnan(y)) + assume(not isinf(y)) + assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS | ns._DUMB | ns.LOWERCASEFIRST, '')((x, y), ''.join(map(py23_str, [x, y]))) == ((x[0].swapcase(),), (x, y)) diff --git a/test_natsort/test_pre_split_function.py b/test_natsort/test_pre_split_function.py new file mode 100644 index 0000000..d32c95b --- /dev/null +++ b/test_natsort/test_pre_split_function.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +"""These test the utils.py functions.""" +from __future__ import unicode_literals + +import sys +import pytest +from natsort.ns_enum import ns +from natsort.utils import _pre_split_function +from compat.hypothesis import ( + given, + text, + use_hypothesis, +) + + +# Each test has an "example" version for demonstrative purposes, +# and a test that uses the hypothesis module. + + +def test_pre_split_function_is_no_op_for_no_alg_options_examples(): + x = 'feijGGAd' + assert _pre_split_function(0)(x) is x + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_pre_split_function_is_no_op_for_no_alg_options(x): + assert _pre_split_function(0)(x) is x + + +def test_pre_split_function_performs_casefold_with_IGNORECASE_examples(): + x = 'feijGGAd' + if sys.version_info[0:2] >= (3, 3): + assert _pre_split_function(ns.IGNORECASE)(x) == x.casefold() + else: + assert _pre_split_function(ns.IGNORECASE)(x) == x.lower() + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_pre_split_function_performs_casefold_with_IGNORECASE(x): + if sys.version_info[0:2] >= (3, 3): + assert _pre_split_function(ns.IGNORECASE)(x) == x.casefold() + else: + assert _pre_split_function(ns.IGNORECASE)(x) == x.lower() + + +def test_pre_split_function_performs_swapcase_with_DUMB_examples(): + x = 'feijGGAd' + assert _pre_split_function(ns._DUMB)(x) == x.swapcase() + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_pre_split_function_performs_swapcase_with_DUMB(x): + assert _pre_split_function(ns._DUMB)(x) == x.swapcase() + + +def test_pre_split_function_performs_swapcase_with_LOWERCASEFIRST_example(): + x = 'feijGGAd' + assert _pre_split_function(ns.LOWERCASEFIRST)(x) == x.swapcase() + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_pre_split_function_performs_swapcase_with_LOWERCASEFIRST(x): + x = 'feijGGAd' + assert _pre_split_function(ns.LOWERCASEFIRST)(x) == x.swapcase() + + +def test_pre_split_function_is_no_op_with_both_LOWERCASEFIRST_AND_DUMB_example(): + x = 'feijGGAd' + assert _pre_split_function(ns._DUMB | ns.LOWERCASEFIRST)(x) is x + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_pre_split_function_is_no_op_with_both_LOWERCASEFIRST_AND_DUMB(x): + assert _pre_split_function(ns._DUMB | ns.LOWERCASEFIRST)(x) is x + + +def test_pre_split_function_performs_swapcase_and_casefold_both_LOWERCASEFIRST_AND_IGNORECASE_example(): + x = 'feijGGAd' + if sys.version_info[0:2] >= (3, 3): + assert _pre_split_function(ns.IGNORECASE | ns.LOWERCASEFIRST)(x) == x.swapcase().casefold() + else: + assert _pre_split_function(ns.IGNORECASE | ns.LOWERCASEFIRST)(x) == x.swapcase().lower() + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(text()) +def test_pre_split_function_performs_swapcase_and_casefold_both_LOWERCASEFIRST_AND_IGNORECASE(x): + if sys.version_info[0:2] >= (3, 3): + assert _pre_split_function(ns.IGNORECASE | ns.LOWERCASEFIRST)(x) == x.swapcase().casefold() + else: + assert _pre_split_function(ns.IGNORECASE | ns.LOWERCASEFIRST)(x) == x.swapcase().lower() diff --git a/test_natsort/test_unicode_numbers.py b/test_natsort/test_unicode_numbers.py index 56570b1..1b897eb 100644 --- a/test_natsort/test_unicode_numbers.py +++ b/test_natsort/test_unicode_numbers.py @@ -24,9 +24,10 @@ def test_digit_chars_contains_only_valid_unicode_digit_characters(): assert unicodedata.digit(a, None) is not None -def test_numeric_chars_contains_all_valid_unicode_numeric_characters(): +def test_numeric_chars_contains_all_valid_unicode_numeric_and_digit_characters(): set_numeric_hex = set(numeric_hex) set_numeric_chars = set(numeric_chars) + set_digit_chars = set(digit_chars) for i in py23_range(0X110000): try: a = py23_unichr(i) @@ -37,21 +38,9 @@ def test_numeric_chars_contains_all_valid_unicode_numeric_characters(): if unicodedata.numeric(a, None) is not None: assert i in set_numeric_hex assert a in set_numeric_chars - - -def test_digit_chars_contains_all_valid_unicode_digit_characters(): - set_numeric_hex = set(numeric_hex) - set_numeric_chars = set(numeric_chars) - for i in py23_range(0X110000): - try: - a = py23_unichr(i) - except ValueError: - break - if a in set('0123456789'): - continue if unicodedata.digit(a, None) is not None: assert i in set_numeric_hex - assert a in set_numeric_chars + assert a in set_digit_chars def test_combined_string_contains_all_characters_in_list(): diff --git a/test_natsort/test_utils.py b/test_natsort/test_utils.py index 82bfec4..6bb5818 100644 --- a/test_natsort/test_utils.py +++ b/test_natsort/test_utils.py @@ -2,17 +2,14 @@ """These test the utils.py functions.""" from __future__ import unicode_literals -import sys import pathlib import pytest import string -from math import isnan, isinf from operator import neg as op_neg from pytest import raises from natsort.ns_enum import ns from natsort.utils import ( _sep_inserter, - _natsort_key, _args_to_enum, _regex_chooser, _float_sign_exp_re, @@ -24,60 +21,22 @@ from natsort.utils import ( _do_decoding, _path_splitter, chain_functions, - _parse_string_function, - _parse_path_function, - _parse_number_function, - _parse_bytes_function, - _pre_split_function, - _post_split_function, - _post_string_parse_function, -) -from natsort.locale_help import ( - locale_convert_function, - groupletters, ) from natsort.compat.py23 import py23_str -from natsort.compat.locale import ( - use_pyicu, - null_string, -) -from natsort.compat.fastnumbers import ( - fast_float, - fast_int, -) +from natsort.compat.locale import null_string from slow_splitters import ( - int_splitter, - float_splitter, sep_inserter, add_leading_space_if_first_is_num, ) from compat.hypothesis import ( assume, given, - example, sampled_from, lists, text, - floats, integers, - binary, use_hypothesis, ) -from compat.locale import bad_uni_chars - -if sys.version[0] == '3': - long = int - - -def whitespace_check(x): - """Simplifies testing""" - try: - if x.isspace(): - return x in ' \t\n\r\f\v' - else: - return True - except (AttributeError, TypeError): - return True def test_do_decoding_decodes_bytes_string_to_unicode(): @@ -205,284 +164,6 @@ def test_chain_functions_combines_functions_in_given_order(): # and a test that uses the hypothesis module. -def test_pre_split_function_is_no_op_for_no_alg_options_examples(): - x = 'feijGGAd' - assert _pre_split_function(0)(x) is x - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_pre_split_function_is_no_op_for_no_alg_options(x): - assert _pre_split_function(0)(x) is x - - -def test_pre_split_function_performs_casefold_with_IGNORECASE_examples(): - x = 'feijGGAd' - if sys.version_info[0:2] >= (3, 3): - assert _pre_split_function(ns.IGNORECASE)(x) == x.casefold() - else: - assert _pre_split_function(ns.IGNORECASE)(x) == x.lower() - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_pre_split_function_performs_casefold_with_IGNORECASE(x): - if sys.version_info[0:2] >= (3, 3): - assert _pre_split_function(ns.IGNORECASE)(x) == x.casefold() - else: - assert _pre_split_function(ns.IGNORECASE)(x) == x.lower() - - -def test_pre_split_function_performs_swapcase_with_DUMB_examples(): - x = 'feijGGAd' - assert _pre_split_function(ns._DUMB)(x) == x.swapcase() - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_pre_split_function_performs_swapcase_with_DUMB(x): - assert _pre_split_function(ns._DUMB)(x) == x.swapcase() - - -def test_pre_split_function_performs_swapcase_with_LOWERCASEFIRST_example(): - x = 'feijGGAd' - assert _pre_split_function(ns.LOWERCASEFIRST)(x) == x.swapcase() - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_pre_split_function_performs_swapcase_with_LOWERCASEFIRST(x): - x = 'feijGGAd' - assert _pre_split_function(ns.LOWERCASEFIRST)(x) == x.swapcase() - - -def test_pre_split_function_is_no_op_with_both_LOWERCASEFIRST_AND_DUMB_example(): - x = 'feijGGAd' - assert _pre_split_function(ns._DUMB | ns.LOWERCASEFIRST)(x) is x - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_pre_split_function_is_no_op_with_both_LOWERCASEFIRST_AND_DUMB(x): - assert _pre_split_function(ns._DUMB | ns.LOWERCASEFIRST)(x) is x - - -def test_pre_split_function_performs_swapcase_and_casefold_both_LOWERCASEFIRST_AND_IGNORECASE_example(): - x = 'feijGGAd' - if sys.version_info[0:2] >= (3, 3): - assert _pre_split_function(ns.IGNORECASE | ns.LOWERCASEFIRST)(x) == x.swapcase().casefold() - else: - assert _pre_split_function(ns.IGNORECASE | ns.LOWERCASEFIRST)(x) == x.swapcase().lower() - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_pre_split_function_performs_swapcase_and_casefold_both_LOWERCASEFIRST_AND_IGNORECASE(x): - if sys.version_info[0:2] >= (3, 3): - assert _pre_split_function(ns.IGNORECASE | ns.LOWERCASEFIRST)(x) == x.swapcase().casefold() - else: - assert _pre_split_function(ns.IGNORECASE | ns.LOWERCASEFIRST)(x) == x.swapcase().lower() - - -def test_post_split_function_returns_fast_int_example(): - x = 'hello' - assert _post_split_function(0)(x) is fast_int(x) - assert _post_split_function(0)('5007') == fast_int('5007') - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text() | floats() | integers()) -def test_post_split_function_returns_fast_int(x): - assume(x) - assert _post_split_function(0)(py23_str(x)) == fast_int(py23_str(x)) - - -def test_post_split_function_with_FLOAT_returns_fast_float_example(): - x = 'hello' - assert _post_split_function(ns.FLOAT)(x) is fast_float(x) - assert _post_split_function(ns.FLOAT)('5007') == fast_float('5007') - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text() | floats() | integers()) -def test_post_split_function_with_FLOAT_returns_fast_float(x): - assume(x) - assert _post_split_function(ns.FLOAT)(py23_str(x)) == fast_float(py23_str(x), nan=float('-inf')) - - -def test_post_split_function_with_FLOAT_returns_fast_float_with_neg_inf_replacing_nan(): - assert _post_split_function(ns.FLOAT)('nan') == fast_float('nan', nan=float('-inf')) - - -def test_post_split_function_with_FLOAT_and_NANLAST_returns_fast_float_with_pos_inf_replacing_nan(): - assert _post_split_function(ns.FLOAT | ns.NANLAST)('nan') == fast_float('nan', nan=float('+inf')) - - -def test_post_split_function_with_GROUPLETTERS_returns_fast_int_and_groupletters_example(): - x = 'hello' - assert _post_split_function(ns.GROUPLETTERS)(x) == fast_int(x, key=groupletters) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_post_split_function_with_GROUPLETTERS_returns_fast_int_and_groupletters(x): - assume(x) - assert _post_split_function(ns.GROUPLETTERS)(x) == fast_int(x, key=groupletters) - - -def test_post_split_function_with_LOCALE_returns_fast_int_and_groupletters_example(): - x = 'hello' - assert _post_split_function(ns.LOCALE)(x) == fast_int(x, key=locale_convert_function()) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_post_split_function_with_LOCALE_returns_fast_int_and_groupletters(x): - assume(x) - assume(not any(y in bad_uni_chars for y in x)) - assert _post_split_function(ns.LOCALE)(x) == fast_int(x, key=locale_convert_function()) - - -def test_post_split_function_with_LOCALE_and_GROUPLETTERS_returns_fast_int_and_groupletters_and_locale_convert_example(): - x = 'hello' - assert _post_split_function(ns.GROUPLETTERS | ns.LOCALE)(x) == fast_int(x, key=lambda x: locale_convert_function()(groupletters(x))) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_post_split_function_with_LOCALE_and_GROUPLETTERS_returns_fast_int_and_groupletters_and_locale_convert(x): - assume(x) - try: - assert _post_split_function(ns.GROUPLETTERS | ns.LOCALE)(x) == fast_int(x, key=lambda x: locale_convert_function()(groupletters(x))) - except ValueError as e: # handle broken locale lib on BSD. - if 'is not in range' not in str(e): - raise - - -def test_post_split_function_with_LOCALE_and_DUMB_returns_fast_int_and_groupletters_and_locale_convert_example(): - x = 'hello' - assert _post_split_function(ns._DUMB | ns.LOCALE)(x) == fast_int(x, key=lambda x: locale_convert_function()(groupletters(x))) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_post_split_function_with_LOCALE_and_DUMB_returns_fast_int_and_groupletters_and_locale_convert(x): - assume(x) - try: - assert _post_split_function(ns._DUMB | ns.LOCALE)(x) == fast_int(x, key=lambda x: locale_convert_function()(groupletters(x))) - except ValueError as e: # handle broken locale lib on BSD. - if 'is not in range' not in str(e): - raise - - -def test_post_string_parse_function_with_iterable_returns_tuple_with_no_options_example(): - assert _post_string_parse_function(0, '')(iter([7]), '') == (7, ) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test_post_string_parse_function_with_iterable_returns_tuple_with_no_options(x): - assert _post_string_parse_function(0, '')(iter([x]), '') == (x, ) - - -def test_post_string_parse_function_with_empty_tuple_returns_double_empty_tuple(): - assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS, '')((), '') == ((), ()) - - -def test_post_string_parse_function_with_null_string_first_element_adds_empty_string_on_first_tuple_element(): - assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS, '')(('', 60), '') == ((b'',) if use_pyicu else ('',), ('', 60)) - - -def test_post_string_parse_function_returns_first_element_in_first_tuple_element_example(): - assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS, '')(('this', 60), 'this60') == (('t',), ('this', 60)) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(x=text(), y=floats() | integers()) -def test_post_string_parse_function_returns_first_element_in_first_tuple_element(x, y): - assume(x) - assume(not isnan(y)) - assume(not isinf(y)) - assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS, '')((x, y), ''.join(map(py23_str, [x, y]))) == ((x[0],), (x, y)) - - -def test_post_string_parse_function_returns_first_element_in_first_tuple_element_caseswapped_with_DUMB_and_LOWERCASEFIRST_example(): - assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS | ns._DUMB | ns.LOWERCASEFIRST, '')(('this', 60), 'this60') == (('T',), ('this', 60)) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(x=text(), y=floats() | integers()) -def test_post_string_parse_function_returns_first_element_in_first_tuple_element_caseswapped_with_DUMB_and_LOWERCASEFIRST(x, y): - assume(x) - assume(not isnan(y)) - assume(not isinf(y)) - assert _post_string_parse_function(ns.LOCALE | ns.UNGROUPLETTERS | ns._DUMB | ns.LOWERCASEFIRST, '')((x, y), ''.join(map(py23_str, [x, y]))) == ((x[0].swapcase(),), (x, y)) - - -def test_parse_number_function_makes_function_that_returns_tuple_example(): - assert _parse_number_function(0, '')(57) == ('', 57) - assert _parse_number_function(0, '')(float('nan')) == ('', float('-inf')) - assert _parse_number_function(ns.NANLAST, '')(float('nan')) == ('', float('+inf')) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(floats() | integers()) -def test_parse_number_function_makes_function_that_returns_tuple(x): - assume(not isnan(x)) - assert _parse_number_function(0, '')(x) == ('', x) - - -def test_parse_number_function_with_PATH_makes_function_that_returns_nested_tuple_example(): - assert _parse_number_function(ns.PATH, '')(57) == (('', 57), ) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(floats() | integers()) -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_bytes_function_makes_function_that_returns_tuple_example(): - assert _parse_bytes_function(0)(b'hello') == (b'hello', ) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(binary()) -def test_parse_bytes_function_makes_function_that_returns_tuple(x): - assert _parse_bytes_function(0)(x) == (x, ) - - -def test_parse_bytes_function_with_IGNORECASE_makes_function_that_returns_tuple_with_lowercase_example(): - assert _parse_bytes_function(ns.IGNORECASE)(b'HelLo') == (b'hello', ) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(binary()) -def test_parse_bytes_function_with_IGNORECASE_makes_function_that_returns_tuple_with_lowercase(x): - assert _parse_bytes_function(ns.IGNORECASE)(x) == (x.lower(), ) - - -def test_parse_bytes_function_with_PATH_makes_function_that_returns_nested_tuple_example(): - assert _parse_bytes_function(ns.PATH)(b'hello') == ((b'hello', ), ) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(binary()) -def test_parse_bytes_function_with_PATH_makes_function_that_returns_nested_tuple(x): - assert _parse_bytes_function(ns.PATH)(x) == ((x, ), ) - - -def test_parse_bytes_function_with_PATH_and_IGNORECASE_makes_function_that_returns_nested_tuple_with_lowercase_example(): - assert _parse_bytes_function(ns.PATH | ns.IGNORECASE)(b'HelLo') == ((b'hello', ), ) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(binary()) -def test_parse_bytes_function_with_PATH_and_IGNORECASE_makes_function_that_returns_nested_tuple_with_lowercase(x): - assert _parse_bytes_function(ns.PATH | ns.IGNORECASE)(x) == ((x.lower(), ), ) - - def test_sep_inserter_does_nothing_if_no_numbers_example(): assert list(_sep_inserter(iter(['a', 'b', 'c']), '')) == ['a', 'b', 'c'] assert list(_sep_inserter(iter(['a']), '')) == ['a'] @@ -532,199 +213,3 @@ def test_path_splitter_splits_path_string_by_separator_and_removes_extension(x): z = py23_str(pathlib.Path(*x[:-2])) + '.' + x[-1] y = tuple(pathlib.Path(z).parts) assert tuple(_path_splitter(z)) == y[:-1] + (pathlib.Path(z).stem, pathlib.Path(z).suffix) - - -def no_op(x): - """A function that does nothing.""" - return x - - -def tuple2(x, dummy): - """Make the input a tuple.""" - return tuple(x) - - -def test_parse_string_function_raises_TypeError_if_given_a_number_example(): - with raises(TypeError): - assert _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)(50.0) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(floats()) -def test_parse_string_function_raises_TypeError_if_given_a_number(x): - with raises(TypeError): - assert _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)(x) - - -def test_parse_string_function_only_parses_digits_with_nosign_int_example(): - assert _parse_string_function(0, '', _int_nosign_re.split, no_op, fast_int, tuple2)('a5+5.034e-1') == ('a', 5, '+', 5, '.', 34, 'e-', 1) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) -@example([10000000000000000000000000000000000000000000000000000000000000000000000000, - 100000000000000000000000000000000000000000000000000000000000000000000000000, - 100000000000000000000000000000000000000000000000000000000000000000000000000]) -def test_parse_string_function_only_parses_digits_with_nosign_int(x): - assume(all(whitespace_check(y) for y in x)) - s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) - assert _parse_string_function(0, '', _int_nosign_re.split, no_op, fast_int, tuple2)(s) == int_splitter(s, False, '') - - -def test_parse_string_function_parses_digit_with_sign_with_signed_int_example(): - assert _parse_string_function(0, '', _int_sign_re.split, no_op, fast_int, tuple2)('a5+5.034e-1') == ('a', 5, '', 5, '.', 34, 'e', -1) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) -def test_parse_string_function_parses_digit_with_sign_with_signed_int(x): - assume(all(whitespace_check(y) for y in x)) - s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) - assert _parse_string_function(0, '', _int_sign_re.split, no_op, fast_int, tuple2)(s) == int_splitter(s, True, '') - - -def test_parse_string_function_only_parses_float_with_nosign_noexp_float_example(): - assert _parse_string_function(0, '', _float_nosign_noexp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '+', 5.034, 'e-', 1.0) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) -def test_parse_string_function_only_parses_float_with_nosign_noexp_float(x): - assume(not any(type(y) == float and isnan(y) for y in x)) - assume(all(whitespace_check(y) for y in x)) - s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) - assert _parse_string_function(0, '', _float_nosign_noexp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, False, False, '') - - -def test_parse_string_function_only_parses_float_with_exponent_with_nosign_exp_float_example(): - assert _parse_string_function(0, '', _float_nosign_exp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '+', 0.5034) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) -def test_parse_string_function_only_parses_float_with_exponent_with_nosign_exp_float(x): - assume(not any(type(y) == float and isnan(y) for y in x)) - assume(all(whitespace_check(y) for y in x)) - s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) - assert _parse_string_function(0, '', _float_nosign_exp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, False, True, '') - - -def test_parse_string_function_only_parses_float_with_sign_with_sign_noexp_float_example(): - assert _parse_string_function(0, '', _float_sign_noexp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '', 5.034, 'e', -1.0) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) -def test_parse_string_function_only_parses_float_with_sign_with_sign_noexp_float(x): - assume(not any(type(y) == float and isnan(y) for y in x)) - assume(all(whitespace_check(y) for y in x)) - s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) - assert _parse_string_function(0, '', _float_sign_noexp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, True, False, '') - - -def test_parse_string_function_parses_float_with_sign_exp_float_example(): - assert _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)('a5+5.034e-1') == ('a', 5.0, '', 0.5034) - assert _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)('6a5+5.034e-1') == ('', 6.0, 'a', 5.0, '', 0.5034) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) -def test_parse_string_function_parses_float_with_sign_exp_float(x): - assume(not any(type(y) == float and isnan(y) for y in x)) - assume(all(whitespace_check(y) for y in x)) - s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) - assert _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2)(s) == float_splitter(s, True, True, '') - - -def test_parse_string_function_selects_pre_function_value_if_not_dumb(): - def tuple2(x, orig): - """Make the input a tuple.""" - return (orig[0], tuple(x)) - assert _parse_string_function(0, '', _int_nosign_re.split, py23_str.upper, fast_float, tuple2)('a5+5.034e-1') == ('A', ('A', 5, '+', 5, '.', 34, 'E-', 1)) - assert _parse_string_function(ns._DUMB, '', _int_nosign_re.split, py23_str.upper, fast_float, tuple2)('a5+5.034e-1') == ('A', ('A', 5, '+', 5, '.', 34, 'E-', 1)) - assert _parse_string_function(ns.LOCALE, '', _int_nosign_re.split, py23_str.upper, fast_float, tuple2)('a5+5.034e-1') == ('A', ('A', 5, '+', 5, '.', 34, 'E-', 1)) - assert _parse_string_function(ns.LOCALE | ns._DUMB, '', _int_nosign_re.split, py23_str.upper, fast_float, tuple2)('a5+5.034e-1') == ('a', ('A', 5, '+', 5, '.', 34, 'E-', 1)) - - -def test_parse_path_function_parses_string_as_path_then_as_string(): - splt = _parse_string_function(0, '', _float_sign_exp_re.split, no_op, fast_float, tuple2) - assert _parse_path_function(splt)('/p/Folder (10)/file34.5nm (2).tar.gz') == (('/',), ('p', ), ('Folder (', 10.0, ')',), ('file', 34.5, 'nm (', 2.0, ')'), ('.tar',), ('.gz',)) - assert _parse_path_function(splt)('../Folder (10)/file (2).tar.gz') == (('..', ), ('Folder (', 10.0, ')',), ('file (', 2.0, ')'), ('.tar',), ('.gz',)) - assert _parse_path_function(splt)('Folder (10)/file.f34.5nm (2).tar.gz') == (('Folder (', 10.0, ')',), ('file.f', 34.5, 'nm (', 2.0, ')'), ('.tar',), ('.gz',)) - - -# Just a few tests to make sure _natsort_key is working - -regex = _regex_chooser[ns.INT] -pre = _pre_split_function(ns.INT) -post = _post_split_function(ns.INT) -after = _post_string_parse_function(ns.INT, '') -string_func = _parse_string_function(ns.INT, '', regex.split, pre, post, after) -bytes_func = _parse_bytes_function(ns.INT) -num_func = _parse_number_function(ns.INT, '') - - -def test__natsort_key_with_numeric_input_and_PATH_returns_number_in_nested_tuple(): - # It gracefully handles as_path for numeric input by putting an extra tuple around it - # so it will sort against the other as_path results. - sfunc = _parse_path_function(string_func) - bytes_func = _parse_bytes_function(ns.PATH) - num_func = _parse_number_function(ns.PATH, '') - assert _natsort_key(10, None, sfunc, bytes_func, num_func) == (('', 10),) - - -if sys.version[0] == '3': - def test__natsort_key_with_bytes_input_and_PATH_returns_number_in_nested_tuple(): - # It gracefully handles as_path for numeric input by putting an extra tuple around it - # so it will sort against the other as_path results. - sfunc = _parse_path_function(string_func) - bytes_func = _parse_bytes_function(ns.PATH) - num_func = _parse_number_function(ns.PATH, '') - assert _natsort_key(b'/hello/world', None, sfunc, bytes_func, num_func) == ((b'/hello/world',),) - - -def test__natsort_key_with_tuple_of_paths_and_PATH_returns_triply_nested_tuple(): - # PATH also handles recursion well. - sfunc = _parse_path_function(string_func) - bytes_func = _parse_bytes_function(ns.PATH) - num_func = _parse_number_function(ns.PATH, '') - assert _natsort_key(('/Folder', '/Folder (1)'), None, sfunc, bytes_func, num_func) == ((('/',), ('Folder',)), (('/',), ('Folder (', 1, ')'))) - - -# The remaining tests provide no examples, just hypothesis tests. -# They only confirm that _natsort_key uses the above building blocks. - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(floats() | integers()) -def test__natsort_key_with_numeric_input_takes_number_path(x): - assume(not isnan(x)) - assert _natsort_key(x, None, string_func, bytes_func, num_func) == num_func(x) - - -if sys.version[0] == '3': - @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') - @given(binary()) - def test__natsort_key_with_bytes_input_takes_bytes_path(x): - assume(x) - assert _natsort_key(x, None, string_func, bytes_func, num_func) == bytes_func(x) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) -def test__natsort_key_with_text_input_takes_string_path(x): - assume(not any(type(y) == float and isnan(y) for y in x)) - s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) - assert _natsort_key(s, None, string_func, bytes_func, num_func) == string_func(s) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(lists(elements=text(), min_size=1, max_size=10)) -def test__natsort_key_with_nested_input_takes_nested_path(x): - assert _natsort_key(x, None, string_func, bytes_func, num_func) == tuple(string_func(s) for s in x) - - -@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(text()) -def test__natsort_key_with_key_argument_applies_key_before_processing(x): - assert _natsort_key(x, len, string_func, bytes_func, num_func) == num_func(len(x)) |
