Skip to content

Commit 55d2b37

Browse files
committed
Standardize behaviour of removetree("/") and add test case to FSTestCase
1 parent 7dbeb88 commit 55d2b37

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

fs/base.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ def removedir(self, path):
273273
Raises:
274274
fs.errors.DirectoryNotEmpty: If the directory is not empty (
275275
see `~fs.base.FS.removetree` for a way to remove the
276-
directory contents.).
276+
directory contents).
277277
fs.errors.DirectoryExpected: If the path does not refer to
278278
a directory.
279279
fs.errors.ResourceNotFound: If no resource exists at the
@@ -1215,14 +1215,38 @@ def opendir(
12151215

12161216
def removetree(self, dir_path):
12171217
# type: (Text) -> None
1218-
"""Recursively remove the contents of a directory.
1218+
"""Recursively remove a directory and all its contents.
12191219
1220-
This method is similar to `~fs.base.removedir`, but will
1220+
This method is similar to `~fs.base.FS.removedir`, but will
12211221
remove the contents of the directory if it is not empty.
12221222
12231223
Arguments:
12241224
dir_path (str): Path to a directory on the filesystem.
12251225
1226+
Caution:
1227+
A filesystem should never delete its root folder, so
1228+
``FS.removetree("/")`` has different semantics: the
1229+
contents of the root folder will be deleted, but the
1230+
root will be untouched::
1231+
1232+
>>> home_fs = fs.open_fs("~")
1233+
>>> home_fs.removetree("/")
1234+
>>> home_fs.exists("/")
1235+
True
1236+
>>> home_fs.isempty("/")
1237+
True
1238+
1239+
Combined with `~fs.base.FS.opendir`, this can be used
1240+
to clear a directory without removing the directory
1241+
itself::
1242+
1243+
>>> home_fs = fs.open_fs("~")
1244+
>>> home_fs.opendir("/Videos").removetree("/")
1245+
>>> home_fs.exists("/Videos")
1246+
True
1247+
>>> home_fs.isempty("/Videos")
1248+
True
1249+
12261250
"""
12271251
_dir_path = abspath(normpath(dir_path))
12281252
with self._lock:

fs/test.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,15 @@ def assert_not_exists(self, path):
292292
"""
293293
self.assertFalse(self.fs.exists(path))
294294

295+
def assert_isempty(self, path):
296+
"""Assert a path is an empty directory.
297+
298+
Arguments:
299+
path (str): A path on the filesystem.
300+
301+
"""
302+
self.assertTrue(self.fs.isempty(path))
303+
295304
def assert_isfile(self, path):
296305
"""Assert a path is a file.
297306
@@ -1101,6 +1110,7 @@ def test_removedir(self):
11011110
self.fs.removedir("foo/bar")
11021111

11031112
def test_removetree(self):
1113+
self.fs.makedirs("spam")
11041114
self.fs.makedirs("foo/bar/baz")
11051115
self.fs.makedirs("foo/egg")
11061116
self.fs.makedirs("foo/a/b/c/d/e")
@@ -1116,6 +1126,7 @@ def test_removetree(self):
11161126

11171127
self.fs.removetree("foo")
11181128
self.assert_not_exists("foo")
1129+
self.assert_exists("spam")
11191130

11201131
# Errors on files
11211132
self.fs.create("bar")
@@ -1126,6 +1137,34 @@ def test_removetree(self):
11261137
with self.assertRaises(errors.ResourceNotFound):
11271138
self.fs.removetree("foofoo")
11281139

1140+
def test_removetree_root(self):
1141+
self.fs.makedirs("foo/bar/baz")
1142+
self.fs.makedirs("foo/egg")
1143+
self.fs.makedirs("foo/a/b/c/d/e")
1144+
self.fs.create("foo/egg.txt")
1145+
self.fs.create("foo/bar/egg.bin")
1146+
self.fs.create("foo/a/b/c/1.txt")
1147+
self.fs.create("foo/a/b/c/2.txt")
1148+
self.fs.create("foo/a/b/c/3.txt")
1149+
1150+
self.assert_exists("foo/egg.txt")
1151+
self.assert_exists("foo/bar/egg.bin")
1152+
1153+
# removetree("/") removes the contents,
1154+
# but not the root folder itself
1155+
self.fs.removetree("/")
1156+
self.assert_exists("/")
1157+
self.assert_isempty("/")
1158+
1159+
# we check we can create a file after
1160+
# to catch potential issues with the
1161+
# root folder being deleted on faulty
1162+
# implementations
1163+
self.fs.create("egg")
1164+
self.fs.makedir("yolk")
1165+
self.assert_exists("egg")
1166+
self.assert_exists("yolk")
1167+
11291168
def test_setinfo(self):
11301169
self.fs.create("birthday.txt")
11311170
now = math.floor(time.time())

0 commit comments

Comments
 (0)