From 009973f7f4b650aa20109e67edae673faf4f25f4 Mon Sep 17 00:00:00 2001 From: nfnty Date: Tue, 24 Jan 2017 06:27:07 +0100 Subject: container.fsobject: Fix natural sort Fixes #749 --- .gitignore | 1 + ranger/container/fsobject.py | 32 +++++++++++++++++++------------- tests/ranger/container/test_fsobject.py | 27 +++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index e97a99b7..dbbb1ce0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *~ *.pyc *.pyo +/.cache stuff/* doc/ranger.1.html build diff --git a/ranger/container/fsobject.py b/ranger/container/fsobject.py index 0447d5a6..59807dfb 100644 --- a/ranger/container/fsobject.py +++ b/ranger/container/fsobject.py @@ -36,17 +36,13 @@ DOCUMENT_BASENAMES = ('bugs', 'bugs', 'changelog', 'copying', 'credits', BAD_INFO = '?' - -# pylint: disable=invalid-name -_unsafe_chars = '\n' + ''.join(map(chr, range(32))) + ''.join(map(chr, range(128, 256))) -_safe_string_table = maketrans(_unsafe_chars, '?' * len(_unsafe_chars)) -_extract_number_re = re.compile(r'(\d+|\D)') -_integers = set("0123456789") -# pylint: enable=invalid-name +_UNSAFE_CHARS = '\n' + ''.join(map(chr, range(32))) + ''.join(map(chr, range(128, 256))) +_SAFE_STRING_TABLE = maketrans(_UNSAFE_CHARS, '?' * len(_UNSAFE_CHARS)) +_EXTRACT_NUMBER_RE = re.compile(r'(\d+|\D)') def safe_path(path): - return path.translate(_safe_string_table) + return path.translate(_SAFE_STRING_TABLE) class FileSystemObject( # pylint: disable=too-many-instance-attributes @@ -149,17 +145,27 @@ class FileSystemObject( # pylint: disable=too-many-instance-attributes @lazy_property def basename_natural(self): - return [('0', int(s)) if s in _integers else (s, 0) - for s in _extract_number_re.split(self.relative_path)] + basename_list = [] + for string in _EXTRACT_NUMBER_RE.split(self.relative_path): + try: + basename_list += [('0', int(string))] + except ValueError: + basename_list += [(string, 0)] + return basename_list @lazy_property def basename_natural_lower(self): - return [('0', int(s)) if s in _integers else (s, 0) - for s in _extract_number_re.split(self.relative_path_lower)] + basename_list = [] + for string in _EXTRACT_NUMBER_RE.split(self.relative_path_lower): + try: + basename_list += [('0', int(string))] + except ValueError: + basename_list += [(string, 0)] + return basename_list @lazy_property def safe_basename(self): - return self.basename.translate(_safe_string_table) + return self.basename.translate(_SAFE_STRING_TABLE) @lazy_property def user(self): diff --git a/tests/ranger/container/test_fsobject.py b/tests/ranger/container/test_fsobject.py index 2c6a693f..d2c9a770 100644 --- a/tests/ranger/container/test_fsobject.py +++ b/tests/ranger/container/test_fsobject.py @@ -21,15 +21,34 @@ def create_filesystem_object(path): def test_basename_natural1(): """Test filenames without extensions.""" - fsos = [create_filesystem_object(path) - for path in ("hello", "hello1", "hello2")] + fsos = [ + create_filesystem_object(path) + for path in ( + "0", "1", "2", "3", + "10", "11", "12", "13", + "100", "101", "102", "103", + "110", "111", "112", "113", + "hello", + "hello1", "hello2", + "hello11", "hello12", + "hello100", "hello101", "hello111", "hello112", + ) + ] assert fsos == sorted(fsos[::-1], key=operator.attrgetter("basename_natural")) assert fsos == sorted(fsos[::-1], key=operator.attrgetter("basename_natural_lower")) def test_basename_natural2(): """Test filenames with extensions.""" - fsos = [create_filesystem_object(path) - for path in ("hello", "hello.txt", "hello1.txt", "hello2.txt")] + fsos = [ + create_filesystem_object(path) + for path in ( + "hello", "hello.txt", + "hello0.txt", "hello1.txt", "hello2.txt", "hello3.txt" + "hello10.txt", "hello11.txt", "hello12.txt", "hello13.txt" + "hello100.txt", "hello101.txt", "hello102.txt", "hello103.txt" + "hello110.txt", "hello111.txt", "hello112.txt", "hello113.txt" + ) + ] assert fsos == sorted(fsos[::-1], key=operator.attrgetter("basename_natural")) assert fsos == sorted(fsos[::-1], key=operator.attrgetter("basename_natural_lower")) -- cgit 1.4.1-2-gfad0