mirror of https://github.com/borgbase/vorta
Handle empty path in `FileTreeModel.addItem`. (#1552)
This commit is contained in:
parent
ef297bbf4b
commit
c620c0d9ac
|
@ -162,15 +162,22 @@ class FileSystemItem(Generic[T]):
|
|||
"""
|
||||
if isinstance(child_subpath_index, FileSystemItem):
|
||||
child = child_subpath_index
|
||||
if not child.subpath:
|
||||
raise ValueError("Child without subpath")
|
||||
|
||||
i = bisect.bisect_left(self.children, child)
|
||||
if i < len(self.children) and self.children[i] == child:
|
||||
del self.children[i]
|
||||
else:
|
||||
raise ValueError("Child not found")
|
||||
|
||||
elif isinstance(child_subpath_index, str):
|
||||
subpath = child_subpath_index
|
||||
i = bisect.bisect_left(self.children, subpath)
|
||||
if i < len(self.children) and self.children[i].subpath == subpath:
|
||||
del self.children[i]
|
||||
else:
|
||||
raise ValueError("Child not found")
|
||||
|
||||
elif isinstance(child_subpath_index, int):
|
||||
i = child_subpath_index
|
||||
|
@ -239,7 +246,7 @@ class FileSystemItem(Generic[T]):
|
|||
i, item = res
|
||||
return item
|
||||
|
||||
fsi = reduce(walk, path, self)
|
||||
fsi = reduce(walk, path, self) # handles empty path -> returns self
|
||||
return fsi
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -351,14 +358,17 @@ class FileTreeModel(QAbstractItemModel, Generic[T]):
|
|||
item : FileSystemItemLike
|
||||
The item.
|
||||
"""
|
||||
self.beginResetModel()
|
||||
|
||||
path = item[0]
|
||||
data = item[1]
|
||||
|
||||
if isinstance(path, PurePath):
|
||||
path = path.parts
|
||||
|
||||
if not path:
|
||||
return # empty path (e.g. `.`) can't be added
|
||||
|
||||
self.beginResetModel()
|
||||
|
||||
def child(tup, subpath):
|
||||
fsi, i = tup
|
||||
i += 1
|
||||
|
@ -594,7 +604,7 @@ class FileTreeModel(QAbstractItemModel, Generic[T]):
|
|||
if isinstance(path, PurePath):
|
||||
path = path.parts
|
||||
|
||||
return self.root.get_path(path)
|
||||
return self.root.get_path(path) # handels empty path
|
||||
|
||||
def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole):
|
||||
"""
|
||||
|
@ -689,6 +699,9 @@ class FileTreeModel(QAbstractItemModel, Generic[T]):
|
|||
if isinstance(path, PurePath):
|
||||
path = path.parts
|
||||
|
||||
if not path:
|
||||
return QModelIndex() # empty path won't ever be in the model
|
||||
|
||||
# flat mode
|
||||
if self.mode == self.DisplayMode.FLAT:
|
||||
i = bisect.bisect_left(self._flattened, path)
|
||||
|
@ -889,7 +902,15 @@ class FileTreeSortProxyModel(QSortFilterProxyModel):
|
|||
super().__init__(parent)
|
||||
self.folders_on_top = False
|
||||
|
||||
def keepFoldersOnTop(self, value: bool = None) -> bool:
|
||||
@overload
|
||||
def keepFoldersOnTop(self) -> bool:
|
||||
...
|
||||
|
||||
@overload
|
||||
def keepFoldersOnTop(self, value: bool) -> bool:
|
||||
...
|
||||
|
||||
def keepFoldersOnTop(self, value=None) -> bool:
|
||||
"""
|
||||
Set or get whether folders are kept on top when sorting.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
{"type": "d", "mode": "drwxrwxr-x", "user": "theuser", "group": "theuser", "uid": 1000, "gid": 1000, "path": ".", "healthy": true, "source": "", "linktarget": "", "flags": null, "mtime": "2022-05-13T14:33:57.305797", "size": 0}
|
||||
{"type": "d", "mode": "drwxrwxr-x", "user": "theuser", "group": "theuser", "uid": 1000, "gid": 1000, "path": "home/theuser/vorta", "healthy": true, "source": "", "linktarget": "", "flags": null, "mtime": "2022-05-13T14:33:57.305797", "size": 0}
|
||||
{"type": "d", "mode": "drwx------", "user": "theuser", "group": "theuser", "uid": 1000, "gid": 1000, "path": "home/theuser/vorta/.pytest_cache", "healthy": true, "source": "", "linktarget": "", "flags": null, "mtime": "2022-04-19T17:45:37.456679", "size": 0}
|
||||
{"type": "d", "mode": "drwx------", "user": "theuser", "group": "theuser", "uid": 1000, "gid": 1000, "path": "home/theuser/vorta/.pytest_cache/v", "healthy": true, "source": "", "linktarget": "", "flags": null, "mtime": "2022-04-19T17:45:37.456679", "size": 0}
|
||||
|
|
|
@ -41,6 +41,11 @@ class TestFileSystemItem:
|
|||
# may not add a child with the same subpath
|
||||
item.add(child)
|
||||
|
||||
# not implemented due to performance reasons:
|
||||
# child = FileSystemItem((), 8)
|
||||
# with pytest.raises(ValueError):
|
||||
# item.add(child) # may not add a child with an empty path
|
||||
|
||||
def test_remove(self):
|
||||
item = FileSystemItem(PurePath('test').parts, 0)
|
||||
child1 = FileSystemItem(PurePath('test/a').parts, 4)
|
||||
|
@ -63,6 +68,14 @@ class TestFileSystemItem:
|
|||
assert len(item.children) == 1
|
||||
assert child3 not in item.children
|
||||
|
||||
# test remove item not present
|
||||
child = FileSystemItem(PurePath('notpresent').parts, 2)
|
||||
with pytest.raises(ValueError):
|
||||
item.remove(child)
|
||||
child = FileSystemItem((), 2)
|
||||
with pytest.raises(ValueError):
|
||||
item.remove(child)
|
||||
|
||||
def test_get(self):
|
||||
item = FileSystemItem(PurePath('test').parts, 0)
|
||||
child1 = FileSystemItem(PurePath('test/a').parts, 4)
|
||||
|
@ -105,6 +118,9 @@ class TestFileSystemItem:
|
|||
assert item.get_path(PurePath('a/aa').parts) is child11
|
||||
assert item.get_path(('b',)) is child2
|
||||
|
||||
# test get empty path
|
||||
assert item.get_path(()) is item
|
||||
|
||||
|
||||
class TestFileTreeModel:
|
||||
def test_basic_setup(self):
|
||||
|
@ -170,6 +186,16 @@ class TestFileTreeModel:
|
|||
item3 = model.getItem(PurePath('/hello'))
|
||||
assert len(item3.children) == 0
|
||||
|
||||
def test_empty_path(self):
|
||||
model = TreeModelImp()
|
||||
assert model.rowCount() == 0
|
||||
|
||||
model.addItem(((), None))
|
||||
assert model.rowCount() == 0
|
||||
|
||||
model.addItem((PurePath('.'), None))
|
||||
assert model.rowCount() == 0
|
||||
|
||||
def test_root(self):
|
||||
model = TreeModelImp()
|
||||
assert model.getItem(PurePath()) == model.root
|
||||
|
|
Loading…
Reference in New Issue