mirror of
https://github.com/python/cpython.git
synced 2025-07-24 19:54:21 +00:00
GH-73991: Add follow_symlinks argument to pathlib.Path.copy()
(#120519)
Add support for not following symlinks in `pathlib.Path.copy()`. On Windows we add the `COPY_FILE_COPY_SYMLINK` flag is following symlinks is disabled. If the source is symlink to a directory, this call will fail with `ERROR_ACCESS_DENIED`. In this case we add `COPY_FILE_DIRECTORY` to the flags and retry. This can fail on old Windowses, which we note in the docs. No news as `copy()` was only just added.
This commit is contained in:
parent
9f741e55c1
commit
20d5b84f57
6 changed files with 86 additions and 11 deletions
|
@ -1743,7 +1743,7 @@ class DummyPathTest(DummyPurePathTest):
|
|||
source.copy(target)
|
||||
|
||||
@needs_symlinks
|
||||
def test_copy_symlink(self):
|
||||
def test_copy_symlink_follow_symlinks_true(self):
|
||||
base = self.cls(self.base)
|
||||
source = base / 'linkA'
|
||||
target = base / 'copyA'
|
||||
|
@ -1752,6 +1752,26 @@ class DummyPathTest(DummyPurePathTest):
|
|||
self.assertFalse(target.is_symlink())
|
||||
self.assertEqual(source.read_text(), target.read_text())
|
||||
|
||||
@needs_symlinks
|
||||
def test_copy_symlink_follow_symlinks_false(self):
|
||||
base = self.cls(self.base)
|
||||
source = base / 'linkA'
|
||||
target = base / 'copyA'
|
||||
source.copy(target, follow_symlinks=False)
|
||||
self.assertTrue(target.exists())
|
||||
self.assertTrue(target.is_symlink())
|
||||
self.assertEqual(source.readlink(), target.readlink())
|
||||
|
||||
@needs_symlinks
|
||||
def test_copy_directory_symlink_follow_symlinks_false(self):
|
||||
base = self.cls(self.base)
|
||||
source = base / 'linkB'
|
||||
target = base / 'copyA'
|
||||
source.copy(target, follow_symlinks=False)
|
||||
self.assertTrue(target.exists())
|
||||
self.assertTrue(target.is_symlink())
|
||||
self.assertEqual(source.readlink(), target.readlink())
|
||||
|
||||
def test_copy_to_existing_file(self):
|
||||
base = self.cls(self.base)
|
||||
source = base / 'fileA'
|
||||
|
@ -1780,6 +1800,19 @@ class DummyPathTest(DummyPurePathTest):
|
|||
self.assertFalse(real_target.is_symlink())
|
||||
self.assertEqual(source.read_text(), real_target.read_text())
|
||||
|
||||
@needs_symlinks
|
||||
def test_copy_to_existing_symlink_follow_symlinks_false(self):
|
||||
base = self.cls(self.base)
|
||||
source = base / 'dirB' / 'fileB'
|
||||
target = base / 'linkA'
|
||||
real_target = base / 'fileA'
|
||||
source.copy(target, follow_symlinks=False)
|
||||
self.assertTrue(target.exists())
|
||||
self.assertTrue(target.is_symlink())
|
||||
self.assertTrue(real_target.exists())
|
||||
self.assertFalse(real_target.is_symlink())
|
||||
self.assertEqual(source.read_text(), real_target.read_text())
|
||||
|
||||
def test_copy_empty(self):
|
||||
base = self.cls(self.base)
|
||||
source = base / 'empty'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue