diff --git a/core/exclude.py b/core/exclude.py index eb8ffc08..557ac823 100644 --- a/core/exclude.py +++ b/core/exclude.py @@ -12,6 +12,7 @@ from os import sep import logging import functools from hscommon.util import FileOrPath +from hscommon.plat import ISWINDOWS import time default_regexes = [r"^thumbs\.db$", # Obsolete after WindowsXP @@ -19,10 +20,10 @@ default_regexes = [r"^thumbs\.db$", # Obsolete after WindowsXP r"^\.DS_Store$", # MacOS metadata r"^\.Trash\-.*", # Linux trash directories r"^\$Recycle\.Bin$", # Windows - r"^\..*", # Hidden files + r"^\..*", # Hidden files on Unix-like ] # These are too broad -forbidden_regexes = [r".*", r"\/.*", r".*\/.*", r".*\..*"] +forbidden_regexes = [r".*", r"\/.*", r".*\/.*", r".*\\\\.*", r".*\..*"] def timer(func): @@ -168,10 +169,16 @@ class ExcludeList(Markable): def build_compiled_caches(self, union=False): if not union: - self._cached_compiled_files =\ - [x for x in self._excluded_compiled if sep not in x.pattern] - self._cached_compiled_paths =\ - [x for x in self._excluded_compiled if sep in x.pattern] + if not ISWINDOWS: + self._cached_compiled_files =\ + [x for x in self._excluded_compiled if not has_sep(x.pattern)] + self._cached_compiled_paths =\ + [x for x in self._excluded_compiled if has_sep(x.pattern)] + else: + self._cached_compiled_files =\ + [x for x in self._excluded_compiled if not has_sep(x.pattern)] + self._cached_compiled_paths =\ + [x for x in self._excluded_compiled if has_sep(x.pattern)] return marked_count = [x for marked, x in self if marked] # If there is no item, the compiled Pattern will be '' and match everything! @@ -184,13 +191,13 @@ class ExcludeList(Markable): # the same regardless of whether the client asked for union or not self._cached_compiled_union_all =\ (re.compile('|'.join(marked_count)),) - files_marked = [x for x in marked_count if sep not in x] + files_marked = [x for x in marked_count if not has_sep(x)] if not files_marked: self._cached_compiled_union_files = tuple() else: self._cached_compiled_union_files =\ (re.compile('|'.join(files_marked)),) - paths_marked = [x for x in marked_count if sep in x] + paths_marked = [x for x in marked_count if has_sep(x)] if not paths_marked: self._cached_compiled_union_paths = tuple() else: @@ -488,3 +495,11 @@ def ordered_keys(_dict): list_of_items.sort(key=lambda x: x[1].get("index")) for item in list_of_items: yield item[0] + + +if ISWINDOWS: + def has_sep(x): + return '\\' + sep in x +else: + def has_sep(x): + return sep in x diff --git a/core/tests/directories_test.py b/core/tests/directories_test.py index 061e1476..8a5ddcdb 100644 --- a/core/tests/directories_test.py +++ b/core/tests/directories_test.py @@ -12,6 +12,7 @@ import shutil from pytest import raises from hscommon.path import Path from hscommon.testutil import eq_ +from hscommon.plat import ISWINDOWS from ..fs import File from ..directories import ( @@ -428,7 +429,10 @@ files: {self.d._exclude_list.compiled_files} all: {self.d._exclude_list.compiled assert "unwanted_subdirfile.gif" not in files assert "unwanted_subdarfile.png" not in files - regex3 = r".*Recycle\.Bin\/.*unwanted.*subdirfile.*" + if ISWINDOWS: + regex3 = r".*Recycle\.Bin\\.*unwanted.*subdirfile.*" + else: + regex3 = r".*Recycle\.Bin\/.*unwanted.*subdirfile.*" self.d._exclude_list.rename(regex2, regex3) assert self.d._exclude_list.error(regex3) is None # print(f"get_folders(): {[x for x in self.d.get_folders()]}") @@ -516,6 +520,8 @@ files: {self.d._exclude_list.compiled_files} all: {self.d._exclude_list.compiled self.d.set_state(p1["foobar"][".hidden_dir"], DirectoryState.Normal) # The files should still be filtered files = self.get_files_and_expect_num_result(1) + eq_(len(self.d._exclude_list.compiled_paths), 0) + eq_(len(self.d._exclude_list.compiled_files), 1) assert ".hidden_file.txt" not in files assert ".hidden_subfile.png" not in files assert "foobar.jpg" in files diff --git a/core/tests/exclude_test.py b/core/tests/exclude_test.py index 3745ac21..8bfc8cc7 100644 --- a/core/tests/exclude_test.py +++ b/core/tests/exclude_test.py @@ -245,7 +245,7 @@ class TestCaseCompiledList(): assert expr.pattern in exprs def test_compiled_files(self): - # test is separator is indeed checked properly to yield the output + # is path separator checked properly to yield the output regex1 = r"test/one/sub" self.e_separate.add(regex1) self.e_separate.mark(regex1)