Skip to content

Commit 2a93304

Browse files
committed
establish new errors.IllegalDestination
1 parent 9a7fe1a commit 2a93304

File tree

4 files changed

+42
-33
lines changed

4 files changed

+42
-33
lines changed

fs/base.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
from contextlib import closing
2222
from functools import partial, wraps
2323

24-
from . import copy, errors, fsencode, iotools, tools, walk, wildcard, glob
24+
from . import copy, errors, fsencode, glob, iotools, tools, walk, wildcard
2525
from .copy import copy_modified_time
2626
from .glob import BoundGlobber
2727
from .mode import validate_open_mode
28-
from .path import abspath, join, normpath
28+
from .path import abspath, isbase, join, normpath
2929
from .time import datetime_to_epoch
3030
from .walk import Walker
3131

@@ -425,11 +425,10 @@ def copy(
425425
with self._lock:
426426
_src_path = self.validatepath(src_path)
427427
_dst_path = self.validatepath(dst_path)
428+
if _src_path == _dst_path:
429+
raise errors.IllegalDestination(dst_path)
428430
if not overwrite and self.exists(_dst_path):
429431
raise errors.DestinationExists(dst_path)
430-
if overwrite and _src_path == _dst_path:
431-
# exit early when copying a file onto itself
432-
return
433432
with closing(self.open(_src_path, "rb")) as read_file:
434433
# FIXME(@althonos): typing complains because open return IO
435434
self.upload(_dst_path, read_file) # type: ignore
@@ -1093,6 +1092,12 @@ def movedir(self, src_path, dst_path, create=False, preserve_time=False):
10931092
from .move import move_dir
10941093

10951094
with self._lock:
1095+
_src_path = self.validatepath(src_path)
1096+
_dst_path = self.validatepath(dst_path)
1097+
if _src_path == _dst_path:
1098+
return
1099+
if isbase(_src_path, _dst_path):
1100+
raise errors.IllegalDestination(dst_path)
10961101
if not create and not self.exists(dst_path):
10971102
raise errors.ResourceNotFound(dst_path)
10981103
move_dir(self, src_path, self, dst_path, preserve_time=preserve_time)

fs/errors.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232
"FilesystemClosed",
3333
"FSError",
3434
"IllegalBackReference",
35+
"IllegalDestination",
3536
"InsufficientStorage",
3637
"InvalidCharsInPath",
37-
"InvalidMoveOperation",
3838
"InvalidPath",
3939
"MissingInfoNamespace",
4040
"NoSysPath",
@@ -241,16 +241,14 @@ class RemoveRootError(OperationFailed):
241241
default_message = "root directory may not be removed"
242242

243243

244-
class IllegalMoveDestination(OperationFailed):
245-
"""Attempt to move a folder into its own subfolder."""
244+
class IllegalDestination(OperationFailed):
245+
"""The given destination cannot be used for the operation.
246246
247-
default_message = "'{path}' cannot be moved into itself"
248-
249-
250-
class IllegalCopyDestination(OperationFailed):
251-
"""Attempt to copy a folder into its own subfolder."""
247+
This error will occur when attempting to move / copy a folder into itself or copying
248+
a file onto itself.
249+
"""
252250

253-
default_message = "'{path}' cannot be copied into itself"
251+
default_message = "'{path}' is not a legal destination"
254252

255253

256254
class ResourceError(FSError):

fs/memoryfs.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from .enums import ResourceType, Seek
2020
from .info import Info
2121
from .mode import Mode
22-
from .path import iteratepath, normpath, split
22+
from .path import isbase, iteratepath, normpath, split
2323

2424
if typing.TYPE_CHECKING:
2525
from typing import (
@@ -478,8 +478,17 @@ def move(self, src_path, dst_path, overwrite=False, preserve_time=False):
478478
copy_modified_time(self, src_path, self, dst_path)
479479

480480
def movedir(self, src_path, dst_path, create=False, preserve_time=False):
481-
src_dir, src_name = split(self.validatepath(src_path))
482-
dst_dir, dst_name = split(self.validatepath(dst_path))
481+
_src_path = self.validatepath(src_path)
482+
_dst_path = self.validatepath(dst_path)
483+
dst_dir, dst_name = split(_dst_path)
484+
src_dir, src_name = split(_src_path)
485+
486+
# move a dir onto itself
487+
if _src_path == _dst_path:
488+
return
489+
# move a dir into itself
490+
if isbase(_src_path, _dst_path):
491+
raise errors.IllegalDestination(dst_path)
483492

484493
with self._lock:
485494
src_dir_entry = self._get_dir_entry(src_dir)

fs/test.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,20 +1830,20 @@ def test_move_file_onto_itself_relpath(self):
18301830

18311831
def test_copy_file_onto_itself(self):
18321832
self.fs.writetext("file.txt", "Hello")
1833-
self.fs.copy("file.txt", "file.txt", overwrite=True)
1834-
self.assert_text("file.txt", "Hello")
1835-
1836-
with self.assertRaises(errors.DestinationExists):
1833+
with self.assertRaises(errors.IllegalDestination):
1834+
self.fs.copy("file.txt", "file.txt", overwrite=True)
1835+
with self.assertRaises(errors.IllegalDestination):
18371836
self.fs.copy("file.txt", "file.txt", overwrite=False)
1837+
self.assert_text("file.txt", "Hello")
18381838

18391839
def test_copy_file_onto_itself_relpath(self):
18401840
subdir = self.fs.makedir("sub")
18411841
subdir.writetext("file.txt", "Hello")
1842-
self.fs.copy("sub/file.txt", "sub/../sub/file.txt", overwrite=True)
1843-
self.assert_text("sub/file.txt", "Hello")
1844-
1845-
with self.assertRaises(errors.DestinationExists):
1842+
with self.assertRaises(errors.IllegalDestination):
1843+
self.fs.copy("sub/file.txt", "sub/../sub/file.txt", overwrite=True)
1844+
with self.assertRaises(errors.IllegalDestination):
18461845
self.fs.copy("sub/file.txt", "sub/../sub/file.txt", overwrite=False)
1846+
self.assert_text("sub/file.txt", "Hello")
18471847

18481848
def test_copydir(self):
18491849
self.fs.makedirs("foo/bar/baz/egg")
@@ -1868,21 +1868,18 @@ def test_copydir_onto_itself(self):
18681868
sub = folder.makedir("sub")
18691869
sub.writetext("file2.txt", "Hello2")
18701870

1871-
self.fs.copydir("folder", "folder")
1871+
with self.assertRaises(errors.IllegalDestination):
1872+
self.fs.copydir("folder", "folder")
18721873
self.assert_text("folder/file1.txt", "Hello1")
18731874
self.assert_text("folder/sub/file2.txt", "Hello2")
18741875

18751876
def test_copydir_into_its_own_subfolder(self):
1876-
# TODO: This test hangs forever at the moment.
1877-
#
18781877
# folder = self.fs.makedir("folder")
18791878
# folder.writetext("file1.txt", "Hello1")
18801879
# sub = folder.makedir("sub")
18811880
# sub.writetext("file2.txt", "Hello2")
1882-
# self.fs.copydir("folder", "folder/sub/")
1883-
# self.assert_text("folder/file1.txt", "Hello1")
1884-
# self.assert_text("folder/sub/file1.txt", "Hello1")
1885-
# self.assert_not_exists("folder/sub/file2.txt")
1881+
# with self.assertRaises(errors.IllegalDestination):
1882+
# self.fs.copydir("folder", "folder/sub/")
18861883
pass
18871884

18881885
def test_movedir(self):
@@ -1924,7 +1921,7 @@ def test_movedir_into_its_own_subfolder(self):
19241921
sub = folder.makedir("sub")
19251922
sub.writetext("file2.txt", "Hello2")
19261923

1927-
with self.assertRaises(errors.IllegalMoveDestination):
1924+
with self.assertRaises(errors.IllegalDestination):
19281925
self.fs.movedir("folder", "folder/sub/")
19291926

19301927
def test_match(self):

0 commit comments

Comments
 (0)