diff --git a/natsort/compat/locale.py b/natsort/compat/locale.py
index 4cbe5f5..ab392ee 100644
--- a/natsort/compat/locale.py
+++ b/natsort/compat/locale.py
@@ -6,8 +6,21 @@ from __future__ import (
     absolute_import
 )
 
+# Std. lib imports.
+import sys
+
 # Local imports.
-from natsort.compat.py23 import PY_VERSION, cmp_to_key
+from natsort.compat.py23 import (
+    PY_VERSION,
+    cmp_to_key,
+    py23_unichr,
+)
+
+# This string should be sorted after any other byte string because
+# it contains the max unicode character repeated 20 times.
+# You would need some odd data to come after that.
+null_string = ''
+null_string_max = py23_unichr(sys.maxunicode) * 20
 
 # Make the strxfrm function from strcoll on Python2
 # It can be buggy (especially on BSD-based systems),
@@ -16,7 +29,12 @@ try:
     import icu
     from locale import getlocale
 
-    null_string = b''
+    null_string_locale = b''
+
+    # This string should in theory be sorted after any other byte
+    # string because it contains the max byte char repeated many times.
+    # You would need some odd data to come after that.
+    null_string_locale_max = b'x7f' * 50
 
     def dumb_sort():
         return False
@@ -43,11 +61,28 @@ except ImportError:
     import locale
     if PY_VERSION < 3:
         from locale import strcoll
-        strxfrm = cmp_to_key(strcoll)
-        null_string = strxfrm('')
+        sentinel = object()
+
+        def custom_strcoll(a, b, last=sentinel):
+            """strcoll that can handle a sentinel that is always last."""
+            if a is last:
+                return 0 if a is b else 1
+            elif b is last:  # a cannot also be sentinel b/c above logic
+                return -1
+            else:  # neither are sentinel
+                return strcoll(a, b)
+
+        strxfrm = cmp_to_key(custom_strcoll)
+        null_string_locale = strxfrm('')
+        null_string_locale_max = strxfrm(sentinel)
     else:
         from locale import strxfrm
-        null_string = ''
+        null_string_locale = ''
+
+        # This string should be sorted after any other byte string because
+        # it contains the max unicode character repeated 20 times.
+        # You would need some odd data to come after that.
+        null_string_locale_max = py23_unichr(sys.maxunicode) * 20
 
     # On some systems, locale is broken and does not sort in the expected
     # order. We will try to detect this and compensate.
diff --git a/natsort/natsort.py b/natsort/natsort.py
index be887c7..557e07b 100644
--- a/natsort/natsort.py
+++ b/natsort/natsort.py
@@ -207,13 +207,24 @@ def natsort_keygen(key=None, alg=0, **_kwargs):
         alg |= ns._DUMB
 
     # Set some variables that will be passed to the factory functions
-    sep = natsort.compat.locale.null_string if alg & ns.LOCALEALPHA else ''
+    if alg & ns.NUMAFTER:
+        if alg & ns.LOCALEALPHA:
+            sep = natsort.compat.locale.null_string_locale_max
+        else:
+            sep = natsort.compat.locale.null_string_max
+        pre_sep = natsort.compat.locale.null_string_max
+    else:
+        if alg & ns.LOCALEALPHA:
+            sep = natsort.compat.locale.null_string_locale
+        else:
+            sep = natsort.compat.locale.null_string
+        pre_sep = natsort.compat.locale.null_string
     regex = _regex_chooser[alg & ns._NUMERIC_ONLY]
 
     # Create the functions that will be used to split strings.
     input_transform = _input_string_transform_factory(alg)
     component_transform = _string_component_transform_factory(alg)
-    final_transform = _final_data_transform_factory(alg, sep)
+    final_transform = _final_data_transform_factory(alg, sep, pre_sep)
 
     # Create the high-level parsing functions for strings, bytes, and numbers.
     string_func = _parse_string_factory(
@@ -223,7 +234,7 @@ def natsort_keygen(key=None, alg=0, **_kwargs):
     if alg & ns.PATH:
         string_func = _parse_path_factory(string_func)
     bytes_func = _parse_bytes_factory(alg)
-    num_func = _parse_number_factory(alg, sep)
+    num_func = _parse_number_factory(alg, sep, pre_sep)
 
     # Return the natsort key with the parsing path pre-chosen.
     return partial(
diff --git a/natsort/ns_enum.py b/natsort/ns_enum.py
index 37a00de..4216ddd 100644
--- a/natsort/ns_enum.py
+++ b/natsort/ns_enum.py
@@ -42,6 +42,9 @@ class ns(object):
         Tell `natsort` to not search for exponents as part of a float number.
         For example, with `NOEXP` the number "5.6E5" would be interpreted
         as `5.6`, `"E"`, and `5` instead of `560000`.
+    NUMAFTER, NA
+        Tell `natsort` to sort numbers after non-numbers. By default
+        numbers will be ordered before non-numbers.
     PATH, P
         Tell `natsort` to interpret strings as filesystem paths, so they
         will be split according to the filesystem separator
@@ -151,6 +154,7 @@ class ns(object):
     CAPITALFIRST           = C  = UNGROUPLETTERS
     NANLAST                = NL = 1 << 10
     COMPATIBILITYNORMALIZE = CN = 1 << 11
+    NUMAFTER               = NA = 1 << 12
 
     # The below are private options for internal use only.
     _NUMERIC_ONLY    = REAL | NOEXP
diff --git a/natsort/utils.py b/natsort/utils.py
index c33de1d..b6484b0 100644
--- a/natsort/utils.py
+++ b/natsort/utils.py
@@ -197,7 +197,7 @@ def _parse_bytes_factory(alg):
         return lambda x: (x,)
 
 
-def _parse_number_factory(alg, sep):
+def _parse_number_factory(alg, sep, pre_sep):
     """Create a function that will properly format a number in a tuple."""
     nan_replace = float('+inf') if alg & ns.NANLAST else float('-inf')
 
@@ -207,9 +207,9 @@ def _parse_number_factory(alg, sep):
 
     # Return the function, possibly wrapping in tuple if PATH is selected.
     if alg & ns.PATH and alg & ns.UNGROUPLETTERS and alg & ns.LOCALEALPHA:
-        return lambda x: ((('',), func(x)),)
+        return lambda x: (((pre_sep,), func(x)),)
     elif alg & ns.UNGROUPLETTERS and alg & ns.LOCALEALPHA:
-        return lambda x: (('',), func(x))
+        return lambda x: ((pre_sep,), func(x))
     elif alg & ns.PATH:
         return lambda x: (func(x),)
     else:
@@ -363,7 +363,7 @@ def _string_component_transform_factory(alg):
         return partial(fast_int, **kwargs)
 
 
-def _final_data_transform_factory(alg, sep):
+def _final_data_transform_factory(alg, sep, pre_sep):
     """
     Given a set of natsort algorithms, return the function to operate
     on the post-parsed strings according to the user's request.
@@ -383,7 +383,7 @@ def _final_data_transform_factory(alg, sep):
             if not split_val:
                 return (), ()
             elif split_val[0] == sep:
-                return ('',), split_val
+                return (pre_sep,), split_val
             else:
                 return (transform(val[0]),), split_val
         return func

Feature request natsorted():  Sort by letters, then numbers
I'd like to submit a feature request to add an option that would allow natsorted() to sort by letters first, then numbers instead of numbers first, then letters.  Here is an example of the list that I am looking to sort - I am sorting by index 2 ('ABCDE', 'BCDEF' and '10001'):

```python
from natsort import natsorted
a = [
	['192.168.1.1', 'generic_description_1', 'ABCDE', 'apples', '172.16.1.1', u'\nCircuit is up\n'],
	['192.168.1.1', 'generic_description_2', 'BCDEF', 'oranges', '172.16.2.1', u'\nCircuit is up\n'],
	['192.168.2.1', 'generic_description_3', '10001', 'bananas', '172.16.3.1', u'\nCircuit is up\n']
]
print(natsorted(a, key = lambda x: x[2]))
```

Here are the results that are printed:

```
[['192.168.2.1', 'generic_description_3', '10001', 'bananas', '172.16.3.1', u'\nCircuit is up\n'],
 ['192.168.1.1', 'generic_description_1', 'ABCDE', 'apples', '172.16.1.1', u'\nCircuit is up\n'],
 ['192.168.1.1', 'generic_description_2', 'BCDEF', 'oranges', '172.16.2.1', u'\nCircuit is up\n']]
```

And as you can see, it sorts by index 2 by numbers first, then letters:

10001
ABCDE
BCDEF


The option I am requesting would allow the sorting by letters first, then numbers - like this:

ABCDE
BCDEF
10001

Thanks for the consideration!

-Matt
diff --git a/test_natsort/test_final_data_transform_factory.py b/test_natsort/test_final_data_transform_factory.py
index bfd3dfd..f0207e6 100644
--- a/test_natsort/test_final_data_transform_factory.py
+++ b/test_natsort/test_final_data_transform_factory.py
@@ -20,38 +20,38 @@ from hypothesis.strategies import (
 
 
 def test_final_data_transform_factory_with_iterable_returns_tuple_with_no_options_example():
-    assert _final_data_transform_factory(0, '')(iter([7]), '') == (7,)
+    assert _final_data_transform_factory(0, '', '')(iter([7]), '') == (7,)
 
 
 @given(text())
 def test_final_data_transform_factory_with_iterable_returns_tuple_with_no_options(x):
-    assert _final_data_transform_factory(0, '')(iter([x]), '') == (x,)
+    assert _final_data_transform_factory(0, '', '')(iter([x]), '') == (x,)
     # UNGROUPLETTERS without LOCALE does nothing, as does LOCALE without UNGROUPLETTERS
-    assert _final_data_transform_factory(ns.UNGROUPLETTERS, '')(iter([x]), '') == _final_data_transform_factory(0, '')(iter([x]), '')
-    assert _final_data_transform_factory(ns.LOCALE, '')(iter([x]), '') == _final_data_transform_factory(0, '')(iter([x]), '')
+    assert _final_data_transform_factory(ns.UNGROUPLETTERS, '', '')(iter([x]), '') == _final_data_transform_factory(0, '', '')(iter([x]), '')
+    assert _final_data_transform_factory(ns.LOCALE, '', '')(iter([x]), '') == _final_data_transform_factory(0, '', '')(iter([x]), '')
 
 
 def test_final_data_transform_factory_with_empty_tuple_returns_double_empty_tuple():
-    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS, '')((), '') == ((), ())
+    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS, '', '')((), '') == ((), ())
 
 
 def test_final_data_transform_factory_with_null_string_first_element_adds_empty_string_on_first_tuple_element():
-    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS, '')(('', 60), '') == (('',), ('', 60))
+    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS, '', 'xx')(('', 60), '') == (('xx',), ('', 60))
 
 
 def test_final_data_transform_factory_returns_first_element_in_first_tuple_element_example():
-    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS, '')(('this', 60), 'this60') == (('t',), ('this', 60))
+    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS, '', '')(('this', 60), 'this60') == (('t',), ('this', 60))
 
 
 @given(x=text().filter(bool), y=floats(allow_nan=False, allow_infinity=False) | integers())
 def test_final_data_transform_factory_returns_first_element_in_first_tuple_element(x, y):
-    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS, '')((x, y), ''.join(map(py23_str, [x, y]))) == ((x[0],), (x, y))
+    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS, '', '')((x, y), ''.join(map(py23_str, [x, y]))) == ((x[0],), (x, y))
 
 
 def test_final_data_transform_factory_returns_first_element_in_first_tuple_element_caseswapped_with_DUMB_and_LOWERCASEFIRST_example():
-    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS | ns._DUMB | ns.LOWERCASEFIRST, '')(('this', 60), 'this60') == (('T',), ('this', 60))
+    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS | ns._DUMB | ns.LOWERCASEFIRST, '', '')(('this', 60), 'this60') == (('T',), ('this', 60))
 
 
 @given(x=text().filter(bool), y=floats(allow_nan=False, allow_infinity=False) | integers())
 def test_final_data_transform_factory_returns_first_element_in_first_tuple_element_caseswapped_with_DUMB_and_LOWERCASEFIRST(x, y):
-    assert _final_data_transform_factory(ns.LOCALE | ns.UNGROUPLETTERS | ns._DUMB | ns.LOWERCASEFIRST, '')((x, y), ''.join(map(py23_str, [x, y]))) == ((x[0].swapcase(),), (x, y))
+    assert _final_data_transform_factory(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_natsort_key.py b/test_natsort/test_natsort_key.py
index a675cb2..9aabd11 100644
--- a/test_natsort/test_natsort_key.py
+++ b/test_natsort/test_natsort_key.py
@@ -34,10 +34,10 @@ if PY_VERSION >= 3:
 regex = _regex_chooser[ns.INT]
 pre = _input_string_transform_factory(ns.INT)
 post = _string_component_transform_factory(ns.INT)
-after = _final_data_transform_factory(ns.INT, '')
+after = _final_data_transform_factory(ns.INT, '', '')
 string_func = _parse_string_factory(ns.INT, '', regex.split, pre, post, after)
 bytes_func = _parse_bytes_factory(ns.INT)
-num_func = _parse_number_factory(ns.INT, '')
+num_func = _parse_number_factory(ns.INT, '', '')
 
 
 def test__natsort_key_with_numeric_input_and_PATH_returns_number_in_nested_tuple():
@@ -45,7 +45,7 @@ def test__natsort_key_with_numeric_input_and_PATH_returns_number_in_nested_tuple
     # 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, '')
+    num_func = _parse_number_factory(ns.PATH, '', '')
     assert _natsort_key(10, None, sfunc, bytes_func, num_func) == (('', 10),)
 
 
@@ -55,7 +55,7 @@ def test__natsort_key_with_bytes_input_and_PATH_returns_number_in_nested_tuple()
     # 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, '')
+    num_func = _parse_number_factory(ns.PATH, '', '')
     assert _natsort_key(b'/hello/world', None, sfunc, bytes_func, num_func) == ((b'/hello/world',),)
 
 
@@ -63,7 +63,7 @@ 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, '')
+    num_func = _parse_number_factory(ns.PATH, '', '')
     assert _natsort_key(('/Folder', '/Folder (1)'), None, sfunc, bytes_func, num_func) == ((('/',), ('Folder',)), (('/',), ('Folder (', 1, ')')))
 
 
diff --git a/test_natsort/test_natsort_keygen.py b/test_natsort/test_natsort_keygen.py
index e94d3d3..9ea408a 100644
--- a/test_natsort/test_natsort_keygen.py
+++ b/test_natsort/test_natsort_keygen.py
@@ -16,7 +16,7 @@ from natsort import (
 )
 from natsort.compat.py23 import PY_VERSION
 from natsort.compat.locale import (
-    null_string,
+    null_string_locale,
     get_strxfrm,
 )
 from compat.mock import patch
@@ -79,9 +79,9 @@ def test_natsort_keygen_splits_input_with_locale():
     load_locale('en_US')
     strxfrm = get_strxfrm()
     with patch('natsort.compat.locale.dumb_sort', return_value=False):
-        assert natsort_keygen(alg=ns.L)(INPUT) == ((null_string, 6, strxfrm('A-'), 5, strxfrm('.'), 34, strxfrm('e+'), 1), (strxfrm('/Folder ('), 1, strxfrm(')/Foo')), (null_string, 56.7))
+        assert natsort_keygen(alg=ns.L)(INPUT) == ((null_string_locale, 6, strxfrm('A-'), 5, strxfrm('.'), 34, strxfrm('e+'), 1), (strxfrm('/Folder ('), 1, strxfrm(')/Foo')), (null_string_locale, 56.7))
     with patch('natsort.compat.locale.dumb_sort', return_value=True):
-        assert natsort_keygen(alg=ns.L)(INPUT) == ((null_string, 6, strxfrm('aa--'), 5, strxfrm('..'), 34, strxfrm('eE++'), 1), (strxfrm('//ffoOlLdDeErR  (('), 1, strxfrm('))//ffoOoO')), (null_string, 56.7))
+        assert natsort_keygen(alg=ns.L)(INPUT) == ((null_string_locale, 6, strxfrm('aa--'), 5, strxfrm('..'), 34, strxfrm('eE++'), 1), (strxfrm('//ffoOlLdDeErR  (('), 1, strxfrm('))//ffoOoO')), (null_string_locale, 56.7))
     if PY_VERSION >= 3: assert natsort_keygen(alg=ns.LA)(b'6A-5.034e+1') == (b'6A-5.034e+1',)
     locale.setlocale(locale.LC_ALL, str(''))
 
@@ -90,7 +90,7 @@ def test_natsort_keygen_splits_input_with_locale_and_capitalfirst():
     load_locale('en_US')
     strxfrm = get_strxfrm()
     with patch('natsort.compat.locale.dumb_sort', return_value=False):
-        assert natsort_keygen(alg=ns.LA | ns.C)(INPUT) == ((('',), (null_string, 6, strxfrm('A-'), 5, strxfrm('.'), 34, strxfrm('e+'), 1)), (('/',), (strxfrm('/Folder ('), 1, strxfrm(')/Foo'))), (('',), (null_string, 56.7)))
+        assert natsort_keygen(alg=ns.LA | ns.C)(INPUT) == ((('',), (null_string_locale, 6, strxfrm('A-'), 5, strxfrm('.'), 34, strxfrm('e+'), 1)), (('/',), (strxfrm('/Folder ('), 1, strxfrm(')/Foo'))), (('',), (null_string_locale, 56.7)))
     if PY_VERSION >= 3: assert natsort_keygen(alg=ns.LA | ns.C)(b'6A-5.034e+1') == (b'6A-5.034e+1',)
     locale.setlocale(locale.LC_ALL, str(''))
 
diff --git a/test_natsort/test_natsorted.py b/test_natsort/test_natsorted.py
index fcbf75b..71ffbf6 100644
--- a/test_natsort/test_natsorted.py
+++ b/test_natsort/test_natsorted.py
@@ -82,8 +82,10 @@ def test_natsorted_returns_sorted_list_with_mixed_type_input_and_does_not_raise_
 def test_natsorted_with_mixed_input_returns_sorted_results_without_error():
     a = ['0', 'Á', '2', 'Z']
     assert natsorted(a) == ['0', '2', 'Á', 'Z']
+    assert natsorted(a, alg=ns.NUMAFTER) == ['Á', 'Z', '0', '2']
     a = ['2', 'ä', 'b', 1.5, 3]
     assert natsorted(a) == [1.5, '2', 3, 'ä', 'b']
+    assert natsorted(a, alg=ns.NUMAFTER) == ['ä', 'b', 1.5, '2', 3]
 
 
 def test_natsorted_with_nan_input_returns_sorted_results_with_nan_last_with_NANLAST():
@@ -243,8 +245,10 @@ def test_natsorted_with_LOCALE_and_mixed_input_returns_sorted_results_without_er
     load_locale('en_US')
     a = ['0', 'Á', '2', 'Z']
     assert natsorted(a, alg=ns.LOCALE) == ['0', '2', 'Á', 'Z']
+    assert natsorted(a, alg=ns.LOCALE | ns.NUMAFTER) == ['Á', 'Z', '0', '2']
     a = ['2', 'ä', 'b', 1.5, 3]
     assert natsorted(a, alg=ns.LOCALE) == [1.5, '2', 3, 'ä', 'b']
+    assert natsorted(a, alg=ns.LOCALE | ns.NUMAFTER) == ['ä', 'b', 1.5, '2', 3]
     locale.setlocale(locale.LC_ALL, str(''))
 
 
@@ -252,8 +256,10 @@ def test_natsorted_with_LOCALE_and_UNGROUPLETTERS_and_mixed_input_returns_sorted
     load_locale('en_US')
     a = ['0', 'Á', '2', 'Z']
     assert natsorted(a, alg=ns.LOCALE | ns.UNGROUPLETTERS) == ['0', '2', 'Á', 'Z']
+    assert natsorted(a, alg=ns.LOCALE | ns.UNGROUPLETTERS | ns.NUMAFTER) == ['Á', 'Z', '0', '2']
     a = ['2', 'ä', 'b', 1.5, 3]
     assert natsorted(a, alg=ns.LOCALE | ns.UNGROUPLETTERS) == [1.5, '2', 3, 'ä', 'b']
+    assert natsorted(a, alg=ns.LOCALE | ns.UNGROUPLETTERS | ns.NUMAFTER) == ['ä', 'b', 1.5, '2', 3]
     locale.setlocale(locale.LC_ALL, str(''))
 
 
@@ -261,6 +267,16 @@ def test_natsorted_with_PATH_and_LOCALE_and_UNGROUPLETTERS_and_mixed_input_retur
     load_locale('en_US')
     a = ['0', 'Á', '2', 'Z']
     assert natsorted(a, alg=ns.PATH | ns.LOCALE | ns.UNGROUPLETTERS) == ['0', '2', 'Á', 'Z']
+    assert natsorted(a, alg=ns.PATH | ns.LOCALE | ns.UNGROUPLETTERS | ns.NUMAFTER) == ['Á', 'Z', '0', '2']
     a = ['2', 'ä', 'b', 1.5, 3]
     assert natsorted(a, alg=ns.PATH | ns.LOCALE | ns.UNGROUPLETTERS) == [1.5, '2', 3, 'ä', 'b']
+    assert natsorted(a, alg=ns.PATH | ns.LOCALE | ns.UNGROUPLETTERS | ns.NUMAFTER) == ['ä', 'b', 1.5, '2', 3]
     locale.setlocale(locale.LC_ALL, str(''))
+
+
+def test_natsorted_sorts_an_odd_collection_of_string():
+    a = ['Corn', 'apple', 'Banana', '73', 'Apple', '5039', 'corn', '~~~~~~', 'banana']
+    assert natsorted(a) == ['73', '5039', 'Apple', 'Banana', 'Corn',
+                            'apple', 'banana', 'corn', '~~~~~~']
+    assert natsorted(a, alg=ns.NUMAFTER) == ['Apple', 'Banana', 'Corn',
+                                             'apple', 'banana', 'corn', '~~~~~~', '73', '5039']
diff --git a/test_natsort/test_parse_number_function.py b/test_natsort/test_parse_number_function.py
index 163d066..2e7a9fe 100644
--- a/test_natsort/test_parse_number_function.py
+++ b/test_natsort/test_parse_number_function.py
@@ -18,38 +18,38 @@ from hypothesis.strategies import (
 
 
 def test_parse_number_factory_makes_function_that_returns_tuple_example():
-    assert _parse_number_factory(0, '')(57) == ('', 57)
-    assert _parse_number_factory(0, '')(float('nan')) == ('', float('-inf'))
-    assert _parse_number_factory(ns.NANLAST, '')(float('nan')) == ('', float('+inf'))
+    assert _parse_number_factory(0, '', '')(57) == ('', 57)
+    assert _parse_number_factory(0, '', '')(float('nan')) == ('', float('-inf'))
+    assert _parse_number_factory(ns.NANLAST, '', '')(float('nan')) == ('', float('+inf'))
 
 
 @given(floats(allow_nan=False) | integers())
 def test_parse_number_factory_makes_function_that_returns_tuple(x):
-    assert _parse_number_factory(0, '')(x) == ('', x)
+    assert _parse_number_factory(0, '', '')(x) == ('', x)
 
 
 def test_parse_number_factory_with_PATH_makes_function_that_returns_nested_tuple_example():
-    assert _parse_number_factory(ns.PATH, '')(57) == (('', 57),)
+    assert _parse_number_factory(ns.PATH, '', '')(57) == (('', 57),)
 
 
 @given(floats(allow_nan=False) | integers())
 def test_parse_number_factory_with_PATH_makes_function_that_returns_nested_tuple(x):
-    assert _parse_number_factory(ns.PATH, '')(x) == (('', x),)
+    assert _parse_number_factory(ns.PATH, '', '')(x) == (('', x),)
 
 
 def test_parse_number_factory_with_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple_example():
-    assert _parse_number_factory(ns.UNGROUPLETTERS | ns.LOCALE, '')(57) == (('',), ('', 57))
+    assert _parse_number_factory(ns.UNGROUPLETTERS | ns.LOCALE, '', 'xx')(57) == (('xx',), ('', 57))
 
 
 @given(floats(allow_nan=False) | integers())
 def test_parse_number_factory_with_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple(x):
-    assert _parse_number_factory(ns.UNGROUPLETTERS | ns.LOCALE, '')(x) == (('',), ('', x))
+    assert _parse_number_factory(ns.UNGROUPLETTERS | ns.LOCALE, '', 'xx')(x) == (('xx',), ('', x))
 
 
 def test_parse_number_factory_with_PATH_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple_example():
-    assert _parse_number_factory(ns.PATH | ns.UNGROUPLETTERS | ns.LOCALE, '')(57) == ((('',), ('', 57)),)
+    assert _parse_number_factory(ns.PATH | ns.UNGROUPLETTERS | ns.LOCALE, '', 'xx')(57) == ((('xx',), ('', 57)),)
 
 
 @given(floats(allow_nan=False) | integers())
 def test_parse_number_factory_with_PATH_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple(x):
-    assert _parse_number_factory(ns.PATH | ns.UNGROUPLETTERS | ns.LOCALE, '')(x) == ((('',), ('', x)),)
+    assert _parse_number_factory(ns.PATH | ns.UNGROUPLETTERS | ns.LOCALE, '', 'xx')(x) == ((('xx',), ('', x)),)
diff --git a/test_natsort/test_utils.py b/test_natsort/test_utils.py
index cfa06b6..10ad0fa 100644
--- a/test_natsort/test_utils.py
+++ b/test_natsort/test_utils.py
@@ -24,7 +24,7 @@ from natsort.utils import (
     chain_functions,
 )
 from natsort.compat.py23 import py23_str, py23_cmp
-from natsort.compat.locale import null_string
+from natsort.compat.locale import null_string_locale
 from slow_splitters import (
     sep_inserter,
     add_leading_space_if_first_is_num,
@@ -149,6 +149,7 @@ def test_ns_enum_values_have_are_as_expected():
     assert ns.UNGROUPLETTERS == ns.CAPITALFIRST
     assert ns.NANLAST == ns.NL
     assert ns.COMPATIBILITYNORMALIZE == ns.CN
+    assert ns.NUMAFTER == ns.NA
 
     # Convenience
     assert ns.LOCALE == ns.LOCALEALPHA | ns.LOCALENUM
@@ -195,7 +196,7 @@ def test_sep_inserter_does_nothing_if_only_one_number_example():
 
 def test_sep_inserter_inserts_separator_string_between_two_numbers_example():
     assert list(_sep_inserter(iter([5, 9]), '')) == ['', 5, '', 9]
-    assert list(_sep_inserter(iter([5, 9]), null_string)) == [null_string, 5, null_string, 9]
+    assert list(_sep_inserter(iter([5, 9]), null_string_locale)) == [null_string_locale, 5, null_string_locale, 9]
 
 
 @given(lists(elements=text().filter(bool) | integers()))

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest hypothesis>=3.8.0
apt-get update apt-get install -y gcc g++ libicu-dev
3.9
requirements.txt testing-requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
astroid==1.5.3
attrs==25.3.0
coverage==7.8.0
exceptiongroup==1.2.2
execnet==2.1.1
hypothesis==6.130.6
iniconfig==2.1.0
lazy-object-proxy==1.10.0
-e git+https://github.com/SethMMorton/natsort.git@2e474460d65998dd72f1db56556b03cb3f69f806#egg=natsort
packaging==24.2
pep8==1.7.1
pluggy==1.5.0
pyflakes==3.3.2
pytest==8.3.5
pytest-cache==1.0
pytest-cov==6.0.0
pytest-flakes==4.0.5
pytest-pep8==1.0.6
six==1.17.0
sortedcontainers==2.4.0
tomli==2.2.1
wrapt==1.17.2

name: natsort
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - astroid==1.5.3
      - attrs==25.3.0
      - coverage==7.8.0
      - exceptiongroup==1.2.2
      - execnet==2.1.1
      - hypothesis==6.130.6
      - iniconfig==2.1.0
      - lazy-object-proxy==1.10.0
      - packaging==24.2
      - pep8==1.7.1
      - pluggy==1.5.0
      - pyflakes==3.3.2
      - pytest==8.3.5
      - pytest-cache==1.0
      - pytest-cov==6.0.0
      - pytest-flakes==4.0.5
      - pytest-pep8==1.0.6
      - six==1.17.0
      - sortedcontainers==2.4.0
      - tomli==2.2.1
      - wrapt==1.17.2
prefix: /opt/conda/envs/natsort

test_natsort/test_final_data_transform_factory.py::test_final_data_transform_factory_with_iterable_returns_tuple_with_no_options_example test_natsort/test_final_data_transform_factory.py::test_final_data_transform_factory_with_iterable_returns_tuple_with_no_options test_natsort/test_final_data_transform_factory.py::test_final_data_transform_factory_with_empty_tuple_returns_double_empty_tuple test_natsort/test_final_data_transform_factory.py::test_final_data_transform_factory_with_null_string_first_element_adds_empty_string_on_first_tuple_element test_natsort/test_final_data_transform_factory.py::test_final_data_transform_factory_returns_first_element_in_first_tuple_element_example test_natsort/test_final_data_transform_factory.py::test_final_data_transform_factory_returns_first_element_in_first_tuple_element test_natsort/test_final_data_transform_factory.py::test_final_data_transform_factory_returns_first_element_in_first_tuple_element_caseswapped_with_DUMB_and_LOWERCASEFIRST_example test_natsort/test_final_data_transform_factory.py::test_final_data_transform_factory_returns_first_element_in_first_tuple_element_caseswapped_with_DUMB_and_LOWERCASEFIRST test_natsort/test_natsort_key.py::test__natsort_key_with_numeric_input_and_PATH_returns_number_in_nested_tuple test_natsort/test_natsort_key.py::test__natsort_key_with_bytes_input_and_PATH_returns_number_in_nested_tuple test_natsort/test_natsort_key.py::test__natsort_key_with_tuple_of_paths_and_PATH_returns_triply_nested_tuple test_natsort/test_natsort_key.py::test__natsort_key_with_numeric_input_takes_number_path test_natsort/test_natsort_key.py::test__natsort_key_with_bytes_input_takes_bytes_path test_natsort/test_natsort_key.py::test__natsort_key_with_text_input_takes_string_path test_natsort/test_natsort_key.py::test__natsort_key_with_nested_input_takes_nested_path test_natsort/test_natsort_key.py::test__natsort_key_with_key_argument_applies_key_before_processing test_natsort/test_natsort_keygen.py::test_natsort_key_public_raises_DeprecationWarning_when_called test_natsort/test_natsort_keygen.py::test_natsort_keygen_with_invalid_alg_input_raises_ValueError test_natsort/test_natsort_keygen.py::test_natsort_keygen_returns_natsort_key_that_parses_input test_natsort/test_natsort_keygen.py::test_natsort_keygen_returns_key_that_can_be_used_to_sort_list_in_place_with_same_result_as_natsorted test_natsort/test_natsort_keygen.py::test_natsort_keygen_splits_input_with_defaults test_natsort/test_natsort_keygen.py::test_natsort_keygen_splits_input_with_real test_natsort/test_natsort_keygen.py::test_natsort_keygen_splits_input_with_lowercasefirst_noexp_float test_natsort/test_natsort_keygen.py::test_natsort_keygen_splits_input_with_path test_natsort/test_natsort_keygen.py::test_natsort_keygen_splits_input_with_ignorecase test_natsort/test_natsorted.py::test_natsorted_returns_strings_with_numbers_in_ascending_order test_natsort/test_natsorted.py::test_natsorted_returns_list_of_numbers_sorted_as_signed_floats_with_exponents test_natsort/test_natsorted.py::test_natsorted_returns_list_of_numbers_sorted_as_unsigned_floats_without_exponents_with_NOEXP_option test_natsort/test_natsorted.py::test_natsorted_returns_list_of_numbers_sorted_as_unsigned_ints_with_INT_option test_natsort/test_natsorted.py::test_natsorted_returns_list_of_numbers_sorted_as_unsigned_ints_with_DIGIT_and_VERSION_option test_natsort/test_natsorted.py::test_natsorted_returns_list_of_numbers_sorted_as_signed_ints_with_SIGNED_option test_natsort/test_natsorted.py::test_natsorted_returns_list_of_numbers_sorted_accounting_for_sign_with_SIGNED_option test_natsort/test_natsorted.py::test_natsorted_returns_list_of_numbers_sorted_not_accounting_for_sign_without_SIGNED_option test_natsort/test_natsorted.py::test_natsorted_returns_sorted_list_of_version_numbers_by_default_or_with_VERSION_option test_natsort/test_natsorted.py::test_natsorted_returns_sorted_list_with_mixed_type_input_and_does_not_raise_TypeError_on_Python3 test_natsort/test_natsorted.py::test_natsorted_with_mixed_input_returns_sorted_results_without_error test_natsort/test_natsorted.py::test_natsorted_with_nan_input_returns_sorted_results_with_nan_last_with_NANLAST test_natsort/test_natsorted.py::test_natsorted_with_nan_input_returns_sorted_results_with_nan_first_without_NANLAST test_natsort/test_natsorted.py::test_natsorted_with_mixed_input_raises_TypeError_if_bytes_type_is_involved_on_Python3 test_natsort/test_natsorted.py::test_natsorted_raises_ValueError_for_non_iterable_input test_natsort/test_natsorted.py::test_natsorted_recursivley_applies_key_to_nested_lists_to_return_sorted_nested_list test_natsort/test_natsorted.py::test_natsorted_applies_key_to_each_list_element_before_sorting_list test_natsort/test_natsorted.py::test_natsorted_returns_list_in_reversed_order_with_reverse_option test_natsort/test_natsorted.py::test_natsorted_sorts_OS_generated_paths_incorrectly_without_PATH_option test_natsort/test_natsorted.py::test_natsorted_sorts_OS_generated_paths_correctly_with_PATH_option test_natsort/test_natsorted.py::test_natsorted_can_handle_sorting_paths_and_numbers_with_PATH test_natsort/test_natsorted.py::test_natsorted_returns_results_in_ASCII_order_with_no_case_options test_natsort/test_natsorted.py::test_natsorted_returns_results_sorted_by_lowercase_ASCII_order_with_IGNORECASE test_natsort/test_natsorted.py::test_natsorted_returns_results_in_ASCII_order_but_with_lowercase_letters_first_with_LOWERCASEFIRST test_natsort/test_natsorted.py::test_natsorted_returns_results_with_uppercase_and_lowercase_letters_grouped_together_with_GROUPLETTERS test_natsort/test_natsorted.py::test_natsorted_returns_results_in_natural_order_with_GROUPLETTERS_and_LOWERCASEFIRST test_natsort/test_natsorted.py::test_natsorted_places_uppercase_letters_before_lowercase_letters_for_nested_input test_natsort/test_natsorted.py::test_natsorted_with_LOWERCASEFIRST_places_lowercase_letters_before_uppercase_letters_for_nested_input test_natsort/test_natsorted.py::test_natsorted_with_IGNORECASE_sorts_without_regard_to_case_for_nested_input test_natsort/test_natsorted.py::test_natsorted_sorts_an_odd_collection_of_string test_natsort/test_parse_number_function.py::test_parse_number_factory_makes_function_that_returns_tuple_example test_natsort/test_parse_number_function.py::test_parse_number_factory_makes_function_that_returns_tuple test_natsort/test_parse_number_function.py::test_parse_number_factory_with_PATH_makes_function_that_returns_nested_tuple_example test_natsort/test_parse_number_function.py::test_parse_number_factory_with_PATH_makes_function_that_returns_nested_tuple test_natsort/test_parse_number_function.py::test_parse_number_factory_with_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple_example test_natsort/test_parse_number_function.py::test_parse_number_factory_with_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple test_natsort/test_parse_number_function.py::test_parse_number_factory_with_PATH_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple_example test_natsort/test_parse_number_function.py::test_parse_number_factory_with_PATH_UNGROUPLETTERS_LOCALE_makes_function_that_returns_nested_tuple test_natsort/test_utils.py::test_do_decoding_decodes_bytes_string_to_unicode test_natsort/test_utils.py::test_args_to_enum_raises_TypeError_for_invalid_argument test_natsort/test_utils.py::test_args_to_enum_converts_signed_exp_float_to_ns_F test_natsort/test_utils.py::test_args_to_enum_converts_signed_noexp_float_to_ns_FN test_natsort/test_utils.py::test_args_to_enum_converts_unsigned_exp_float_to_ns_FU test_natsort/test_utils.py::test_args_to_enum_converts_unsigned_unexp_float_to_ns_FNU test_natsort/test_utils.py::test_args_to_enum_converts_float_and_path_and_py3safe_to_ns_FPT test_natsort/test_utils.py::test_args_to_enum_converts_int_and_path_to_ns_IP test_natsort/test_utils.py::test_args_to_enum_converts_unsigned_int_and_py3safe_to_ns_IUT test_natsort/test_utils.py::test_args_to_enum_converts_None_to_ns_IU test_natsort/test_utils.py::test_regex_chooser_returns_correct_regular_expression_object test_natsort/test_utils.py::test_ns_enum_values_have_are_as_expected test_natsort/test_utils.py::test_chain_functions_is_a_no_op_if_no_functions_are_given test_natsort/test_utils.py::test_chain_functions_does_one_function_if_one_function_is_given test_natsort/test_utils.py::test_chain_functions_combines_functions_in_given_order test_natsort/test_utils.py::test_groupletters_returns_letters_with_lowercase_transform_of_letter_example test_natsort/test_utils.py::test_groupeletters_returns_letters_with_lowercase_transform_of_letter test_natsort/test_utils.py::test_sep_inserter_does_nothing_if_no_numbers_example test_natsort/test_utils.py::test_sep_inserter_does_nothing_if_only_one_number_example test_natsort/test_utils.py::test_sep_inserter_inserts_separator_string_between_two_numbers_example test_natsort/test_utils.py::test_path_splitter_splits_path_string_by_separator_example test_natsort/test_utils.py::test_path_splitter_splits_path_string_by_separator test_natsort/test_utils.py::test_path_splitter_splits_path_string_by_separator_and_removes_extension_example test_natsort/test_utils.py::test_path_splitter_splits_path_string_by_separator_and_removes_extension test_natsort/test_utils.py::test_py23_cmp
test_natsort/test_natsort_keygen.py::test_natsort_keygen_splits_input_with_locale test_natsort/test_natsort_keygen.py::test_natsort_keygen_splits_input_with_locale_and_capitalfirst test_natsort/test_natsorted.py::test_natsorted_with_LOCALE_returns_results_sorted_by_lowercase_first_and_grouped_letters test_natsort/test_natsorted.py::test_natsorted_with_LOCALE_and_CAPITALFIRST_returns_results_sorted_by_capital_first_and_ungrouped test_natsort/test_natsorted.py::test_natsorted_with_LOCALE_and_LOWERCASEFIRST_returns_results_sorted_by_uppercase_first_and_grouped_letters test_natsort/test_natsorted.py::test_natsorted_with_LOCALE_and_CAPITALFIRST_and_LOWERCASE_returns_results_sorted_by_capital_last_and_ungrouped test_natsort/test_natsorted.py::test_natsorted_with_LOCALE_and_en_setting_returns_results_sorted_by_en_language test_natsort/test_natsorted.py::test_natsorted_with_LOCALE_and_mixed_input_returns_sorted_results_without_error test_natsort/test_natsorted.py::test_natsorted_with_LOCALE_and_UNGROUPLETTERS_and_mixed_input_returns_sorted_results_without_error test_natsort/test_natsorted.py::test_natsorted_with_PATH_and_LOCALE_and_UNGROUPLETTERS_and_mixed_input_returns_sorted_results_without_error test_natsort/test_utils.py::test_sep_inserter_inserts_separator_between_two_numbers
natsort/ns_enum.py natsort/natsort.py natsort/compat/locale.py natsort/utils.py
natsort/ns_enum.py natsort/natsort.py natsort/compat/locale.py natsort/utils.py