def test__natsort_key_with_version_or_digit_matches_usigned_int(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, ns.VERSION) == _natsort_key(s, None, ns.INT | ns.UNSIGNED) assert _natsort_key(s, None, ns.DIGIT) == _natsort_key(s, None, ns.VERSION)
def test__natsort_key_with_IGNORECASE_lowercases_text(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) try: assert _natsort_key(s, None, ns.IGNORECASE) == tuple(_number_extracter(s.casefold(), _int_nosign_re, *int_nosafe_nolocale_nogroup)) except AttributeError: assert _natsort_key(s, None, ns.IGNORECASE) == tuple(_number_extracter(s.lower(), _int_nosign_re, *int_nosafe_nolocale_nogroup))
def test__natsort_key_with_float_and_unsigned_splits_input_into_string_and_unsigned_float(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 ns.U == ns.UNSIGNED assert _natsort_key(s, None, ns.F | ns.U) == tuple(_number_extracter(s, _float_nosign_exp_re, *float_nosafe_nolocale_nogroup)) # Default is unsigned search assert _natsort_key(s, None, ns.F) == tuple(_number_extracter(s, _float_nosign_exp_re, *float_nosafe_nolocale_nogroup))
def test__natsort_key_with_invalid_alg_input_raises_ValueError(): # Invalid arguments give the correct response with raises(ValueError) as err: _natsort_key('a', None, '1') assert str( err.value ) == "_natsort_key: 'alg' argument must be from the enum 'ns', got 1"
def test__natsort_key_with_version_or_digit_matches_usigned_int(): assert _natsort_key('a-5.034e2', None, ns.VERSION) == _natsort_key('a-5.034e2', None, ns.INT | ns.UNSIGNED) assert _natsort_key('a-5.034e2', None, ns.DIGIT) == _natsort_key('a-5.034e2', None, ns.VERSION)
def test__natsort_key_with_int_splits_and_signed_input_into_string_and_signed_int( 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, ns.INT | ns.SIGNED) == tuple( _number_extracter(s, _int_sign_re, *int_nosafe_nolocale_nogroup)) assert _natsort_key(s, None, ns.SIGNED) == tuple( _number_extracter(s, _int_sign_re, *int_nosafe_nolocale_nogroup))
def test__natsort_key_with_bytes_input_only_applies_LOWERCASEFIRST_or_IGNORECASE_and_returns_in_tuple(): if sys.version[0] == '3': assert _natsort_key(b'Apple56', None, ns.I) == (b'Apple56',) assert _natsort_key(b'Apple56', None, ns.LF) == (b'aPPLE56',) assert _natsort_key(b'Apple56', None, ns.IC) == (b'apple56',) assert _natsort_key(b'Apple56', None, ns.G) == (b'Apple56',) else: assert True
def test__natsort_key_with_bytes_input_only_applies_LOWERCASEFIRST_or_IGNORECASE_and_returns_in_tuple( ): if sys.version[0] == '3': assert _natsort_key(b'Apple56', None, ns.I) == (b'Apple56', ) assert _natsort_key(b'Apple56', None, ns.LF) == (b'aPPLE56', ) assert _natsort_key(b'Apple56', None, ns.IC) == (b'apple56', ) assert _natsort_key(b'Apple56', None, ns.G) == (b'Apple56', ) else: assert True
def test__natsort_key_with_int_splits_input_into_string_and_unsigned_int(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 ns.I == ns.INT assert _natsort_key(s, None, ns.INT) == tuple(_number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup)) # Default is int search assert _natsort_key(s, None, ns.NOEXP) == tuple(_number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup)) # NOEXP is ignored for integers assert _natsort_key(s, None, ns.I | ns.NOEXP) == tuple(_number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup))
def test__natsort_key_with_LOCALE_transforms_floats_according_to_the_current_locale_and_strxfrms_strings(x): # Locale aware sorting 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) load_locale('en_US') if dumb_sort(): assert _natsort_key(s, None, ns.LOCALE | ns.F) == tuple(_number_extracter(s.swapcase(), _float_nosign_exp_re, *float_nosafe_locale_group)) else: assert _natsort_key(s, None, ns.LOCALE | ns.F) == tuple(_number_extracter(s, _float_nosign_exp_re, *float_nosafe_locale_nogroup)) locale.setlocale(locale.LC_NUMERIC, str(''))
def test__natsort_key_with_IGNORECASE_lowercases_text(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) try: assert _natsort_key(s, None, ns.IGNORECASE) == tuple( _number_extracter(s.casefold(), _int_nosign_re, *int_nosafe_nolocale_nogroup)) except AttributeError: assert _natsort_key(s, None, ns.IGNORECASE) == tuple( _number_extracter(s.lower(), _int_nosign_re, *int_nosafe_nolocale_nogroup))
def test__natsort_key_with_int_splits_input_into_string_and_unsigned_int(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 ns.I == ns.INT assert _natsort_key(s, None, ns.INT) == tuple( _number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup)) # Default is int search assert _natsort_key(s, None, ns.NOEXP) == tuple( _number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup)) # NOEXP is ignored for integers assert _natsort_key(s, None, ns.I | ns.NOEXP) == tuple( _number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup))
def test__natsort_key_with_float_and_unsigned_splits_input_into_string_and_unsigned_float( 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 ns.U == ns.UNSIGNED assert _natsort_key(s, None, ns.F | ns.U) == tuple( _number_extracter(s, _float_nosign_exp_re, *float_nosafe_nolocale_nogroup)) # Default is unsigned search assert _natsort_key(s, None, ns.F) == tuple( _number_extracter(s, _float_nosign_exp_re, *float_nosafe_nolocale_nogroup))
def test__natsort_key_with_LOCALE_transforms_floats_according_to_the_current_locale_and_strxfrms_strings( x): # Locale aware sorting 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) load_locale('en_US') if dumb_sort(): assert _natsort_key(s, None, ns.LOCALE | ns.F) == tuple( _number_extracter(s.swapcase(), _float_nosign_exp_re, *float_nosafe_locale_group)) else: assert _natsort_key(s, None, ns.LOCALE | ns.F) == tuple( _number_extracter(s, _float_nosign_exp_re, *float_nosafe_locale_nogroup)) locale.setlocale(locale.LC_NUMERIC, str(''))
def test__natsort_key_with_float_and_noexp_splits_input_into_string_and_unsigned_float_without_exponent( 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, ns.F | ns.N) == tuple( _number_extracter(s, _float_nosign_noexp_re, *float_nosafe_nolocale_nogroup))
def test__natsort_key_with_tuple_input_returns_nested_tuples(x): # Iterables are parsed recursively so you can sort lists of lists. 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) t = tuple( _number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup)) assert _natsort_key((s, s), None, ns.I) == (t, t)
def test__natsort_key_with_tuple_input_but_itemgetter_key_returns_split_second_element(x): # A key is applied before recursion, but not in the recursive calls. assume(len(x) <= 10) 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) t = tuple(_number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup)) assert _natsort_key((s, s), itemgetter(1), ns.I) == t
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_float_and_signed_splits_input_into_string_and_signed_float_with_exponent(x): assume(len(x) <= 10) 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 ns.F == ns.FLOAT assert ns.S == ns.SIGNED assert _natsort_key(s, None, ns.F | ns.S) == tuple(_number_extracter(s, _float_sign_exp_re, *float_nosafe_nolocale_nogroup))
def test__natsort_key_with_tuple_input_returns_nested_tuples(x): # Iterables are parsed recursively so you can sort lists of lists. assume(len(x) <= 10) 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) t = tuple(_number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup)) assert _natsort_key((s, s), None, ns.I) == (t, t)
def test__natsort_key_with_GROUPLETTERS_and_LOWERCASEFIRST_inverts_text_first_then_doubles_letters_with_lowercase_letter_first(x): assume(len(x) <= 10) assume(not any(type(y) == float and isnan(y) for y in x)) s = ''.join(ichain([repr(y)] if type(y) in (float, long, int) else [low(y), y] for y in x)) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) t = _number_extracter(s.swapcase(), _int_nosign_re, *int_nosafe_nolocale_nogroup) assert _natsort_key(s, None, ns.G | ns.LF) == tuple(''.join(low(z) + z for z in y) if type(y) not in (float, long, int) else y for y in t)
def test__natsort_key_with_LOCALE_and_UNGROUPLETTERS_places_space_before_string_with_capital_first_letter( x): # Locale aware sorting 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) load_locale('en_US') if dumb_sort(): t = tuple( _number_extracter(s.swapcase(), _float_nosign_exp_re, *float_nosafe_locale_group)) else: t = tuple( _number_extracter(s, _float_nosign_exp_re, *float_nosafe_locale_nogroup)) if not t: r = (t, t) elif t[0] in (null_string, get_strxfrm()(b'\x00') if sys.version[0] == '2' and not use_pyicu else null_string): r = ((b'' if use_pyicu else '', ), t) else: r = ((s[0], ), t) assert _natsort_key(s, None, ns.LOCALE | ns.UNGROUPLETTERS | ns.F) == r # The below are all aliases for UNGROUPLETTERS assert ns.UNGROUPLETTERS == ns.UG assert ns.UNGROUPLETTERS == ns.CAPITALFIRST assert ns.UNGROUPLETTERS == ns.C locale.setlocale(locale.LC_NUMERIC, str(''))
def test__natsort_key_with_relative_path_intput_and_PATH_returns_nested_tuple_where_each_element_is_path_component_with_leading_relative_parent_and_split_extensions( ): assert _natsort_key('../Folder (10)/file (2).tar.gz', None, ns.PATH | ns.F) == (('..', ), ( 'Folder (', 10.0, ')', ), ('file (', 2.0, ')'), ('.tar', ), ('.gz', ))
def test__natsort_key_with_LOCALE_and_UNGROUPLETTERS_places_space_before_string_with_capital_first_letter(): # Locale aware sorting locale.setlocale(locale.LC_NUMERIC, str('en_US.UTF-8')) if use_pyicu: from natsort.locale_help import get_pyicu_transform from locale import getlocale strxfrm = get_pyicu_transform(getlocale()) else: from natsort.locale_help import strxfrm assert _natsort_key('Apple56.5', None, ns.LOCALE | ns.UNGROUPLETTERS | ns.F) == (strxfrm(' Apple'), 56.5) assert _natsort_key('apple56.5', None, ns.LOCALE | ns.UNGROUPLETTERS | ns.F) == (strxfrm('apple'), 56.5) assert _natsort_key('12Apple56.5', None, ns.LOCALE | ns.UNGROUPLETTERS | ns.F) == (null_string, 12.0, strxfrm('Apple'), 56.5) # The below are all aliases for UNGROUPLETTERS assert ns.UNGROUPLETTERS == ns.UG assert ns.UNGROUPLETTERS == ns.CAPITALFIRST assert ns.UNGROUPLETTERS == ns.C locale.setlocale(locale.LC_NUMERIC, str(''))
def test__natsort_key_with_pathlib_intput_and_PATH_returns_nested_tuples(): # Converts pathlib PurePath (and subclass) objects to string before sorting assert _natsort_key(pathlib.Path('../Folder (10)/file (2).tar.gz'), None, ns.PATH | ns.F) == (('..', ), ( 'Folder (', 10.0, ')', ), ('file (', 2.0, ')'), ('.tar', ), ('.gz', ))
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_factory(string_func) bytes_func = _parse_bytes_factory(ns.PATH) num_func = _parse_number_factory(ns.PATH, '') assert _natsort_key(10, None, sfunc, bytes_func, num_func) == (('', 10), )
def test__natsort_key_with_tuple_input_but_itemgetter_key_returns_split_second_element( x): # A key is applied before recursion, but not in the recursive calls. 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) t = tuple( _number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup)) assert _natsort_key((s, s), itemgetter(1), ns.I) == t
def test_natsort_key_public(): # 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') == _natsort_key('a-5.034e2', key=None, alg=ns.F) assert len(w) == 1 assert "natsort_key is deprecated as of 3.4.0, please use natsort_keygen" in str(w[-1].message) assert natsort_key('a-5.034e2', number_type=float, signed=False, exp=False) == _natsort_key('a-5.034e2', key=None, alg=ns.F | ns.U | ns.N) assert natsort_key('a-5.034e2', alg=ns.F | ns.U | ns.N) == _natsort_key('a-5.034e2', key=None, alg=ns.F | ns.U | ns.N) # 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_key_with_LOCALE_transforms_floats_according_to_the_current_locale_and_strxfrms_strings(): # Locale aware sorting locale.setlocale(locale.LC_NUMERIC, str('en_US.UTF-8')) if use_pyicu: from natsort.locale_help import get_pyicu_transform from locale import getlocale strxfrm = get_pyicu_transform(getlocale()) else: from natsort.locale_help import strxfrm assert _natsort_key('Apple56.5', None, ns.LOCALE) == (strxfrm('Apple'), 56.5) assert _natsort_key('Apple56,5', None, ns.LOCALE) == (strxfrm('Apple'), 56.0, strxfrm(','), 5.0) locale.setlocale(locale.LC_NUMERIC, str('de_DE.UTF-8')) if use_pyicu: strxfrm = get_pyicu_transform(getlocale()) assert _natsort_key('Apple56.5', None, ns.LOCALE) == (strxfrm('Apple'), 56.5) assert _natsort_key('Apple56,5', None, ns.LOCALE) == (strxfrm('Apple'), 56.5) locale.setlocale(locale.LC_NUMERIC, str(''))
def test__natsort_key_with_tuple_of_paths_and_PATH_returns_triply_nested_tuple( ): # PATH also handles recursion well. sfunc = _parse_path_factory(string_func) bytes_func = _parse_bytes_factory(ns.PATH) num_func = _parse_number_factory(ns.PATH, '') assert _natsort_key( ('/Folder', '/Folder (1)'), None, sfunc, bytes_func, num_func) == ((('/', ), ('Folder', )), (('/', ), ('Folder (', 1, ')')))
def test__natsort_key_with_absolute_path_intput_and_PATH_returns_nested_tuple_where_each_element_is_path_component_with_leading_root_and_split_extensions( ): # Turn on PATH to split a file path into components assert _natsort_key('/p/Folder (10)/file34.5nm (2).tar.gz', None, ns.PATH | ns.F) == (('/', ), ('p', ), ( 'Folder (', 10.0, ')', ), ('file', 34.5, 'nm (', 2.0, ')'), ('.tar', ), ('.gz', ))
def test__natsort_key_with_GROUPLETTERS_doubles_text_with_lowercase_letter_first( x): assume(not any(type(y) == float and isnan(y) for y in x)) s = ''.join( ichain([repr(y)] if type(y) in (float, long, int) else [low(y), y] for y in x)) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) t = _number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup) assert _natsort_key(s, None, ns.GROUPLETTERS) == tuple(''.join( low(z) + z for z in y) if type(y) not in (float, long, int) else y for y in t)
def test__natsort_key_with_GROUPLETTERS_doubles_text_with_lowercase_letter_first(x): try: low = py23_str.casefold except AttributeError: low = py23_str.lower assume(len(x) <= 10) assume(not any(type(y) == float and isnan(y) for y in x)) s = ''.join(ichain([repr(y)] if type(y) in (float, long, int) else [low(y), y] for y in x)) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) t = _number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup) assert _natsort_key(s, None, ns.GROUPLETTERS) == tuple(''.join(low(z) + z for z in y) if type(y) not in (float, long, int) else y for y in t)
def test__natsort_key_with_LOCALE_and_UNGROUPLETTERS_places_space_before_string_with_capital_first_letter( ): # Locale aware sorting locale.setlocale(locale.LC_NUMERIC, str('en_US.UTF-8')) if use_pyicu: from natsort.locale_help import get_pyicu_transform from locale import getlocale strxfrm = get_pyicu_transform(getlocale()) else: from natsort.locale_help import strxfrm assert _natsort_key('Apple56.5', None, ns.LOCALE | ns.UNGROUPLETTERS | ns.F) == (strxfrm(' Apple'), 56.5) assert _natsort_key('apple56.5', None, ns.LOCALE | ns.UNGROUPLETTERS | ns.F) == (strxfrm('apple'), 56.5) assert _natsort_key('12Apple56.5', None, ns.LOCALE | ns.UNGROUPLETTERS | ns.F) == (null_string, 12.0, strxfrm('Apple'), 56.5) # The below are all aliases for UNGROUPLETTERS assert ns.UNGROUPLETTERS == ns.UG assert ns.UNGROUPLETTERS == ns.CAPITALFIRST assert ns.UNGROUPLETTERS == ns.C locale.setlocale(locale.LC_NUMERIC, str(''))
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') == _natsort_key('a-5.034e2', key=None, alg=ns.I) 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_key_with_LOCALE_transforms_floats_according_to_the_current_locale_and_strxfrms_strings( ): # Locale aware sorting locale.setlocale(locale.LC_NUMERIC, str('en_US.UTF-8')) if use_pyicu: from natsort.locale_help import get_pyicu_transform from locale import getlocale strxfrm = get_pyicu_transform(getlocale()) else: from natsort.locale_help import strxfrm assert _natsort_key('Apple56.5', None, ns.LOCALE) == (strxfrm('Apple'), 56.5) assert _natsort_key('Apple56,5', None, ns.LOCALE) == (strxfrm('Apple'), 56.0, strxfrm(','), 5.0) locale.setlocale(locale.LC_NUMERIC, str('de_DE.UTF-8')) if use_pyicu: strxfrm = get_pyicu_transform(getlocale()) assert _natsort_key('Apple56.5', None, ns.LOCALE) == (strxfrm('Apple'), 56.5) assert _natsort_key('Apple56,5', None, ns.LOCALE) == (strxfrm('Apple'), 56.5) locale.setlocale(locale.LC_NUMERIC, str(''))
def test_natsort_keygen(): # Creates equivalent natsort keys a = 'a-5.034e1' assert natsort_keygen()(a) == _natsort_key(a, key=None, alg=ns.F) assert natsort_keygen(alg=ns.UNSIGNED)(a) == _natsort_key(a, key=None, alg=ns.U) assert natsort_keygen(alg=ns.NOEXP)(a) == _natsort_key(a, key=None, alg=ns.N) assert natsort_keygen(alg=ns.U | ns.N)(a) == _natsort_key(a, key=None, alg=ns.U | ns.N) assert natsort_keygen(alg=ns.INT)(a) == _natsort_key(a, key=None, alg=ns.INT) assert natsort_keygen(alg=ns.I | ns.U)(a) == _natsort_key(a, key=None, alg=ns.I | ns.U) assert natsort_keygen(alg=ns.VERSION)(a) == _natsort_key(a, key=None, alg=ns.V) assert natsort_keygen(alg=ns.PATH)(a) == _natsort_key(a, key=None, alg=ns.PATH) # Custom keys are more straightforward with keygen f1 = natsort_keygen(key=lambda x: x.upper()) f2 = lambda x: _natsort_key(x, key=lambda y: y.upper(), alg=ns.F) assert f1(a) == f2(a) # It also makes sorting lists in-place easier (no lambdas!) a = ['a50', 'a51.', 'a50.31', 'a50.4', 'a5.034e1', 'a50.300'] b = a[:] a.sort(key=natsort_keygen(alg=ns.I)) assert a == natsorted(b, alg=ns.I)
def test__natsort_key_with_LOCALE_and_UNGROUPLETTERS_places_space_before_string_with_capital_first_letter(x): # Locale aware sorting 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) load_locale('en_US') if dumb_sort(): t = tuple(_number_extracter(s.swapcase(), _float_nosign_exp_re, *float_nosafe_locale_group)) else: t = tuple(_number_extracter(s, _float_nosign_exp_re, *float_nosafe_locale_nogroup)) if not t: r = (t, t) elif t[0] in (null_string, get_strxfrm()(b'\x00') if sys.version[0] == '2' and not use_pyicu else null_string): r = ((b'' if use_pyicu else '',), t) else: r = ((s[0],), t) assert _natsort_key(s, None, ns.LOCALE | ns.UNGROUPLETTERS | ns.F) == r # The below are all aliases for UNGROUPLETTERS assert ns.UNGROUPLETTERS == ns.UG assert ns.UNGROUPLETTERS == ns.CAPITALFIRST assert ns.UNGROUPLETTERS == ns.C locale.setlocale(locale.LC_NUMERIC, str(''))
def natsort_key(val, key=None, number_type=float, signed=None, exp=None, as_path=None, py3_safe=None, alg=0): """\ Key to sort strings and numbers naturally. Key to sort strings and numbers naturally, not lexicographically. It is designed for use in passing to the 'sorted' builtin or 'sort' attribute of lists. .. note:: Deprecated since version 3.4.0. This function remains in the publicly exposed API for backwards-compatibility reasons, but future development should use the newer `natsort_keygen` function. It is planned to remove this from the public API in natsort version 4.0.0. A DeprecationWarning will be raised via the warnings module; set warnings.simplefilter("always") to raise them to see if your code will work in version 4.0.0. Parameters ---------- val : {{str, unicode}} The value used by the sorting algorithm key : callable, optional A key used to manipulate the input value before parsing for numbers. It is **not** applied recursively. It should accept a single argument and return a single value. number_type : {{None, float, int}}, optional Deprecated as of version 3.5.0 and will become an undocumented keyword-only argument in 4.0.0. Please use the `alg` argument for all future development. See :class:`ns` class documentation for details. signed : {{True, False}}, optional Deprecated as of version 3.5.0 and will become an undocumented keyword-only argument in 4.0.0. Please use the `alg` argument for all future development. See :class:`ns` class documentation for details. exp : {{True, False}}, optional Deprecated as of version 3.5.0 and will become an undocumented keyword-only argument in 4.0.0. Please use the `alg` argument for all future development. See :class:`ns` class documentation for details. as_path : {{True, False}}, optional Deprecated as of version 3.5.0 and will become an undocumented keyword-only argument in 4.0.0. Please use the `alg` argument for all future development. See :class:`ns` class documentation for details. py3_safe : {{True, False}}, optional Deprecated as of version 3.5.0 and will become an undocumented keyword-only argument in 4.0.0. Please use the `alg` argument for all future development. See :class:`ns` class documentation for details. alg : ns enum, optional This option is used to control which algorithm `natsort` uses when sorting. For details into these options, please see the :class:`ns` class documentation. The default is `ns.FLOAT`. Returns ------- out : tuple The modified value with numbers extracted. See Also -------- natsort_keygen : Generates a properly wrapped `natsort_key`. Examples -------- Using natsort_key is just like any other sorting key in python:: >>> a = ['num3', 'num5', 'num2'] >>> a.sort(key=natsort_key) >>> a [{u}'num2', {u}'num3', {u}'num5'] It works by separating out the numbers from the strings:: >>> natsort_key('num2') ({u}'num', 2.0) If you need to call natsort_key with the number_type argument, or get a special attribute or item of each element of the sequence, please use the `natsort_keygen` function. Actually, please just use the `natsort_keygen` function. Notes ----- Iterables are parsed recursively so you can sort lists of lists:: >>> natsort_key(('a1', 'a10')) (({u}'a', 1.0), ({u}'a', 10.0)) Strings that lead with a number get an empty string at the front of the tuple. This is designed to get around the "unorderable types" issue of Python3:: >>> natsort_key('15a') ({u}'', 15.0, {u}'a') You can give bare numbers, too:: >>> natsort_key(10) ({u}'', 10) If you have a case where one of your string has two numbers in a row, you can turn on the "py3_safe" option to try to add a "" between sets of two numbers:: >>> natsort_key('43h7+3', py3_safe=True) ({u}'', 43.0, {u}'h', 7.0, {u}'', 3.0) """ msg = "natsort_key is deprecated as of 3.4.0, please use natsort_keygen" warn(msg, DeprecationWarning) alg = _args_to_enum(number_type, signed, exp, as_path, py3_safe) | alg return _natsort_key(val, key, alg)
def test__natsort_key_with_LOWERCASEFIRST_inverts_text_case(x): assume(len(x) <= 10) 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, ns.LOWERCASEFIRST) == tuple(_number_extracter(s.swapcase(), _int_nosign_re, *int_nosafe_nolocale_nogroup))
def test_natsort_keygen_returns_natsort_key_with_alg_option(): a = 'a-5.034e1' assert natsort_keygen()(a) == _natsort_key(a, None, ns.I) assert natsort_keygen(alg=ns.F | ns.S)(a) == _natsort_key(a, None, ns.F | ns.S)
def test__natsort_key_with_TYPESAFE_inserts_spaces_between_numbers(x): # Turn on TYPESAFE to put a '' between adjacent numbers assume(len(x) <= 10) 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, ns.TYPESAFE | ns.S) == tuple(_number_extracter(s, _int_sign_re, *int_safe_nolocale_nogroup))
def test__natsort_key_with_invalid_alg_input_raises_ValueError(): # Invalid arguments give the correct response with raises(ValueError) as err: _natsort_key('a', None, '1') assert str(err.value) == "_natsort_key: 'alg' argument must be from the enum 'ns', got 1"
def f2(x): return _natsort_key(x, lambda y: y.upper(), ns.I)
def test__natsort_key_with_numeric_input_returns_number_with_leading_empty_string(x): assume(not isnan(x)) if x.is_integer(): x = int(x) assert _natsort_key(x, None, ns.I) == ('', x)
def test__natsort_key_with_key_applies_key_function_before_splitting(x): assume(len(x) <= 10) 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, lambda x: x.upper(), ns.I) == tuple(_number_extracter(s.upper(), _int_nosign_re, *int_nosafe_nolocale_nogroup))
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)
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. assert _natsort_key(10, None, ns.PATH) == (('', 10),)
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))
def test__natsort_key_with_relative_path_intput_and_PATH_returns_nested_tuple_where_each_element_is_path_component_and_split_extensions(): assert _natsort_key('Folder (10)/file.f34.5nm (2).tar.gz', None, ns.PATH | ns.F) == (('Folder (', 10.0, ')',), ('file.f', 34.5, 'nm (', 2.0, ')'), ('.tar',), ('.gz',))
def test__natsort_key_with_UNGROUPLETTERS_does_nothing_without_LOCALE(x): assume(len(x) <= 10) 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, ns.UG | ns.I) == _natsort_key(s, None, ns.I)
def test__natsort_key_with_text_input_takes_string_path(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)
def test__natsort_key_with_bytes_input_takes_bytes_path(x): assert _natsort_key(x, None, string_func, bytes_func, num_func) == bytes_func(x)
def test__natsort_key_with_numeric_input_takes_number_path(x): assert _natsort_key(x, None, string_func, bytes_func, num_func) == num_func(x)
def test__natsort_key_with_absolute_path_intput_and_PATH_returns_nested_tuple_where_each_element_is_path_component_with_leading_root_and_split_extensions(): # Turn on PATH to split a file path into components assert _natsort_key('/p/Folder (10)/file34.5nm (2).tar.gz', None, ns.PATH | ns.F) == (('/',), ('p', ), ('Folder (', 10.0, ')',), ('file', 34.5, 'nm (', 2.0, ')'), ('.tar',), ('.gz',))
def test__natsort_key_with_real_matches_signed_float(x): assume(len(x) <= 10) 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, ns.R) == _natsort_key(s, None, ns.F | ns.S)
def test__natsort_key_with_pathlib_intput_and_PATH_returns_nested_tuples(): # Converts pathlib PurePath (and subclass) objects to string before sorting assert _natsort_key(pathlib.Path('../Folder (10)/file (2).tar.gz'), None, ns.PATH | ns.F) == (('..', ), ('Folder (', 10.0, ')',), ('file (', 2.0, ')'), ('.tar',), ('.gz',))
def test__natsort_key_with_version_or_digit_matches_usigned_int(x): assume(len(x) <= 10) 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, ns.VERSION) == _natsort_key(s, None, ns.INT | ns.UNSIGNED) assert _natsort_key(s, None, ns.DIGIT) == _natsort_key(s, None, ns.VERSION)
def test__natsort_key_with_tuple_of_paths_and_PATH_returns_triply_nested_tuple(): # PATH also handles recursion well. assert _natsort_key(('/Folder', '/Folder (1)'), None, ns.PATH) == ((('/',), ('Folder',)), (('/',), ('Folder (', 1, ')')))
def test__natsort_key_with_tuple_of_paths_and_PATH_returns_triply_nested_tuple( ): # PATH also handles recursion well. assert _natsort_key( ('/Folder', '/Folder (1)'), None, ns.PATH) == ((('/', ), ('Folder', )), (('/', ), ('Folder (', 1, ')')))