diff options
-rw-r--r-- | .travis.yml | 3 | ||||
-rw-r--r-- | MANIFEST.in | 36 | ||||
-rw-r--r-- | README.rst | 15 | ||||
-rw-r--r-- | docs/source/changelog.rst | 7 | ||||
-rw-r--r-- | natsort/_version.py | 2 | ||||
-rw-r--r-- | natsort/compat/fake_fastnumbers.py | 11 | ||||
-rw-r--r-- | natsort/compat/fastnumbers.py | 2 | ||||
-rw-r--r-- | natsort/compat/locale.py | 2 | ||||
-rw-r--r-- | natsort/unicode_numbers.py | 355 | ||||
-rw-r--r-- | natsort/utils.py | 4 | ||||
-rw-r--r-- | setup.py | 6 | ||||
-rw-r--r-- | test_natsort/compat/hypothesis.py | 13 | ||||
-rw-r--r-- | test_natsort/slow_splitters.py | 3 | ||||
-rw-r--r-- | test_natsort/test_fake_fastnumbers.py | 43 | ||||
-rw-r--r-- | test_natsort/test_locale_help.py | 14 | ||||
-rw-r--r-- | test_natsort/test_main.py | 26 | ||||
-rw-r--r-- | test_natsort/test_unicode_numbers.py | 15 | ||||
-rw-r--r-- | test_natsort/test_utils.py | 114 | ||||
-rw-r--r-- | tox.ini | 2 |
19 files changed, 372 insertions, 301 deletions
diff --git a/.travis.yml b/.travis.yml index 53efa3f..7b35f1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,10 @@ language: python python: - 2.6 - 2.7 -- 3.2 +# - 3.2 - 3.3 - 3.4 +- 3.5 env: - WITH_OPTIONS=true - WITH_OPTIONS=false diff --git a/MANIFEST.in b/MANIFEST.in index 96e4e99..142df79 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,34 +1,14 @@ include README.rst include LICENSE -include natsort/natsort.py -include natsort/_version.py -include natsort/__main__.py -include natsort/__init__.py -include natsort/locale_help.py -include natsort/utils.py -include natsort/ns_enum.py -include natsort/unicode_numbers.py -include natsort/compat/__init__.py -include natsort/compat/py23.py -include natsort/compat/fake_fastnumbers.py -include natsort/compat/fastnumbers.py -include natsort/compat/locale.py -include natsort/compat/pathlib.py -include natsort/compat/pathlib.py -include test_natsort/profile_natsorted.py -include test_natsort/stress_natsort.py -include test_natsort/slow_splitters.py -include test_natsort/test_natsort.py -include test_natsort/test_locale_help.py -include test_natsort/test_fake_fastnumbers.py -include test_natsort/test_main.py -include test_natsort/test_utils.py -include test_natsort/test_unicode_numbers.py -include test_natsort/compat/__init__.py -include test_natsort/compat/hypothesis.py -include test_natsort/compat/locale.py -include test_natsort/compat/mock.py +recursive-include natsort *.py +recursive-include test_natsort *.py include setup.py include setup.cfg +include tox.ini +include .travis.yml +include .coveragerc +include .gitignore +include .hgignore prune natsort/__pycache__ +prune test_natsort/__pycache__ graft docs/source @@ -56,7 +56,7 @@ Sorting versions is handled properly by default (as of ``natsort`` version >= 4. ['version-1.9', 'version-1.10', 'version-1.11', 'version-2.0'] If you need to sort release candidates, please see -`this useful hack <http://pythonhosted.org//natsort/examples.htm#rc-sorting>`_ . +`this useful hack <http://pythonhosted.org//natsort/examples.html#rc-sorting>`_ . You can also perform locale-aware sorting (or "human sorting"), where the non-numeric characters are ordered based on their meaning, not on their @@ -225,6 +225,13 @@ History These are the last three entries of the changelog. See the package documentation for the complete `changelog <http://pythonhosted.org//natsort/changelog.html>`_. +11-01-2015 v. 4.0.4 +''''''''''''''''''' + + - Improved coverage of unit tests. + - Unit tests use new and improved hypothesis library. + - Fixed compatibility issues with Python 3.5 + 06-25-2015 v. 4.0.3 ''''''''''''''''''' @@ -236,9 +243,3 @@ for the complete `changelog <http://pythonhosted.org//natsort/changelog.html>`_. - Added back Python 2.6 and Python 3.2 compatibility. Unit testing is now performed for these versions. - Consolidated under-the-hood compatibility functionality. - -06-04-2015 v. 4.0.1 -''''''''''''''''''' - - - Added support for sorting NaN by internally converting to -Infinity - or +Infinity diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 5a7d897..349b309 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -3,6 +3,13 @@ Changelog --------- +11-01-2015 v. 4.0.4 +''''''''''''''''''' + + - Improved coverage of unit tests. + - Unit tests use new and improved hypothesis library. + - Fixed compatibility issues with Python 3.5 + 06-25-2015 v. 4.0.3 ''''''''''''''''''' diff --git a/natsort/_version.py b/natsort/_version.py index 8c229c5..1e393ca 100644 --- a/natsort/_version.py +++ b/natsort/_version.py @@ -6,4 +6,4 @@ from __future__ import ( absolute_import ) -__version__ = '4.0.3' +__version__ = '4.0.4' diff --git a/natsort/compat/fake_fastnumbers.py b/natsort/compat/fake_fastnumbers.py index 6fd954a..115b028 100644 --- a/natsort/compat/fake_fastnumbers.py +++ b/natsort/compat/fake_fastnumbers.py @@ -15,11 +15,12 @@ from __future__ import ( import sys import re import unicodedata -float_re = re.compile(r'[-+]?(\d*\.?\d+(?:[eE][-+]?\d+)?|inf(?:inity)?|nan)$') +s = r'\s*[-+]?(\d*\.?\d+(?:[eE][-+]?\d+)?|inf(?:inity)?|nan)\s*$' +float_re = re.compile(s) if sys.version[0] == '2': - int_re = re.compile(r'[-+]?\d+[lL]?$') + int_re = re.compile(r'\s*[-+]?\d+[lL]?\s*$') else: - int_re = re.compile(r'[-+]?\d+$') + int_re = re.compile(r'\s*[-+]?\d+\s*$') long = int unicode = str @@ -29,7 +30,7 @@ def fast_float(x, regex_matcher=float_re.match, uni=unicodedata.numeric): if type(x) in (int, long, float): return float(x) elif regex_matcher(x): - return float(x) + return float(x.strip()) elif type(x) == unicode and len(x) == 1 and uni(x, None) is not None: return uni(x) else: @@ -43,7 +44,7 @@ def fast_int(x, regex_matcher=int_re.match, uni=unicodedata.digit): if type(x) in (int, long, float): return int(x) elif regex_matcher(x): - return int(x.rstrip('Ll')) + return int(x.strip().rstrip('Ll')) elif type(x) == unicode and len(x) == 1 and uni(x, None) is not None: return uni(x) else: diff --git a/natsort/compat/fastnumbers.py b/natsort/compat/fastnumbers.py index c2c603b..2dc9bbe 100644 --- a/natsort/compat/fastnumbers.py +++ b/natsort/compat/fastnumbers.py @@ -18,7 +18,7 @@ try: import fastnumbers v = list(map(int, fastnumbers.__version__.split('.'))) if not (v[0] >= 0 and v[1] >= 5): # Require >= version 0.5.0. - raise ImportError + raise ImportError # pragma: no cover except ImportError: from natsort.compat.fake_fastnumbers import ( fast_float, diff --git a/natsort/compat/locale.py b/natsort/compat/locale.py index 618f666..1e1d596 100644 --- a/natsort/compat/locale.py +++ b/natsort/compat/locale.py @@ -23,7 +23,7 @@ try: # then create a sort key from that def get_pyicu_transform(l, _d={}): if l not in _d: - if l == (None, None): + if l == (None, None): # pragma: no cover c = PyICU.Collator.createInstance(PyICU.Locale()) else: loc = '.'.join(l) diff --git a/natsort/unicode_numbers.py b/natsort/unicode_numbers.py index c93ed56..a810ff9 100644 --- a/natsort/unicode_numbers.py +++ b/natsort/unicode_numbers.py @@ -20,146 +20,219 @@ from natsort.compat.py23 import py23_unichr # runtime penalty, the hex values of the Unicode numeric characters # are hard-coded below. numeric_hex = [ - 0XB2, 0XB3, 0XB9, 0XBC, 0XBD, 0XBE, 0X660, 0X661, 0X662, 0X663, 0X664, - 0X665, 0X666, 0X667, 0X668, 0X669, 0X6F0, 0X6F1, 0X6F2, 0X6F3, 0X6F4, - 0X6F5, 0X6F6, 0X6F7, 0X6F8, 0X6F9, 0X7C0, 0X7C1, 0X7C2, 0X7C3, 0X7C4, - 0X7C5, 0X7C6, 0X7C7, 0X7C8, 0X7C9, 0X966, 0X967, 0X968, 0X969, 0X96A, - 0X96B, 0X96C, 0X96D, 0X96E, 0X96F, 0X9E6, 0X9E7, 0X9E8, 0X9E9, 0X9EA, - 0X9EB, 0X9EC, 0X9ED, 0X9EE, 0X9EF, 0X9F4, 0X9F5, 0X9F6, 0X9F7, 0X9F8, - 0X9F9, 0XA66, 0XA67, 0XA68, 0XA69, 0XA6A, 0XA6B, 0XA6C, 0XA6D, 0XA6E, - 0XA6F, 0XAE6, 0XAE7, 0XAE8, 0XAE9, 0XAEA, 0XAEB, 0XAEC, 0XAED, 0XAEE, - 0XAEF, 0XB66, 0XB67, 0XB68, 0XB69, 0XB6A, 0XB6B, 0XB6C, 0XB6D, 0XB6E, - 0XB6F, 0XB72, 0XB73, 0XB74, 0XB75, 0XB76, 0XB77, 0XBE6, 0XBE7, 0XBE8, - 0XBE9, 0XBEA, 0XBEB, 0XBEC, 0XBED, 0XBEE, 0XBEF, 0XBF0, 0XBF1, 0XBF2, - 0XC66, 0XC67, 0XC68, 0XC69, 0XC6A, 0XC6B, 0XC6C, 0XC6D, 0XC6E, 0XC6F, - 0XC78, 0XC79, 0XC7A, 0XC7B, 0XC7C, 0XC7D, 0XC7E, 0XCE6, 0XCE7, 0XCE8, - 0XCE9, 0XCEA, 0XCEB, 0XCEC, 0XCED, 0XCEE, 0XCEF, 0XD66, 0XD67, 0XD68, - 0XD69, 0XD6A, 0XD6B, 0XD6C, 0XD6D, 0XD6E, 0XD6F, 0XD70, 0XD71, 0XD72, - 0XD73, 0XD74, 0XD75, 0XE50, 0XE51, 0XE52, 0XE53, 0XE54, 0XE55, 0XE56, - 0XE57, 0XE58, 0XE59, 0XED0, 0XED1, 0XED2, 0XED3, 0XED4, 0XED5, 0XED6, - 0XED7, 0XED8, 0XED9, 0XF20, 0XF21, 0XF22, 0XF23, 0XF24, 0XF25, 0XF26, - 0XF27, 0XF28, 0XF29, 0XF2A, 0XF2B, 0XF2C, 0XF2D, 0XF2E, 0XF2F, 0XF30, - 0XF31, 0XF32, 0XF33, 0X1040, 0X1041, 0X1042, 0X1043, 0X1044, 0X1045, - 0X1046, 0X1047, 0X1048, 0X1049, 0X1090, 0X1091, 0X1092, 0X1093, 0X1094, - 0X1095, 0X1096, 0X1097, 0X1098, 0X1099, 0X1369, 0X136A, 0X136B, 0X136C, - 0X136D, 0X136E, 0X136F, 0X1370, 0X1371, 0X1372, 0X1373, 0X1374, 0X1375, - 0X1376, 0X1377, 0X1378, 0X1379, 0X137A, 0X137B, 0X137C, 0X16EE, 0X16EF, - 0X16F0, 0X17E0, 0X17E1, 0X17E2, 0X17E3, 0X17E4, 0X17E5, 0X17E6, 0X17E7, - 0X17E8, 0X17E9, 0X17F0, 0X17F1, 0X17F2, 0X17F3, 0X17F4, 0X17F5, 0X17F6, - 0X17F7, 0X17F8, 0X17F9, 0X1810, 0X1811, 0X1812, 0X1813, 0X1814, 0X1815, - 0X1816, 0X1817, 0X1818, 0X1819, 0X1946, 0X1947, 0X1948, 0X1949, 0X194A, - 0X194B, 0X194C, 0X194D, 0X194E, 0X194F, 0X19D0, 0X19D1, 0X19D2, 0X19D3, - 0X19D4, 0X19D5, 0X19D6, 0X19D7, 0X19D8, 0X19D9, 0X19DA, 0X1A80, 0X1A81, - 0X1A82, 0X1A83, 0X1A84, 0X1A85, 0X1A86, 0X1A87, 0X1A88, 0X1A89, 0X1A90, - 0X1A91, 0X1A92, 0X1A93, 0X1A94, 0X1A95, 0X1A96, 0X1A97, 0X1A98, 0X1A99, - 0X1B50, 0X1B51, 0X1B52, 0X1B53, 0X1B54, 0X1B55, 0X1B56, 0X1B57, 0X1B58, - 0X1B59, 0X1BB0, 0X1BB1, 0X1BB2, 0X1BB3, 0X1BB4, 0X1BB5, 0X1BB6, 0X1BB7, - 0X1BB8, 0X1BB9, 0X1C40, 0X1C41, 0X1C42, 0X1C43, 0X1C44, 0X1C45, 0X1C46, - 0X1C47, 0X1C48, 0X1C49, 0X1C50, 0X1C51, 0X1C52, 0X1C53, 0X1C54, 0X1C55, - 0X1C56, 0X1C57, 0X1C58, 0X1C59, 0X2070, 0X2074, 0X2075, 0X2076, 0X2077, - 0X2078, 0X2079, 0X2080, 0X2081, 0X2082, 0X2083, 0X2084, 0X2085, 0X2086, - 0X2087, 0X2088, 0X2089, 0X2150, 0X2151, 0X2152, 0X2153, 0X2154, 0X2155, - 0X2156, 0X2157, 0X2158, 0X2159, 0X215A, 0X215B, 0X215C, 0X215D, 0X215E, - 0X215F, 0X2160, 0X2161, 0X2162, 0X2163, 0X2164, 0X2165, 0X2166, 0X2167, - 0X2168, 0X2169, 0X216A, 0X216B, 0X216C, 0X216D, 0X216E, 0X216F, 0X2170, - 0X2171, 0X2172, 0X2173, 0X2174, 0X2175, 0X2176, 0X2177, 0X2178, 0X2179, - 0X217A, 0X217B, 0X217C, 0X217D, 0X217E, 0X217F, 0X2180, 0X2181, 0X2182, - 0X2185, 0X2186, 0X2187, 0X2188, 0X2189, 0X2460, 0X2461, 0X2462, 0X2463, - 0X2464, 0X2465, 0X2466, 0X2467, 0X2468, 0X2469, 0X246A, 0X246B, 0X246C, - 0X246D, 0X246E, 0X246F, 0X2470, 0X2471, 0X2472, 0X2473, 0X2474, 0X2475, - 0X2476, 0X2477, 0X2478, 0X2479, 0X247A, 0X247B, 0X247C, 0X247D, 0X247E, - 0X247F, 0X2480, 0X2481, 0X2482, 0X2483, 0X2484, 0X2485, 0X2486, 0X2487, - 0X2488, 0X2489, 0X248A, 0X248B, 0X248C, 0X248D, 0X248E, 0X248F, 0X2490, - 0X2491, 0X2492, 0X2493, 0X2494, 0X2495, 0X2496, 0X2497, 0X2498, 0X2499, - 0X249A, 0X249B, 0X24EA, 0X24EB, 0X24EC, 0X24ED, 0X24EE, 0X24EF, 0X24F0, - 0X24F1, 0X24F2, 0X24F3, 0X24F4, 0X24F5, 0X24F6, 0X24F7, 0X24F8, 0X24F9, - 0X24FA, 0X24FB, 0X24FC, 0X24FD, 0X24FE, 0X24FF, 0X2776, 0X2777, 0X2778, - 0X2779, 0X277A, 0X277B, 0X277C, 0X277D, 0X277E, 0X277F, 0X2780, 0X2781, - 0X2782, 0X2783, 0X2784, 0X2785, 0X2786, 0X2787, 0X2788, 0X2789, 0X278A, - 0X278B, 0X278C, 0X278D, 0X278E, 0X278F, 0X2790, 0X2791, 0X2792, 0X2793, - 0X2CFD, 0X3007, 0X3021, 0X3022, 0X3023, 0X3024, 0X3025, 0X3026, 0X3027, - 0X3028, 0X3029, 0X3038, 0X3039, 0X303A, 0X3192, 0X3193, 0X3194, 0X3195, - 0X3220, 0X3221, 0X3222, 0X3223, 0X3224, 0X3225, 0X3226, 0X3227, 0X3228, - 0X3229, 0X3248, 0X3249, 0X324A, 0X324B, 0X324C, 0X324D, 0X324E, 0X324F, - 0X3251, 0X3252, 0X3253, 0X3254, 0X3255, 0X3256, 0X3257, 0X3258, 0X3259, - 0X325A, 0X325B, 0X325C, 0X325D, 0X325E, 0X325F, 0X3280, 0X3281, 0X3282, - 0X3283, 0X3284, 0X3285, 0X3286, 0X3287, 0X3288, 0X3289, 0X32B1, 0X32B2, - 0X32B3, 0X32B4, 0X32B5, 0X32B6, 0X32B7, 0X32B8, 0X32B9, 0X32BA, 0X32BB, - 0X32BC, 0X32BD, 0X32BE, 0X32BF, 0X3405, 0X3483, 0X382A, 0X3B4D, 0X4E00, - 0X4E03, 0X4E07, 0X4E09, 0X4E5D, 0X4E8C, 0X4E94, 0X4E96, 0X4EBF, 0X4EC0, - 0X4EDF, 0X4EE8, 0X4F0D, 0X4F70, 0X5104, 0X5146, 0X5169, 0X516B, 0X516D, - 0X5341, 0X5343, 0X5344, 0X5345, 0X534C, 0X53C1, 0X53C2, 0X53C3, 0X53C4, - 0X56DB, 0X58F1, 0X58F9, 0X5E7A, 0X5EFE, 0X5EFF, 0X5F0C, 0X5F0D, 0X5F0E, - 0X5F10, 0X62FE, 0X634C, 0X67D2, 0X6F06, 0X7396, 0X767E, 0X8086, 0X842C, - 0X8CAE, 0X8CB3, 0X8D30, 0X9621, 0X9646, 0X964C, 0X9678, 0X96F6, 0XA620, - 0XA621, 0XA622, 0XA623, 0XA624, 0XA625, 0XA626, 0XA627, 0XA628, 0XA629, - 0XA6E6, 0XA6E7, 0XA6E8, 0XA6E9, 0XA6EA, 0XA6EB, 0XA6EC, 0XA6ED, 0XA6EE, - 0XA6EF, 0XA830, 0XA831, 0XA832, 0XA833, 0XA834, 0XA835, 0XA8D0, 0XA8D1, - 0XA8D2, 0XA8D3, 0XA8D4, 0XA8D5, 0XA8D6, 0XA8D7, 0XA8D8, 0XA8D9, 0XA900, - 0XA901, 0XA902, 0XA903, 0XA904, 0XA905, 0XA906, 0XA907, 0XA908, 0XA909, - 0XA9D0, 0XA9D1, 0XA9D2, 0XA9D3, 0XA9D4, 0XA9D5, 0XA9D6, 0XA9D7, 0XA9D8, - 0XA9D9, 0XAA50, 0XAA51, 0XAA52, 0XAA53, 0XAA54, 0XAA55, 0XAA56, 0XAA57, - 0XAA58, 0XAA59, 0XABF0, 0XABF1, 0XABF2, 0XABF3, 0XABF4, 0XABF5, 0XABF6, - 0XABF7, 0XABF8, 0XABF9, 0XF96B, 0XF973, 0XF978, 0XF9B2, 0XF9D1, 0XF9D3, - 0XF9FD, 0XFF10, 0XFF11, 0XFF12, 0XFF13, 0XFF14, 0XFF15, 0XFF16, 0XFF17, - 0XFF18, 0XFF19, 0X10107, 0X10108, 0X10109, 0X1010A, 0X1010B, 0X1010C, - 0X1010D, 0X1010E, 0X1010F, 0X10110, 0X10111, 0X10112, 0X10113, 0X10114, - 0X10115, 0X10116, 0X10117, 0X10118, 0X10119, 0X1011A, 0X1011B, 0X1011C, - 0X1011D, 0X1011E, 0X1011F, 0X10120, 0X10121, 0X10122, 0X10123, 0X10124, - 0X10125, 0X10126, 0X10127, 0X10128, 0X10129, 0X1012A, 0X1012B, 0X1012C, - 0X1012D, 0X1012E, 0X1012F, 0X10130, 0X10131, 0X10132, 0X10133, 0X10140, - 0X10141, 0X10142, 0X10143, 0X10144, 0X10145, 0X10146, 0X10147, 0X10148, - 0X10149, 0X1014A, 0X1014B, 0X1014C, 0X1014D, 0X1014E, 0X1014F, 0X10150, - 0X10151, 0X10152, 0X10153, 0X10154, 0X10155, 0X10156, 0X10157, 0X10158, - 0X10159, 0X1015A, 0X1015B, 0X1015C, 0X1015D, 0X1015E, 0X1015F, 0X10160, - 0X10161, 0X10162, 0X10163, 0X10164, 0X10165, 0X10166, 0X10167, 0X10168, - 0X10169, 0X1016A, 0X1016B, 0X1016C, 0X1016D, 0X1016E, 0X1016F, 0X10170, - 0X10171, 0X10172, 0X10173, 0X10174, 0X10175, 0X10176, 0X10177, 0X10178, - 0X1018A, 0X10320, 0X10321, 0X10322, 0X10323, 0X10341, 0X1034A, 0X103D1, - 0X103D2, 0X103D3, 0X103D4, 0X103D5, 0X104A0, 0X104A1, 0X104A2, 0X104A3, - 0X104A4, 0X104A5, 0X104A6, 0X104A7, 0X104A8, 0X104A9, 0X10858, 0X10859, - 0X1085A, 0X1085B, 0X1085C, 0X1085D, 0X1085E, 0X1085F, 0X10916, 0X10917, - 0X10918, 0X10919, 0X1091A, 0X1091B, 0X10A40, 0X10A41, 0X10A42, 0X10A43, - 0X10A44, 0X10A45, 0X10A46, 0X10A47, 0X10A7D, 0X10A7E, 0X10B58, 0X10B59, - 0X10B5A, 0X10B5B, 0X10B5C, 0X10B5D, 0X10B5E, 0X10B5F, 0X10B78, 0X10B79, - 0X10B7A, 0X10B7B, 0X10B7C, 0X10B7D, 0X10B7E, 0X10B7F, 0X10E60, 0X10E61, - 0X10E62, 0X10E63, 0X10E64, 0X10E65, 0X10E66, 0X10E67, 0X10E68, 0X10E69, - 0X10E6A, 0X10E6B, 0X10E6C, 0X10E6D, 0X10E6E, 0X10E6F, 0X10E70, 0X10E71, - 0X10E72, 0X10E73, 0X10E74, 0X10E75, 0X10E76, 0X10E77, 0X10E78, 0X10E79, - 0X10E7A, 0X10E7B, 0X10E7C, 0X10E7D, 0X10E7E, 0X11052, 0X11053, 0X11054, - 0X11055, 0X11056, 0X11057, 0X11058, 0X11059, 0X1105A, 0X1105B, 0X1105C, - 0X1105D, 0X1105E, 0X1105F, 0X11060, 0X11061, 0X11062, 0X11063, 0X11064, - 0X11065, 0X11066, 0X11067, 0X11068, 0X11069, 0X1106A, 0X1106B, 0X1106C, - 0X1106D, 0X1106E, 0X1106F, 0X110F0, 0X110F1, 0X110F2, 0X110F3, 0X110F4, - 0X110F5, 0X110F6, 0X110F7, 0X110F8, 0X110F9, 0X11136, 0X11137, 0X11138, - 0X11139, 0X1113A, 0X1113B, 0X1113C, 0X1113D, 0X1113E, 0X1113F, 0X111D0, - 0X111D1, 0X111D2, 0X111D3, 0X111D4, 0X111D5, 0X111D6, 0X111D7, 0X111D8, - 0X111D9, 0X116C0, 0X116C1, 0X116C2, 0X116C3, 0X116C4, 0X116C5, 0X116C6, - 0X116C7, 0X116C8, 0X116C9, 0X12400, 0X12401, 0X12402, 0X12403, 0X12404, - 0X12405, 0X12406, 0X12407, 0X12408, 0X12409, 0X1240A, 0X1240B, 0X1240C, - 0X1240D, 0X1240E, 0X1240F, 0X12410, 0X12411, 0X12412, 0X12413, 0X12414, - 0X12415, 0X12416, 0X12417, 0X12418, 0X12419, 0X1241A, 0X1241B, 0X1241C, - 0X1241D, 0X1241E, 0X1241F, 0X12420, 0X12421, 0X12422, 0X12423, 0X12424, - 0X12425, 0X12426, 0X12427, 0X12428, 0X12429, 0X1242A, 0X1242B, 0X1242C, - 0X1242D, 0X1242E, 0X1242F, 0X12430, 0X12431, 0X12432, 0X12433, 0X12434, - 0X12435, 0X12436, 0X12437, 0X12438, 0X12439, 0X1243A, 0X1243B, 0X1243C, - 0X1243D, 0X1243E, 0X1243F, 0X12440, 0X12441, 0X12442, 0X12443, 0X12444, - 0X12445, 0X12446, 0X12447, 0X12448, 0X12449, 0X1244A, 0X1244B, 0X1244C, - 0X1244D, 0X1244E, 0X1244F, 0X12450, 0X12451, 0X12452, 0X12453, 0X12454, - 0X12455, 0X12456, 0X12457, 0X12458, 0X12459, 0X1245A, 0X1245B, 0X1245C, - 0X1245D, 0X1245E, 0X1245F, 0X12460, 0X12461, 0X12462, 0X1D360, 0X1D361, - 0X1D362, 0X1D363, 0X1D364, 0X1D365, 0X1D366, 0X1D367, 0X1D368, 0X1D369, - 0X1D36A, 0X1D36B, 0X1D36C, 0X1D36D, 0X1D36E, 0X1D36F, 0X1D370, 0X1D371, - 0X1D7CE, 0X1D7CF, 0X1D7D0, 0X1D7D1, 0X1D7D2, 0X1D7D3, 0X1D7D4, 0X1D7D5, - 0X1D7D6, 0X1D7D7, 0X1D7D8, 0X1D7D9, 0X1D7DA, 0X1D7DB, 0X1D7DC, 0X1D7DD, - 0X1D7DE, 0X1D7DF, 0X1D7E0, 0X1D7E1, 0X1D7E2, 0X1D7E3, 0X1D7E4, 0X1D7E5, - 0X1D7E6, 0X1D7E7, 0X1D7E8, 0X1D7E9, 0X1D7EA, 0X1D7EB, 0X1D7EC, 0X1D7ED, - 0X1D7EE, 0X1D7EF, 0X1D7F0, 0X1D7F1, 0X1D7F2, 0X1D7F3, 0X1D7F4, 0X1D7F5, - 0X1D7F6, 0X1D7F7, 0X1D7F8, 0X1D7F9, 0X1D7FA, 0X1D7FB, 0X1D7FC, 0X1D7FD, - 0X1D7FE, 0X1D7FF, 0X1F100, 0X1F101, 0X1F102, 0X1F103, 0X1F104, 0X1F105, - 0X1F106, 0X1F107, 0X1F108, 0X1F109, 0X1F10A, 0X20001, 0X20064, 0X200E2, - 0X20121, 0X2092A, 0X20983, 0X2098C, 0X2099C, 0X20AEA, 0X20AFD, 0X20B19, - 0X22390, 0X22998, 0X23B1B, 0X2626D, 0X2F890, + 0X30, 0X31, 0X32, 0X33, 0X34, 0X35, 0X36, 0X37, 0X38, + 0X39, 0XB2, 0XB3, 0XB9, 0XBC, 0XBD, 0XBE, 0X660, 0X661, + 0X662, 0X663, 0X664, 0X665, 0X666, 0X667, 0X668, 0X669, + 0X6F0, 0X6F1, 0X6F2, 0X6F3, 0X6F4, 0X6F5, 0X6F6, 0X6F7, + 0X6F8, 0X6F9, 0X7C0, 0X7C1, 0X7C2, 0X7C3, 0X7C4, 0X7C5, + 0X7C6, 0X7C7, 0X7C8, 0X7C9, 0X966, 0X967, 0X968, 0X969, + 0X96A, 0X96B, 0X96C, 0X96D, 0X96E, 0X96F, 0X9E6, 0X9E7, + 0X9E8, 0X9E9, 0X9EA, 0X9EB, 0X9EC, 0X9ED, 0X9EE, 0X9EF, + 0X9F4, 0X9F5, 0X9F6, 0X9F7, 0X9F8, 0X9F9, 0XA66, 0XA67, + 0XA68, 0XA69, 0XA6A, 0XA6B, 0XA6C, 0XA6D, 0XA6E, 0XA6F, + 0XAE6, 0XAE7, 0XAE8, 0XAE9, 0XAEA, 0XAEB, 0XAEC, 0XAED, + 0XAEE, 0XAEF, 0XB66, 0XB67, 0XB68, 0XB69, 0XB6A, 0XB6B, + 0XB6C, 0XB6D, 0XB6E, 0XB6F, 0XB72, 0XB73, 0XB74, 0XB75, + 0XB76, 0XB77, 0XBE6, 0XBE7, 0XBE8, 0XBE9, 0XBEA, 0XBEB, + 0XBEC, 0XBED, 0XBEE, 0XBEF, 0XBF0, 0XBF1, 0XBF2, 0XC66, + 0XC67, 0XC68, 0XC69, 0XC6A, 0XC6B, 0XC6C, 0XC6D, 0XC6E, + 0XC6F, 0XC78, 0XC79, 0XC7A, 0XC7B, 0XC7C, 0XC7D, 0XC7E, + 0XCE6, 0XCE7, 0XCE8, 0XCE9, 0XCEA, 0XCEB, 0XCEC, 0XCED, + 0XCEE, 0XCEF, 0XD66, 0XD67, 0XD68, 0XD69, 0XD6A, 0XD6B, + 0XD6C, 0XD6D, 0XD6E, 0XD6F, 0XD70, 0XD71, 0XD72, 0XD73, + 0XD74, 0XD75, 0XDE6, 0XDE7, 0XDE8, 0XDE9, 0XDEA, 0XDEB, + 0XDEC, 0XDED, 0XDEE, 0XDEF, 0XE50, 0XE51, 0XE52, 0XE53, + 0XE54, 0XE55, 0XE56, 0XE57, 0XE58, 0XE59, 0XED0, 0XED1, + 0XED2, 0XED3, 0XED4, 0XED5, 0XED6, 0XED7, 0XED8, 0XED9, + 0XF20, 0XF21, 0XF22, 0XF23, 0XF24, 0XF25, 0XF26, 0XF27, + 0XF28, 0XF29, 0XF2A, 0XF2B, 0XF2C, 0XF2D, 0XF2E, 0XF2F, + 0XF30, 0XF31, 0XF32, 0XF33, 0X1040, 0X1041, 0X1042, 0X1043, + 0X1044, 0X1045, 0X1046, 0X1047, 0X1048, 0X1049, 0X1090, + 0X1091, 0X1092, 0X1093, 0X1094, 0X1095, 0X1096, 0X1097, + 0X1098, 0X1099, 0X1369, 0X136A, 0X136B, 0X136C, 0X136D, + 0X136E, 0X136F, 0X1370, 0X1371, 0X1372, 0X1373, 0X1374, + 0X1375, 0X1376, 0X1377, 0X1378, 0X1379, 0X137A, 0X137B, + 0X137C, 0X16EE, 0X16EF, 0X16F0, 0X17E0, 0X17E1, 0X17E2, + 0X17E3, 0X17E4, 0X17E5, 0X17E6, 0X17E7, 0X17E8, 0X17E9, + 0X17F0, 0X17F1, 0X17F2, 0X17F3, 0X17F4, 0X17F5, 0X17F6, + 0X17F7, 0X17F8, 0X17F9, 0X1810, 0X1811, 0X1812, 0X1813, + 0X1814, 0X1815, 0X1816, 0X1817, 0X1818, 0X1819, 0X1946, + 0X1947, 0X1948, 0X1949, 0X194A, 0X194B, 0X194C, 0X194D, + 0X194E, 0X194F, 0X19D0, 0X19D1, 0X19D2, 0X19D3, 0X19D4, + 0X19D5, 0X19D6, 0X19D7, 0X19D8, 0X19D9, 0X19DA, 0X1A80, + 0X1A81, 0X1A82, 0X1A83, 0X1A84, 0X1A85, 0X1A86, 0X1A87, + 0X1A88, 0X1A89, 0X1A90, 0X1A91, 0X1A92, 0X1A93, 0X1A94, + 0X1A95, 0X1A96, 0X1A97, 0X1A98, 0X1A99, 0X1B50, 0X1B51, + 0X1B52, 0X1B53, 0X1B54, 0X1B55, 0X1B56, 0X1B57, 0X1B58, + 0X1B59, 0X1BB0, 0X1BB1, 0X1BB2, 0X1BB3, 0X1BB4, 0X1BB5, + 0X1BB6, 0X1BB7, 0X1BB8, 0X1BB9, 0X1C40, 0X1C41, 0X1C42, + 0X1C43, 0X1C44, 0X1C45, 0X1C46, 0X1C47, 0X1C48, 0X1C49, + 0X1C50, 0X1C51, 0X1C52, 0X1C53, 0X1C54, 0X1C55, 0X1C56, + 0X1C57, 0X1C58, 0X1C59, 0X2070, 0X2074, 0X2075, 0X2076, + 0X2077, 0X2078, 0X2079, 0X2080, 0X2081, 0X2082, 0X2083, + 0X2084, 0X2085, 0X2086, 0X2087, 0X2088, 0X2089, 0X2150, + 0X2151, 0X2152, 0X2153, 0X2154, 0X2155, 0X2156, 0X2157, + 0X2158, 0X2159, 0X215A, 0X215B, 0X215C, 0X215D, 0X215E, + 0X215F, 0X2160, 0X2161, 0X2162, 0X2163, 0X2164, 0X2165, + 0X2166, 0X2167, 0X2168, 0X2169, 0X216A, 0X216B, 0X216C, + 0X216D, 0X216E, 0X216F, 0X2170, 0X2171, 0X2172, 0X2173, + 0X2174, 0X2175, 0X2176, 0X2177, 0X2178, 0X2179, 0X217A, + 0X217B, 0X217C, 0X217D, 0X217E, 0X217F, 0X2180, 0X2181, + 0X2182, 0X2185, 0X2186, 0X2187, 0X2188, 0X2189, 0X2460, + 0X2461, 0X2462, 0X2463, 0X2464, 0X2465, 0X2466, 0X2467, + 0X2468, 0X2469, 0X246A, 0X246B, 0X246C, 0X246D, 0X246E, + 0X246F, 0X2470, 0X2471, 0X2472, 0X2473, 0X2474, 0X2475, + 0X2476, 0X2477, 0X2478, 0X2479, 0X247A, 0X247B, 0X247C, + 0X247D, 0X247E, 0X247F, 0X2480, 0X2481, 0X2482, 0X2483, + 0X2484, 0X2485, 0X2486, 0X2487, 0X2488, 0X2489, 0X248A, + 0X248B, 0X248C, 0X248D, 0X248E, 0X248F, 0X2490, 0X2491, + 0X2492, 0X2493, 0X2494, 0X2495, 0X2496, 0X2497, 0X2498, + 0X2499, 0X249A, 0X249B, 0X24EA, 0X24EB, 0X24EC, 0X24ED, + 0X24EE, 0X24EF, 0X24F0, 0X24F1, 0X24F2, 0X24F3, 0X24F4, + 0X24F5, 0X24F6, 0X24F7, 0X24F8, 0X24F9, 0X24FA, 0X24FB, + 0X24FC, 0X24FD, 0X24FE, 0X24FF, 0X2776, 0X2777, 0X2778, + 0X2779, 0X277A, 0X277B, 0X277C, 0X277D, 0X277E, 0X277F, + 0X2780, 0X2781, 0X2782, 0X2783, 0X2784, 0X2785, 0X2786, + 0X2787, 0X2788, 0X2789, 0X278A, 0X278B, 0X278C, 0X278D, + 0X278E, 0X278F, 0X2790, 0X2791, 0X2792, 0X2793, 0X2CFD, + 0X3007, 0X3021, 0X3022, 0X3023, 0X3024, 0X3025, 0X3026, + 0X3027, 0X3028, 0X3029, 0X3038, 0X3039, 0X303A, 0X3192, + 0X3193, 0X3194, 0X3195, 0X3220, 0X3221, 0X3222, 0X3223, + 0X3224, 0X3225, 0X3226, 0X3227, 0X3228, 0X3229, 0X3248, + 0X3249, 0X324A, 0X324B, 0X324C, 0X324D, 0X324E, 0X324F, + 0X3251, 0X3252, 0X3253, 0X3254, 0X3255, 0X3256, 0X3257, + 0X3258, 0X3259, 0X325A, 0X325B, 0X325C, 0X325D, 0X325E, + 0X325F, 0X3280, 0X3281, 0X3282, 0X3283, 0X3284, 0X3285, + 0X3286, 0X3287, 0X3288, 0X3289, 0X32B1, 0X32B2, 0X32B3, + 0X32B4, 0X32B5, 0X32B6, 0X32B7, 0X32B8, 0X32B9, 0X32BA, + 0X32BB, 0X32BC, 0X32BD, 0X32BE, 0X32BF, 0X3405, 0X3483, + 0X382A, 0X3B4D, 0X4E00, 0X4E03, 0X4E07, 0X4E09, 0X4E5D, + 0X4E8C, 0X4E94, 0X4E96, 0X4EBF, 0X4EC0, 0X4EDF, 0X4EE8, + 0X4F0D, 0X4F70, 0X5104, 0X5146, 0X5169, 0X516B, 0X516D, + 0X5341, 0X5343, 0X5344, 0X5345, 0X534C, 0X53C1, 0X53C2, + 0X53C3, 0X53C4, 0X56DB, 0X58F1, 0X58F9, 0X5E7A, 0X5EFE, + 0X5EFF, 0X5F0C, 0X5F0D, 0X5F0E, 0X5F10, 0X62FE, 0X634C, + 0X67D2, 0X6F06, 0X7396, 0X767E, 0X8086, 0X842C, 0X8CAE, + 0X8CB3, 0X8D30, 0X9621, 0X9646, 0X964C, 0X9678, 0X96F6, + 0XA620, 0XA621, 0XA622, 0XA623, 0XA624, 0XA625, 0XA626, + 0XA627, 0XA628, 0XA629, 0XA6E6, 0XA6E7, 0XA6E8, 0XA6E9, + 0XA6EA, 0XA6EB, 0XA6EC, 0XA6ED, 0XA6EE, 0XA6EF, 0XA830, + 0XA831, 0XA832, 0XA833, 0XA834, 0XA835, 0XA8D0, 0XA8D1, + 0XA8D2, 0XA8D3, 0XA8D4, 0XA8D5, 0XA8D6, 0XA8D7, 0XA8D8, + 0XA8D9, 0XA900, 0XA901, 0XA902, 0XA903, 0XA904, 0XA905, + 0XA906, 0XA907, 0XA908, 0XA909, 0XA9D0, 0XA9D1, 0XA9D2, + 0XA9D3, 0XA9D4, 0XA9D5, 0XA9D6, 0XA9D7, 0XA9D8, 0XA9D9, + 0XA9F0, 0XA9F1, 0XA9F2, 0XA9F3, 0XA9F4, 0XA9F5, 0XA9F6, + 0XA9F7, 0XA9F8, 0XA9F9, 0XAA50, 0XAA51, 0XAA52, 0XAA53, + 0XAA54, 0XAA55, 0XAA56, 0XAA57, 0XAA58, 0XAA59, 0XABF0, + 0XABF1, 0XABF2, 0XABF3, 0XABF4, 0XABF5, 0XABF6, 0XABF7, + 0XABF8, 0XABF9, 0XF96B, 0XF973, 0XF978, 0XF9B2, 0XF9D1, + 0XF9D3, 0XF9FD, 0XFF10, 0XFF11, 0XFF12, 0XFF13, 0XFF14, + 0XFF15, 0XFF16, 0XFF17, 0XFF18, 0XFF19, 0X10107, 0X10108, + 0X10109, 0X1010A, 0X1010B, 0X1010C, 0X1010D, 0X1010E, 0X1010F, + 0X10110, 0X10111, 0X10112, 0X10113, 0X10114, 0X10115, 0X10116, + 0X10117, 0X10118, 0X10119, 0X1011A, 0X1011B, 0X1011C, 0X1011D, + 0X1011E, 0X1011F, 0X10120, 0X10121, 0X10122, 0X10123, 0X10124, + 0X10125, 0X10126, 0X10127, 0X10128, 0X10129, 0X1012A, 0X1012B, + 0X1012C, 0X1012D, 0X1012E, 0X1012F, 0X10130, 0X10131, 0X10132, + 0X10133, 0X10140, 0X10141, 0X10142, 0X10143, 0X10144, 0X10145, + 0X10146, 0X10147, 0X10148, 0X10149, 0X1014A, 0X1014B, 0X1014C, + 0X1014D, 0X1014E, 0X1014F, 0X10150, 0X10151, 0X10152, 0X10153, + 0X10154, 0X10155, 0X10156, 0X10157, 0X10158, 0X10159, 0X1015A, + 0X1015B, 0X1015C, 0X1015D, 0X1015E, 0X1015F, 0X10160, 0X10161, + 0X10162, 0X10163, 0X10164, 0X10165, 0X10166, 0X10167, 0X10168, + 0X10169, 0X1016A, 0X1016B, 0X1016C, 0X1016D, 0X1016E, 0X1016F, + 0X10170, 0X10171, 0X10172, 0X10173, 0X10174, 0X10175, 0X10176, + 0X10177, 0X10178, 0X1018A, 0X1018B, 0X102E1, 0X102E2, 0X102E3, + 0X102E4, 0X102E5, 0X102E6, 0X102E7, 0X102E8, 0X102E9, 0X102EA, + 0X102EB, 0X102EC, 0X102ED, 0X102EE, 0X102EF, 0X102F0, 0X102F1, + 0X102F2, 0X102F3, 0X102F4, 0X102F5, 0X102F6, 0X102F7, 0X102F8, + 0X102F9, 0X102FA, 0X102FB, 0X10320, 0X10321, 0X10322, 0X10323, + 0X10341, 0X1034A, 0X103D1, 0X103D2, 0X103D3, 0X103D4, 0X103D5, + 0X104A0, 0X104A1, 0X104A2, 0X104A3, 0X104A4, 0X104A5, 0X104A6, + 0X104A7, 0X104A8, 0X104A9, 0X10858, 0X10859, 0X1085A, 0X1085B, + 0X1085C, 0X1085D, 0X1085E, 0X1085F, 0X10879, 0X1087A, 0X1087B, + 0X1087C, 0X1087D, 0X1087E, 0X1087F, 0X108A7, 0X108A8, 0X108A9, + 0X108AA, 0X108AB, 0X108AC, 0X108AD, 0X108AE, 0X108AF, 0X108FB, + 0X108FC, 0X108FD, 0X108FE, 0X108FF, 0X10916, 0X10917, 0X10918, + 0X10919, 0X1091A, 0X1091B, 0X109BC, 0X109BD, 0X109C0, 0X109C1, + 0X109C2, 0X109C3, 0X109C4, 0X109C5, 0X109C6, 0X109C7, 0X109C8, + 0X109C9, 0X109CA, 0X109CB, 0X109CC, 0X109CD, 0X109CE, 0X109CF, + 0X109D2, 0X109D3, 0X109D4, 0X109D5, 0X109D6, 0X109D7, 0X109D8, + 0X109D9, 0X109DA, 0X109DB, 0X109DC, 0X109DD, 0X109DE, 0X109DF, + 0X109E0, 0X109E1, 0X109E2, 0X109E3, 0X109E4, 0X109E5, 0X109E6, + 0X109E7, 0X109E8, 0X109E9, 0X109EA, 0X109EB, 0X109EC, 0X109ED, + 0X109EE, 0X109EF, 0X109F0, 0X109F1, 0X109F2, 0X109F3, 0X109F4, + 0X109F5, 0X109F6, 0X109F7, 0X109F8, 0X109F9, 0X109FA, 0X109FB, + 0X109FC, 0X109FD, 0X109FE, 0X109FF, 0X10A40, 0X10A41, 0X10A42, + 0X10A43, 0X10A44, 0X10A45, 0X10A46, 0X10A47, 0X10A7D, 0X10A7E, + 0X10A9D, 0X10A9E, 0X10A9F, 0X10AEB, 0X10AEC, 0X10AED, 0X10AEE, + 0X10AEF, 0X10B58, 0X10B59, 0X10B5A, 0X10B5B, 0X10B5C, 0X10B5D, + 0X10B5E, 0X10B5F, 0X10B78, 0X10B79, 0X10B7A, 0X10B7B, 0X10B7C, + 0X10B7D, 0X10B7E, 0X10B7F, 0X10BA9, 0X10BAA, 0X10BAB, 0X10BAC, + 0X10BAD, 0X10BAE, 0X10BAF, 0X10CFA, 0X10CFB, 0X10CFC, 0X10CFD, + 0X10CFE, 0X10CFF, 0X10E60, 0X10E61, 0X10E62, 0X10E63, 0X10E64, + 0X10E65, 0X10E66, 0X10E67, 0X10E68, 0X10E69, 0X10E6A, 0X10E6B, + 0X10E6C, 0X10E6D, 0X10E6E, 0X10E6F, 0X10E70, 0X10E71, 0X10E72, + 0X10E73, 0X10E74, 0X10E75, 0X10E76, 0X10E77, 0X10E78, 0X10E79, + 0X10E7A, 0X10E7B, 0X10E7C, 0X10E7D, 0X10E7E, 0X11052, 0X11053, + 0X11054, 0X11055, 0X11056, 0X11057, 0X11058, 0X11059, 0X1105A, + 0X1105B, 0X1105C, 0X1105D, 0X1105E, 0X1105F, 0X11060, 0X11061, + 0X11062, 0X11063, 0X11064, 0X11065, 0X11066, 0X11067, 0X11068, + 0X11069, 0X1106A, 0X1106B, 0X1106C, 0X1106D, 0X1106E, 0X1106F, + 0X110F0, 0X110F1, 0X110F2, 0X110F3, 0X110F4, 0X110F5, 0X110F6, + 0X110F7, 0X110F8, 0X110F9, 0X11136, 0X11137, 0X11138, 0X11139, + 0X1113A, 0X1113B, 0X1113C, 0X1113D, 0X1113E, 0X1113F, 0X111D0, + 0X111D1, 0X111D2, 0X111D3, 0X111D4, 0X111D5, 0X111D6, 0X111D7, + 0X111D8, 0X111D9, 0X111E1, 0X111E2, 0X111E3, 0X111E4, 0X111E5, + 0X111E6, 0X111E7, 0X111E8, 0X111E9, 0X111EA, 0X111EB, 0X111EC, + 0X111ED, 0X111EE, 0X111EF, 0X111F0, 0X111F1, 0X111F2, 0X111F3, + 0X111F4, 0X112F0, 0X112F1, 0X112F2, 0X112F3, 0X112F4, 0X112F5, + 0X112F6, 0X112F7, 0X112F8, 0X112F9, 0X114D0, 0X114D1, 0X114D2, + 0X114D3, 0X114D4, 0X114D5, 0X114D6, 0X114D7, 0X114D8, 0X114D9, + 0X11650, 0X11651, 0X11652, 0X11653, 0X11654, 0X11655, 0X11656, + 0X11657, 0X11658, 0X11659, 0X116C0, 0X116C1, 0X116C2, 0X116C3, + 0X116C4, 0X116C5, 0X116C6, 0X116C7, 0X116C8, 0X116C9, 0X11730, + 0X11731, 0X11732, 0X11733, 0X11734, 0X11735, 0X11736, 0X11737, + 0X11738, 0X11739, 0X1173A, 0X1173B, 0X118E0, 0X118E1, 0X118E2, + 0X118E3, 0X118E4, 0X118E5, 0X118E6, 0X118E7, 0X118E8, 0X118E9, + 0X118EA, 0X118EB, 0X118EC, 0X118ED, 0X118EE, 0X118EF, 0X118F0, + 0X118F1, 0X118F2, 0X12400, 0X12401, 0X12402, 0X12403, 0X12404, + 0X12405, 0X12406, 0X12407, 0X12408, 0X12409, 0X1240A, 0X1240B, + 0X1240C, 0X1240D, 0X1240E, 0X1240F, 0X12410, 0X12411, 0X12412, + 0X12413, 0X12414, 0X12415, 0X12416, 0X12417, 0X12418, 0X12419, + 0X1241A, 0X1241B, 0X1241C, 0X1241D, 0X1241E, 0X1241F, 0X12420, + 0X12421, 0X12422, 0X12423, 0X12424, 0X12425, 0X12426, 0X12427, + 0X12428, 0X12429, 0X1242A, 0X1242B, 0X1242C, 0X1242D, 0X1242E, + 0X1242F, 0X12430, 0X12431, 0X12432, 0X12433, 0X12434, 0X12435, + 0X12436, 0X12437, 0X12438, 0X12439, 0X1243A, 0X1243B, 0X1243C, + 0X1243D, 0X1243E, 0X1243F, 0X12440, 0X12441, 0X12442, 0X12443, + 0X12444, 0X12445, 0X12446, 0X12447, 0X12448, 0X12449, 0X1244A, + 0X1244B, 0X1244C, 0X1244D, 0X1244E, 0X1244F, 0X12450, 0X12451, + 0X12452, 0X12453, 0X12454, 0X12455, 0X12456, 0X12457, 0X12458, + 0X12459, 0X1245A, 0X1245B, 0X1245C, 0X1245D, 0X1245E, 0X1245F, + 0X12460, 0X12461, 0X12462, 0X12463, 0X12464, 0X12465, 0X12466, + 0X12467, 0X12468, 0X12469, 0X1246A, 0X1246B, 0X1246C, 0X1246D, + 0X1246E, 0X16A60, 0X16A61, 0X16A62, 0X16A63, 0X16A64, 0X16A65, + 0X16A66, 0X16A67, 0X16A68, 0X16A69, 0X16B50, 0X16B51, 0X16B52, + 0X16B53, 0X16B54, 0X16B55, 0X16B56, 0X16B57, 0X16B58, 0X16B59, + 0X16B5B, 0X16B5C, 0X16B5D, 0X16B5E, 0X16B5F, 0X16B60, 0X16B61, + 0X1D360, 0X1D361, 0X1D362, 0X1D363, 0X1D364, 0X1D365, 0X1D366, + 0X1D367, 0X1D368, 0X1D369, 0X1D36A, 0X1D36B, 0X1D36C, 0X1D36D, + 0X1D36E, 0X1D36F, 0X1D370, 0X1D371, 0X1D7CE, 0X1D7CF, 0X1D7D0, + 0X1D7D1, 0X1D7D2, 0X1D7D3, 0X1D7D4, 0X1D7D5, 0X1D7D6, 0X1D7D7, + 0X1D7D8, 0X1D7D9, 0X1D7DA, 0X1D7DB, 0X1D7DC, 0X1D7DD, 0X1D7DE, + 0X1D7DF, 0X1D7E0, 0X1D7E1, 0X1D7E2, 0X1D7E3, 0X1D7E4, 0X1D7E5, + 0X1D7E6, 0X1D7E7, 0X1D7E8, 0X1D7E9, 0X1D7EA, 0X1D7EB, 0X1D7EC, + 0X1D7ED, 0X1D7EE, 0X1D7EF, 0X1D7F0, 0X1D7F1, 0X1D7F2, 0X1D7F3, + 0X1D7F4, 0X1D7F5, 0X1D7F6, 0X1D7F7, 0X1D7F8, 0X1D7F9, 0X1D7FA, + 0X1D7FB, 0X1D7FC, 0X1D7FD, 0X1D7FE, 0X1D7FF, 0X1E8C7, 0X1E8C8, + 0X1E8C9, 0X1E8CA, 0X1E8CB, 0X1E8CC, 0X1E8CD, 0X1E8CE, 0X1E8CF, + 0X1F100, 0X1F101, 0X1F102, 0X1F103, 0X1F104, 0X1F105, 0X1F106, + 0X1F107, 0X1F108, 0X1F109, 0X1F10A, 0X1F10B, 0X1F10C, 0X20001, + 0X20064, 0X200E2, 0X20121, 0X2092A, 0X20983, 0X2098C, 0X2099C, + 0X20AEA, 0X20AFD, 0X20B19, 0X22390, 0X22998, 0X23B1B, 0X2626D, + 0X2F890 ] # Convert each hex into the literal Unicode character. @@ -170,7 +243,7 @@ numeric_chars = [] for a in numeric_hex: try: l = py23_unichr(a) - except ValueError: + except ValueError: # pragma: no cover break if unicodedata.numeric(l, None) is None: continue diff --git a/natsort/utils.py b/natsort/utils.py index 97dfbc1..214ca01 100644 --- a/natsort/utils.py +++ b/natsort/utils.py @@ -323,7 +323,7 @@ def _natsort_key(val, key, alg): try: lowfirst = alg & _ns['LOWERCASEFIRST'] dumb = dumb_sort() if use_locale else False - if use_locale and dumb and not lowfirst: + if use_locale and dumb and not lowfirst: # pragma: no cover val = val.swapcase() # Compensate for bad locale lib. elif lowfirst and not (use_locale and dumb): val = val.swapcase() @@ -347,7 +347,7 @@ def _natsort_key(val, key, alg): return (ret, ret) elif ret[0] == null_string: return ((b'' if use_pyicu else '',), ret) - elif dumb: + elif dumb: # pragma: no cover if lowfirst: return ((orig_val[0].swapcase(),), ret) else: @@ -6,7 +6,7 @@ import sys from os.path import join # Non-std lib imports -from setuptools import setup +from setuptools import setup, find_packages from setuptools.command.test import test as TestCommand @@ -62,7 +62,7 @@ REQUIRES = 'argparse' if sys.version[:3] in ('2.6', '3.0', '3.1') else '' # Testing needs pytest, and mock if less than python 3.3 TESTS_REQUIRE = ['pytest', 'pytest-pep8', 'pytest-flakes', - 'pytest-cov', 'pytest-cache', 'hypothesis'] + 'pytest-cov', 'pytest-cache', 'hypothesis>=1.6.2'] if (sys.version.startswith('2') or (sys.version.startswith('3') and int(sys.version.split('.')[1]) < 3)): @@ -80,7 +80,7 @@ setup( url='https://github.com/SethMMorton/natsort', license='MIT', install_requires=REQUIRES, - packages=['natsort', 'natsort.compat'], + packages=find_packages(exclude=['test*']), entry_points={'console_scripts': ['natsort = natsort.__main__:main']}, tests_require=TESTS_REQUIRE, cmdclass={'test': PyTest}, diff --git a/test_natsort/compat/hypothesis.py b/test_natsort/compat/hypothesis.py index ade7277..b633ef2 100644 --- a/test_natsort/compat/hypothesis.py +++ b/test_natsort/compat/hypothesis.py @@ -14,14 +14,17 @@ major_minor = sys.version_info[:2] if major_minor != (2, 6): use_hypothesis = True from hypothesis import assume, given, example - from hypothesis.specifiers import ( - integers_in_range, - integers_from, + from hypothesis.strategies import ( sampled_from, + integers, + floats, + tuples, + lists, + text, ) # Otherwise mock these imports, because hypothesis # is incompatible with python 2.6. else: - example = integers_in_range = integers_from = \ - sampled_from = assume = given = compat.mock.MagicMock() + example = sampled_from = assume = given = floats = integers = \ + tuples = lists = text = compat.mock.MagicMock() use_hypothesis = False diff --git a/test_natsort/slow_splitters.py b/test_natsort/slow_splitters.py index 61e8025..8fec3de 100644 --- a/test_natsort/slow_splitters.py +++ b/test_natsort/slow_splitters.py @@ -136,7 +136,8 @@ def float_splitter(x, signed, exp, safe, sep): # Fix a float that looks like a string. fstrings = ('inf', 'infinity', '-inf', '-infinity', '+inf', '+infinity', 'nan') - full_list = [float(y) if type(y) != float and y.lower() in fstrings else y + full_list = [float(y.strip()) + if type(y) != float and y.lower().strip() in fstrings else y for y in full_list] if safe: full_list = sep_inserter(full_list, (float,), sep) diff --git a/test_natsort/test_fake_fastnumbers.py b/test_natsort/test_fake_fastnumbers.py index 594d060..6751879 100644 --- a/test_natsort/test_fake_fastnumbers.py +++ b/test_natsort/test_fake_fastnumbers.py @@ -7,7 +7,6 @@ from __future__ import unicode_literals import pytest import unicodedata from math import isnan -from natsort.compat.py23 import py23_str from natsort.compat.fake_fastnumbers import ( fast_float, fast_int, @@ -17,6 +16,9 @@ from natsort.compat.fake_fastnumbers import ( from compat.hypothesis import ( assume, given, + floats, + integers, + text, use_hypothesis, ) @@ -52,6 +54,17 @@ def is_int(x): # and a test that uses the hypothesis module. +def test_fast_float_leaves_float_asis_example(): + assert fast_float(45.8) == 45.8 + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(floats()) +def test_fast_float_leaves_float_asis(x): + assume(not isnan(x)) # But inf is included + assert fast_float(x) == x + + def test_fast_float_converts_float_string_to_float_example(): assert fast_float('45.8') == 45.8 assert fast_float('-45') == -45.0 @@ -60,7 +73,7 @@ def test_fast_float_converts_float_string_to_float_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(float) +@given(floats()) def test_fast_float_converts_float_string_to_float(x): assume(not isnan(x)) # But inf is included assert fast_float(repr(x)) == x @@ -71,12 +84,22 @@ def test_fast_float_leaves_string_as_is_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(py23_str) +@given(text()) def test_fast_float_leaves_string_as_is(x): assume(not is_float(x)) assert fast_float(x) == x +def test_fast_int_leaves_int_asis_example(): + assert fast_int(45) == 45 + + +@pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') +@given(integers()) +def test_fast_int_leaves_int_asis(x): + assert fast_int(x) == x + + def test_fast_int_leaves_float_string_as_is_example(): assert fast_int('45.8') == '45.8' assert fast_int('nan') == 'nan' @@ -84,7 +107,7 @@ def test_fast_int_leaves_float_string_as_is_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(float) +@given(floats()) def test_fast_int_leaves_float_string_as_is(x): assume(not x.is_integer()) assert fast_int(repr(x)) == repr(x) @@ -95,7 +118,7 @@ def test_fast_int_converts_int_string_to_int_example(): assert fast_int('+45') == 45 -@given(int) +@given(integers()) def test_fast_int_converts_int_string_to_int(x): assert fast_int(repr(x)) == x @@ -105,7 +128,7 @@ def test_fast_int_leaves_string_as_is_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(py23_str) +@given(text()) def test_fast_int_leaves_string_as_is(x): assume(not is_int(x)) assert fast_int(x) == x @@ -116,7 +139,7 @@ def test_isfloat_returns_True_for_real_numbers_example(): assert isfloat(45.8e-2) -@given(float) +@given(floats()) def test_isfloat_returns_True_for_real_numbers(x): assert isfloat(x) @@ -126,7 +149,7 @@ def test_isfloat_returns_False_for_strings_example(): assert not isfloat('invalid') -@given(py23_str) +@given(text()) def test_isfloat_returns_False_for_strings(x): assert not isfloat(x) @@ -136,7 +159,7 @@ def test_isint_returns_True_for_real_numbers_example(): assert isint(45) -@given(int) +@given(integers()) def test_isint_returns_True_for_real_numbers(x): assert isint(x) @@ -146,6 +169,6 @@ def test_isint_returns_False_for_strings_example(): assert not isint('invalid') -@given(py23_str) +@given(text()) def test_isint_returns_False_for_strings(x): assert not isint(x) diff --git a/test_natsort/test_locale_help.py b/test_natsort/test_locale_help.py index 63ff96b..05e3ba4 100644 --- a/test_natsort/test_locale_help.py +++ b/test_natsort/test_locale_help.py @@ -21,6 +21,8 @@ from compat.locale import ( from compat.hypothesis import ( assume, given, + text, + floats, use_hypothesis, ) @@ -35,7 +37,7 @@ def test_grouper_returns_letters_with_lowercase_transform_of_letter_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(py23_str) +@given(text()) def test_grouper_returns_letters_with_lowercase_transform_of_letter(x): assume(type(fast_float(x)) is not float) assert grouper(x, (fast_float, isfloat)) == ''.join(chain.from_iterable([low(y), y] for y in x)) @@ -46,7 +48,7 @@ def test_grouper_returns_float_string_as_float_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(float) +@given(floats()) def test_grouper_returns_float_string_as_float(x): assume(not isnan(x)) assert grouper(repr(x), (fast_float, isfloat)) == x @@ -59,7 +61,7 @@ def test_locale_convert_transforms_float_string_to_float_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(float) +@given(floats()) def test_locale_convert_transforms_float_string_to_float(x): assume(not isnan(x)) load_locale('en_US') @@ -76,7 +78,7 @@ def test_locale_convert_transforms_nonfloat_string_to_strxfrm_string_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(py23_str) +@given(text()) def test_locale_convert_transforms_nonfloat_string_to_strxfrm_string(x): assume(type(fast_float(x)) is not float) load_locale('en_US') @@ -94,7 +96,7 @@ def test_locale_convert_with_groupletters_transforms_nonfloat_string_to_strxfrm_ @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(py23_str) +@given(text()) def test_locale_convert_with_groupletters_transforms_nonfloat_string_to_strxfrm_string_with_grouped_letters(x): assume(type(fast_float(x)) is not float) load_locale('en_US') @@ -113,7 +115,7 @@ def test_locale_convert_transforms_float_string_to_float_with_de_locale_example( @pytest.mark.skipif(not has_locale_de_DE, reason='requires de_DE locale') @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(float) +@given(floats()) def test_locale_convert_transforms_float_string_to_float_with_de_locale(x): assume(not isnan(x)) load_locale('de_DE') diff --git a/test_natsort/test_main.py b/test_natsort/test_main.py index 4751c4a..558d59b 100644 --- a/test_natsort/test_main.py +++ b/test_natsort/test_main.py @@ -11,9 +11,11 @@ from compat.mock import patch, call from compat.hypothesis import ( assume, given, - integers_from, - integers_in_range, sampled_from, + integers, + floats, + tuples, + text, use_hypothesis, ) from natsort.__main__ import ( @@ -172,14 +174,14 @@ def test_range_check_returns_range_as_is_but_with_floats_if_first_is_less_than_s @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(x=int, y=int) +@given(x=integers(), y=integers()) def test_range_check_returns_range_as_is_but_with_floats_if_first_is_less_than_second(x, y): assume(x < y) assert range_check(x, y) == (float(x), float(y)) @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(x=float, y=float) +@given(x=floats(), y=floats()) def test_range_check_returns_range_as_is_but_with_floats_if_first_is_less_than_second2(x, y): assume(x < y) assert range_check(x, y) == (x, y) @@ -192,7 +194,7 @@ def test_range_check_raises_ValueError_if_second_is_less_than_first_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(x=float, y=float) +@given(x=floats(), y=floats()) def test_range_check_raises_ValueError_if_second_is_less_than_first(x, y): assume(x >= y) with raises(ValueError) as err: @@ -212,7 +214,7 @@ def test_check_filter_converts_filter_numbers_to_floats_if_filter_is_valid_examp @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(x=(int, int, float, float), y=(int, float, float, int)) +@given(x=tuples(integers(), integers(), floats(), floats()), y=tuples(integers(), floats(), floats(), integers())) def test_check_filter_converts_filter_numbers_to_floats_if_filter_is_valid(x, y): assume(all(i < j for i, j in zip(x, y))) assert check_filter(list(zip(x, y))) == [(float(i), float(j)) for i, j in zip(x, y)] @@ -225,7 +227,7 @@ def test_check_filter_raises_ValueError_if_filter_is_invalid_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(x=(int, int, float, float), y=(int, float, float, int)) +@given(x=tuples(integers(), integers(), floats(), floats()), y=tuples(integers(), floats(), floats(), integers())) def test_check_filter_raises_ValueError_if_filter_is_invalid(x, y): assume(any(i >= j for i, j in zip(x, y))) with raises(ValueError) as err: @@ -238,7 +240,7 @@ def test_keep_entry_range_returns_True_if_any_portion_of_input_is_between_the_ra @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given((py23_str, integers_in_range(1, 99), py23_str, integers_in_range(1, 99), py23_str)) +@given(tuples(text(), integers(1, 99), text(), integers(1, 99), text())) def test_keep_entry_range_returns_True_if_any_portion_of_input_is_between_the_range_bounds(x): s = ''.join(map(py23_str, x)) assume(any(0 < int(i) < 100 for i in re.findall(r'\d+', s) if re.match(r'\d+$', i))) @@ -250,7 +252,7 @@ def test_keep_entry_range_returns_True_if_any_portion_of_input_is_between_any_ra @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given((py23_str, integers_in_range(2, 89), py23_str, integers_in_range(2, 89), py23_str)) +@given(tuples(text(), integers(2, 89), text(), integers(2, 89), text())) def test_keep_entry_range_returns_True_if_any_portion_of_input_is_between_any_range_bounds(x): s = ''.join(map(py23_str, x)) assume(any((1 < int(i) < 20) or (88 < int(i) < 90) for i in re.findall(r'\d+', s) if re.match(r'\d+$', i))) @@ -262,7 +264,7 @@ def test_keep_entry_range_returns_False_if_no_portion_of_input_is_between_the_ra @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given((py23_str, integers_from(21), py23_str, integers_from(21), py23_str)) +@given(tuples(text(), integers(min_value=21), text(), integers(min_value=21), text())) def test_keep_entry_range_returns_False_if_no_portion_of_input_is_between_the_range_bounds(x): s = ''.join(map(py23_str, x)) assume(all(not (1 <= int(i) <= 20) for i in re.findall(r'\d+', s) if re.match(r'\d+$', i))) @@ -274,7 +276,7 @@ def test_exclude_entry_returns_True_if_exlcude_parameters_are_not_in_input_examp @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given((py23_str, integers_from(0), py23_str, integers_from(0), py23_str)) +@given(tuples(text(), integers(min_value=0), text(), integers(min_value=0), text())) def test_exclude_entry_returns_True_if_exlcude_parameters_are_not_in_input(x): s = ''.join(map(py23_str, x)) assume(not any(int(i) in (23, 45, 87) for i in re.findall(r'\d+', s) if re.match(r'\d+$', i))) @@ -286,7 +288,7 @@ def test_exclude_entry_returns_False_if_exlcude_parameters_are_in_input_example( @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given((py23_str, sampled_from([23, 45, 87]), py23_str, sampled_from([23, 45, 87]), py23_str)) +@given(tuples(text(), sampled_from([23, 45, 87]), text(), sampled_from([23, 45, 87]), text())) def test_exclude_entry_returns_False_if_exlcude_parameters_are_in_input(x): s = ''.join(map(py23_str, x)) assume(any(int(i) in (23, 45, 87) for i in re.findall(r'\d+', s) if re.match(r'\d+$', i))) diff --git a/test_natsort/test_unicode_numbers.py b/test_natsort/test_unicode_numbers.py index 25d4679..56570b1 100644 --- a/test_natsort/test_unicode_numbers.py +++ b/test_natsort/test_unicode_numbers.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import unicodedata from natsort.compat.py23 import py23_range, py23_unichr from natsort.unicode_numbers import ( + numeric_hex, numeric_chars, numeric, digit_chars, @@ -24,7 +25,9 @@ def test_digit_chars_contains_only_valid_unicode_digit_characters(): def test_numeric_chars_contains_all_valid_unicode_numeric_characters(): - for i in py23_range(0X10FFFF): + 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: @@ -32,11 +35,14 @@ def test_numeric_chars_contains_all_valid_unicode_numeric_characters(): if a in set('0123456789'): continue if unicodedata.numeric(a, None) is not None: - assert a in numeric_chars + assert i in set_numeric_hex + assert a in set_numeric_chars def test_digit_chars_contains_all_valid_unicode_digit_characters(): - for i in py23_range(0X10FFFF): + 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: @@ -44,7 +50,8 @@ def test_digit_chars_contains_all_valid_unicode_digit_characters(): if a in set('0123456789'): continue if unicodedata.digit(a, None) is not None: - assert a in digit_chars + assert i in set_numeric_hex + assert a in set_numeric_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 01de5d3..f64d212 100644 --- a/test_natsort/test_utils.py +++ b/test_natsort/test_utils.py @@ -54,6 +54,10 @@ from compat.hypothesis import ( given, example, sampled_from, + lists, + text, + floats, + integers, use_hypothesis, ) @@ -177,7 +181,7 @@ def test_py3_safe_with_use_locale_inserts_null_string_between_two_numbers_exampl @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([py23_str, int]) +@given(lists(elements=text() | integers())) def test_py3_safe_inserts_empty_string_between_two_numbers(x): assume(bool(x)) assert _py3_safe(x, False, isint) == sep_inserter(x, (int, long), '') @@ -189,9 +193,8 @@ def test_path_splitter_splits_path_string_by_separator_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([sampled_from(string.ascii_letters)]) +@given(lists(sampled_from(string.ascii_letters), min_size=2)) def test_path_splitter_splits_path_string_by_separator(x): - assume(len(x) > 1) assume(all(x)) z = py23_str(pathlib.Path(*x)) assert _path_splitter(z) == list(pathlib.Path(z).parts) @@ -204,9 +207,8 @@ def test_path_splitter_splits_path_string_by_separator_and_removes_extension_exa @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([sampled_from(string.ascii_letters)]) +@given(lists(sampled_from(string.ascii_letters), min_size=3)) def test_path_splitter_splits_path_string_by_separator_and_removes_extension(x): - assume(len(x) > 2) assume(all(x)) z = py23_str(pathlib.Path(*x[:-2])) + '.' + x[-1] y = list(pathlib.Path(z).parts) @@ -219,7 +221,7 @@ def test_number_extracter_raises_TypeError_if_given_a_number_example(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(float) +@given(floats()) def test_number_extracter_raises_TypeError_if_given_a_number(x): with raises(TypeError): assert _number_extracter(x, _float_sign_exp_re, *float_nosafe_nolocale_nogroup) @@ -230,9 +232,8 @@ def test_number_extracter_includes_plus_sign_and_exponent_in_float_definition_fo @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_includes_plus_sign_and_exponent_in_float_definition_for_signed_exp_floats(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 _number_extracter(s, _float_sign_exp_re, *float_nosafe_nolocale_nogroup) == float_splitter(s, True, True, False, '') @@ -243,9 +244,8 @@ def test_number_extracter_excludes_plus_sign_in_float_definition_but_includes_ex @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_excludes_plus_sign_in_float_definition_but_includes_exponent_for_unsigned_exp_floats(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 _number_extracter(s, _float_nosign_exp_re, *float_nosafe_nolocale_nogroup) == float_splitter(s, False, True, False, '') @@ -256,9 +256,8 @@ def test_number_extracter_includes_plus_and_minus_sign_in_float_definition_but_e @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_includes_plus_and_minus_sign_in_float_definition_but_excludes_exponent_for_signed_noexp_floats(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 _number_extracter(s, _float_sign_noexp_re, *float_nosafe_nolocale_nogroup) == float_splitter(s, True, False, False, '') @@ -269,9 +268,8 @@ def test_number_extracter_excludes_plus_sign_and_exponent_in_float_definition_fo @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_excludes_plus_sign_and_exponent_in_float_definition_for_unsigned_noexp_floats(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 _number_extracter(s, _float_nosign_noexp_re, *float_nosafe_nolocale_nogroup) == float_splitter(s, False, False, False, '') @@ -282,12 +280,11 @@ def test_number_extracter_excludes_plus_and_minus_sign_in_int_definition_for_uns @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) @example([10000000000000000000000000000000000000000000000000000000000000000000000000, 100000000000000000000000000000000000000000000000000000000000000000000000000, 100000000000000000000000000000000000000000000000000000000000000000000000000]) def test_number_extracter_excludes_plus_and_minus_sign_in_int_definition_for_unsigned_ints(x): - assume(len(x) <= 10) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) assert _number_extracter(s, _int_nosign_re, *int_nosafe_nolocale_nogroup) == int_splitter(s, False, False, '') @@ -297,9 +294,8 @@ def test_number_extracter_includes_plus_and_minus_sign_in_int_definition_for_sig @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_includes_plus_and_minus_sign_in_int_definition_for_signed_ints(x): - assume(len(x) <= 10) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) assert _number_extracter(s, _int_sign_re, *int_nosafe_nolocale_nogroup) == int_splitter(s, True, False, '') @@ -309,9 +305,8 @@ def test_number_extracter_inserts_empty_string_between_floats_for_py3safe_option @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_inserts_empty_string_between_floats_for_py3safe_option(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 _number_extracter(s, _float_sign_exp_re, *float_safe_nolocale_nogroup) == float_splitter(s, True, True, True, '') @@ -322,9 +317,8 @@ def test_number_extracter_inserts_empty_string_between_ints_for_py3safe_option_e @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_inserts_empty_string_between_ints_for_py3safe_option(x): - assume(len(x) <= 10) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) assert _number_extracter(s, _int_sign_re, *int_safe_nolocale_nogroup) == int_splitter(s, True, True, '') @@ -346,9 +340,8 @@ def test_number_extracter_doubles_letters_with_lowercase_version_with_grouplette @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_doubles_letters_with_lowercase_version_with_groupletters_for_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) t = float_splitter(s, True, True, False, '') @@ -361,9 +354,8 @@ def test_number_extracter_doubles_letters_with_lowercase_version_with_grouplette @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_doubles_letters_with_lowercase_version_with_groupletters_for_int(x): - assume(len(x) <= 10) s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) t = int_splitter(s, False, False, '') t = [''.join([low(z) + z for z in y]) if type(y) not in (int, long) else y for y in t] @@ -378,9 +370,8 @@ def test_number_extracter_extracts_numbers_and_strxfrms_strings_with_use_locale_ @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_extracts_numbers_and_strxfrms_strings_with_use_locale(x): - assume(len(x) <= 10) load_locale('en_US') s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) t = int_splitter(s, False, False, null_string) @@ -400,9 +391,8 @@ def test_number_extracter_extracts_numbers_and_strxfrms_letter_doubled_strings_w @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test_number_extracter_extracts_numbers_and_strxfrms_letter_doubled_strings_with_use_locale_and_groupletters(x): - assume(len(x) <= 10) load_locale('en_US') s = ''.join(repr(y) if type(y) in (float, long, int) else y for y in x) t = int_splitter(s, False, False, null_string) @@ -430,9 +420,8 @@ def test__natsort_key_with_nan_input_and_NANLAST_transforms_nan_to_positive_inf( @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) 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 @@ -441,9 +430,8 @@ def test__natsort_key_with_float_and_signed_splits_input_into_string_and_signed_ @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_real_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.R == ns.F | ns.S @@ -451,18 +439,16 @@ def test__natsort_key_with_real_splits_input_into_string_and_signed_float_with_e @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) 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) @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_float_and_signed_and_noexp_splits_input_into_string_and_signed_float_without_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.N == ns.NOEXP @@ -470,9 +456,8 @@ def test__natsort_key_with_float_and_signed_and_noexp_splits_input_into_string_a @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_float_and_unsigned_splits_input_into_string_and_unsigned_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 ns.U == ns.UNSIGNED @@ -482,18 +467,16 @@ def test__natsort_key_with_float_and_unsigned_splits_input_into_string_and_unsig @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_float_and_noexp_splits_input_into_string_and_unsigned_float_without_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 _natsort_key(s, None, ns.F | ns.N) == tuple(_number_extracter(s, _float_nosign_noexp_re, *float_nosafe_nolocale_nogroup)) @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_int_splits_input_into_string_and_unsigned_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 ns.I == ns.INT @@ -505,9 +488,8 @@ def test__natsort_key_with_int_splits_input_into_string_and_unsigned_int(x): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_int_splits_and_signed_input_into_string_and_signed_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.INT | ns.SIGNED) == tuple(_number_extracter(s, _int_sign_re, *int_nosafe_nolocale_nogroup)) @@ -515,9 +497,8 @@ def test__natsort_key_with_int_splits_and_signed_input_into_string_and_signed_in @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) 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) @@ -525,19 +506,17 @@ def test__natsort_key_with_version_or_digit_matches_usigned_int(x): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) 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)) @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) 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)) @@ -545,10 +524,9 @@ def test__natsort_key_with_tuple_input_returns_nested_tuples(x): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=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(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)) @@ -556,7 +534,7 @@ def test__natsort_key_with_tuple_input_but_itemgetter_key_returns_split_second_e @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given(float) +@given(floats()) def test__natsort_key_with_numeric_input_returns_number_with_leading_empty_string(x): assume(not isnan(x)) if x.is_integer(): @@ -565,10 +543,9 @@ def test__natsort_key_with_numeric_input_returns_number_with_leading_empty_strin @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) 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)) @@ -582,9 +559,8 @@ def test__natsort_key_with_invalid_alg_input_raises_ValueError(): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_IGNORECASE_lowercases_text(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) try: @@ -594,18 +570,16 @@ def test__natsort_key_with_IGNORECASE_lowercases_text(x): @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) 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)) @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_GROUPLETTERS_doubles_text_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) @@ -614,9 +588,8 @@ def test__natsort_key_with_GROUPLETTERS_doubles_text_with_lowercase_letter_first @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) 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) @@ -635,10 +608,9 @@ def test__natsort_key_with_bytes_input_only_applies_LOWERCASEFIRST_or_IGNORECASE @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_LOCALE_transforms_floats_according_to_the_current_locale_and_strxfrms_strings(x): # Locale aware sorting - 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) load_locale('en_US') @@ -650,10 +622,9 @@ def test__natsort_key_with_LOCALE_transforms_floats_according_to_the_current_loc @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) def test__natsort_key_with_LOCALE_and_UNGROUPLETTERS_places_space_before_string_with_capital_first_letter(x): # Locale aware sorting - 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) load_locale('en_US') @@ -663,7 +634,7 @@ def test__natsort_key_with_LOCALE_and_UNGROUPLETTERS_places_space_before_string_ t = tuple(_number_extracter(s, _float_nosign_exp_re, *float_nosafe_locale_nogroup)) if not t: r = (t, t) - elif t[0] is null_string: + 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) @@ -676,9 +647,8 @@ def test__natsort_key_with_LOCALE_and_UNGROUPLETTERS_places_space_before_string_ @pytest.mark.skipif(not use_hypothesis, reason='requires python2.7 or greater') -@given([float, py23_str, int]) +@given(lists(elements=floats() | text() | integers(), min_size=1, max_size=10)) 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) @@ -5,7 +5,7 @@ [tox] envlist = - py26, py27, py32, py33, py34, pypy + py26, py27, py32, py33, py34, py35, pypy [testenv] commands = {envpython} setup.py test |