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, )
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_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, )
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_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, )
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, )
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, )
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",), )
text, floats, integers, binary, use_hypothesis, ) if PY_VERSION >= 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),) @pytest.mark.skipif(PY_VERSION < 3, reason='only valid on python3') def test__natsort_key_with_bytes_input_and_PATH_returns_number_in_nested_tuple():
def natsort_keygen(key=None, alg=0, **_kwargs): """\ Generate a key to sort strings and numbers naturally. Generate a key to sort strings and numbers naturally, not lexicographically. This key is designed for use as the `key` argument to functions such as the `sorted` builtin. The user may customize the generated function with the arguments to `natsort_keygen`, including an optional `key` function which will be called before the `natsort_key`. Parameters ---------- 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. 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.INT`. Returns ------- out : function A wrapped version of the `natsort_key` function that is suitable for passing as the `key` argument to functions such as `sorted`. See Also -------- natsorted Examples -------- `natsort_keygen` is a convenient way to create a custom key to sort lists in-place (for example). Calling with no objects will return a plain `natsort_key` instance:: >>> a = ['num5.10', 'num-3', 'num5.3', 'num2'] >>> a.sort(key=natsort_keygen(alg=ns.REAL)) >>> a [{u}'num-3', {u}'num2', {u}'num5.10', {u}'num5.3'] """ # Transform old arguments to the ns enum. try: alg = _args_to_enum(**_kwargs) | alg except TypeError: msg = "natsort_keygen: 'alg' argument must be from the enum 'ns'" raise ValueError(msg + ', got {0}'.format(py23_str(alg))) # Add the _DUMB option if the locale library is broken. if alg & ns.LOCALEALPHA and natsort.compat.locale.dumb_sort(): alg |= ns._DUMB # Set some variable that will be passed to the factory functions sep = natsort.compat.locale.null_string if alg & ns.LOCALEALPHA else '' regex = _regex_chooser[alg & ns._NUMERIC_ONLY] # Create the functions that will be used to split strings. pre = _pre_split_function(alg) post = _post_split_function(alg) after = _post_string_parse_function(alg, sep) # Create the high-level parsing functions for strings, bytes, and numbers. string_func = _parse_string_function(alg, sep, regex.split, pre, post, after) if alg & ns.PATH: string_func = _parse_path_function(string_func) bytes_func = _parse_bytes_function(alg) num_func = _parse_number_function(alg, sep) # Return the natsort key with the parsing path pre-chosen. return partial(_natsort_key, key=key, string_func=string_func, bytes_func=bytes_func, num_func=num_func)
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_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 natsort_keygen(key=None, alg=0, **_kwargs): """\ Generate a key to sort strings and numbers naturally. Generate a key to sort strings and numbers naturally, not lexicographically. This key is designed for use as the `key` argument to functions such as the `sorted` builtin. The user may customize the generated function with the arguments to `natsort_keygen`, including an optional `key` function which will be called before the `natsort_key`. Parameters ---------- 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. 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.INT`. Returns ------- out : function A wrapped version of the `natsort_key` function that is suitable for passing as the `key` argument to functions such as `sorted`. See Also -------- natsorted Examples -------- `natsort_keygen` is a convenient way to create a custom key to sort lists in-place (for example). Calling with no objects will return a plain `natsort_key` instance:: >>> a = ['num5.10', 'num-3', 'num5.3', 'num2'] >>> a.sort(key=natsort_keygen(alg=ns.REAL)) >>> a [{u}'num-3', {u}'num2', {u}'num5.10', {u}'num5.3'] """ # Transform old arguments to the ns enum. try: alg = _args_to_enum(**_kwargs) | alg except TypeError: msg = "natsort_keygen: 'alg' argument must be from the enum 'ns'" raise ValueError(msg+', got {0}'.format(py23_str(alg))) # Add the _DUMB option if the locale library is broken. if alg & ns.LOCALEALPHA and natsort.compat.locale.dumb_sort(): alg |= ns._DUMB # Set some variable that will be passed to the factory functions sep = natsort.compat.locale.null_string if alg & ns.LOCALEALPHA else '' regex = _regex_chooser[alg & ns._NUMERIC_ONLY] # Create the functions that will be used to split strings. pre = _pre_split_function(alg) post = _post_split_function(alg) after = _post_string_parse_function(alg, sep) # Create the high-level parsing functions for strings, bytes, and numbers. string_func = _parse_string_function( alg, sep, regex.split, pre, post, after ) if alg & ns.PATH: string_func = _parse_path_function(string_func) bytes_func = _parse_bytes_function(alg) num_func = _parse_number_function(alg, sep) # Return the natsort key with the parsing path pre-chosen. return partial( _natsort_key, key=key, string_func=string_func, bytes_func=bytes_func, num_func=num_func )