Skip to content

Commit 59f6e4d

Browse files
authored
Fix backward incompatibility introduced in 2.4.16 (#542)
* add default overwrite arg (fixes #535) * update changelog * add tests * fix deletion when moving file on itself * compare normalized pathes in early exit * check no longer needed * remove unused import
1 parent 11ad1ec commit 59f6e4d

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
88

99
## Unreleased
1010

11+
1112
### Added
1213

1314
- Added `filter_glob` and `exclude_glob` parameters to `fs.walk.Walker`.
@@ -16,6 +17,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1617
### Fixed
1718
- Elaborated documentation of `filter_dirs` and `exclude_dirs` in `fs.walk.Walker`.
1819
Closes [#371](https://github.com/PyFilesystem/pyfilesystem2/issues/371).
20+
- Fixes a backward incompatibility where `fs.move.move_file` raises `DestinationExists`
21+
([#535](https://github.com/PyFilesystem/pyfilesystem2/issues/535)).
1922
- Fixed a bug where files could be truncated or deleted when moved / copied onto itself.
2023
Closes [#546](https://github.com/PyFilesystem/pyfilesystem2/issues/546)
2124

fs/move.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,12 @@ def move_file(
8282
rel_dst = frombase(common, dst_syspath)
8383
with _src_fs.lock(), _dst_fs.lock():
8484
with OSFS(common) as base:
85-
base.move(rel_src, rel_dst, preserve_time=preserve_time)
85+
base.move(
86+
rel_src,
87+
rel_dst,
88+
overwrite=True,
89+
preserve_time=preserve_time,
90+
)
8691
return # optimization worked, exit early
8792
except ValueError:
8893
# This is raised if we cannot find a common base folder.

tests/test_move.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,45 @@ def test_move_file_read_only_mem_dest(self):
151151
dst_ro.exists("target.txt"), "file should not have been copied over"
152152
)
153153

154+
@parameterized.expand([("temp", "temp://"), ("mem", "mem://")])
155+
def test_move_file_overwrite(self, _, fs_url):
156+
# we use TempFS and MemoryFS in order to make sure the optimized code path
157+
# behaves like the regular one (TempFS tests the optmized code path).
158+
with open_fs(fs_url) as src, open_fs(fs_url) as dst:
159+
src.writetext("file.txt", "source content")
160+
dst.writetext("target.txt", "target content")
161+
self.assertTrue(src.exists("file.txt"))
162+
self.assertFalse(src.exists("target.txt"))
163+
self.assertFalse(dst.exists("file.txt"))
164+
self.assertTrue(dst.exists("target.txt"))
165+
fs.move.move_file(src, "file.txt", dst, "target.txt")
166+
self.assertFalse(src.exists("file.txt"))
167+
self.assertFalse(src.exists("target.txt"))
168+
self.assertFalse(dst.exists("file.txt"))
169+
self.assertTrue(dst.exists("target.txt"))
170+
self.assertEquals(dst.readtext("target.txt"), "source content")
171+
172+
@parameterized.expand([("temp", "temp://"), ("mem", "mem://")])
173+
def test_move_file_overwrite_itself(self, _, fs_url):
174+
# we use TempFS and MemoryFS in order to make sure the optimized code path
175+
# behaves like the regular one (TempFS tests the optmized code path).
176+
with open_fs(fs_url) as tmp:
177+
tmp.writetext("file.txt", "content")
178+
fs.move.move_file(tmp, "file.txt", tmp, "file.txt")
179+
self.assertTrue(tmp.exists("file.txt"))
180+
self.assertEquals(tmp.readtext("file.txt"), "content")
181+
182+
@parameterized.expand([("temp", "temp://"), ("mem", "mem://")])
183+
def test_move_file_overwrite_itself_relpath(self, _, fs_url):
184+
# we use TempFS and MemoryFS in order to make sure the optimized code path
185+
# behaves like the regular one (TempFS tests the optmized code path).
186+
with open_fs(fs_url) as tmp:
187+
new_dir = tmp.makedir("dir")
188+
new_dir.writetext("file.txt", "content")
189+
fs.move.move_file(tmp, "dir/../dir/file.txt", tmp, "dir/file.txt")
190+
self.assertTrue(tmp.exists("dir/file.txt"))
191+
self.assertEquals(tmp.readtext("dir/file.txt"), "content")
192+
154193
@parameterized.expand([(True,), (False,)])
155194
def test_move_file_cleanup_on_error(self, cleanup):
156195
with open_fs("mem://") as src, open_fs("mem://") as dst:

0 commit comments

Comments
 (0)