diff --git a/core/directories.py b/core/directories.py index 6b84295b..1a82e183 100644 --- a/core/directories.py +++ b/core/directories.py @@ -51,6 +51,7 @@ class Directories: #---Override def __init__(self, fileclasses=[fs.File]): self._dirs = [] + # {path: state} self.states = {} self.fileclasses = fileclasses self.folderclass = fs.Folder @@ -220,7 +221,7 @@ class Directories: continue path = attrib['path'] state = attrib['value'] - self.set_state(Path(path), int(state)) + self.states[Path(path)] = int(state) def save_to_file(self, outfile): """Save folder selection as XML to ``outfile``. @@ -248,11 +249,8 @@ class Directories: """ if self.get_state(path) == state: return - # we don't want to needlessly fill self.states. if get_state returns the same thing - # without an explicit entry, remove that entry - if path in self.states: - del self.states[path] - if self.get_state(path) == state: # no need for an entry - return + for iter_path in list(self.states.keys()): + if path.is_parent_of(iter_path): + del self.states[iter_path] self.states[path] = state diff --git a/core/tests/directories_test.py b/core/tests/directories_test.py index 0c789d46..e5eef713 100644 --- a/core/tests/directories_test.py +++ b/core/tests/directories_test.py @@ -135,31 +135,18 @@ def test_get_state_with_path_not_there(): d.add_path(testpath['onefile']) eq_(d.get_state(testpath), DirectoryState.Normal) -def test_states_remain_when_larger_directory_eat_smaller_ones(): +def test_states_overwritten_when_larger_directory_eat_smaller_ones(): + # ref #248 + # When setting the state of a folder, we overwrite previously set states for subfolders. d = Directories() p = testpath['onefile'] d.add_path(p) d.set_state(p, DirectoryState.Excluded) d.add_path(testpath) d.set_state(testpath, DirectoryState.Reference) - eq_(DirectoryState.Excluded ,d.get_state(p)) - eq_(DirectoryState.Excluded ,d.get_state(p['dir1'])) - eq_(DirectoryState.Reference ,d.get_state(testpath)) - -def test_set_state_keep_state_dict_size_to_minimum(): - d = Directories() - p = testpath['fs'] - d.add_path(p) - d.set_state(p, DirectoryState.Reference) - d.set_state(p['dir1'], DirectoryState.Reference) - eq_(1,len(d.states)) - eq_(DirectoryState.Reference ,d.get_state(p['dir1'])) - d.set_state(p['dir1'], DirectoryState.Normal) - eq_(2,len(d.states)) - eq_(DirectoryState.Normal ,d.get_state(p['dir1'])) - d.set_state(p['dir1'], DirectoryState.Reference) - eq_(1,len(d.states)) - eq_(DirectoryState.Reference ,d.get_state(p['dir1'])) + eq_(d.get_state(p), DirectoryState.Reference) + eq_(d.get_state(p['dir1']), DirectoryState.Reference) + eq_(d.get_state(testpath), DirectoryState.Reference) def test_get_files(): d = Directories() diff --git a/hscommon/path.py b/hscommon/path.py index b7166895..55a3ed42 100755 --- a/hscommon/path.py +++ b/hscommon/path.py @@ -117,6 +117,17 @@ class Path(tuple): first = self[0] return (len(first) == 2) and (first[1] == ':') + def is_parent_of(self, other): + """Whether ``other`` is a subpath of ``self``. + + Almost the same as ``other in self``, but it's a bit more self-explicative and when + ``other == self``, returns False. + """ + if other == self: + return False + else: + return other in self + def remove_drive_letter(self): if self.has_drive_letter(): return self[1:] diff --git a/hscommon/tests/path_test.py b/hscommon/tests/path_test.py index c9b40548..108a99e1 100644 --- a/hscommon/tests/path_test.py +++ b/hscommon/tests/path_test.py @@ -163,6 +163,11 @@ def test_contains(force_ossep): assert 'bleh' not in p assert Path('foo') not in p +def test_is_parent_of(force_ossep): + assert Path(('foo','bar')).is_parent_of(Path(('foo','bar','bleh'))) + assert not Path(('foo','bar')).is_parent_of(Path(('foo','baz'))) + assert not Path(('foo','bar')).is_parent_of(Path(('foo','bar'))) + def test_windows_drive_letter(force_ossep): p = Path(('c:',)) eq_('c:\\',str(p))