mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
GH-130608: Remove dirs_exist_ok
argument from pathlib.Path.copy()
(#130610)
This feature isn't sufficiently motivated.
This commit is contained in:
parent
fdcbc29f26
commit
b545450961
6 changed files with 13 additions and 40 deletions
|
@ -1571,8 +1571,7 @@ Creating files and directories
|
||||||
Copying, moving and deleting
|
Copying, moving and deleting
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. method:: Path.copy(target, *, follow_symlinks=True, dirs_exist_ok=False, \
|
.. method:: Path.copy(target, *, follow_symlinks=True, preserve_metadata=False)
|
||||||
preserve_metadata=False)
|
|
||||||
|
|
||||||
Copy this file or directory tree to the given *target*, and return a new
|
Copy this file or directory tree to the given *target*, and return a new
|
||||||
:class:`!Path` instance pointing to *target*.
|
:class:`!Path` instance pointing to *target*.
|
||||||
|
@ -1582,12 +1581,6 @@ Copying, moving and deleting
|
||||||
default), the symlink's target is copied. Otherwise, the symlink is
|
default), the symlink's target is copied. Otherwise, the symlink is
|
||||||
recreated at the destination.
|
recreated at the destination.
|
||||||
|
|
||||||
If the source is a directory and *dirs_exist_ok* is false (the default), a
|
|
||||||
:exc:`FileExistsError` is raised if the target is an existing directory.
|
|
||||||
If *dirs_exists_ok* is true, the copying operation will overwrite
|
|
||||||
existing files within the destination tree with corresponding files
|
|
||||||
from the source tree.
|
|
||||||
|
|
||||||
If *preserve_metadata* is false (the default), only directory structures
|
If *preserve_metadata* is false (the default), only directory structures
|
||||||
and file data are guaranteed to be copied. Set *preserve_metadata* to true
|
and file data are guaranteed to be copied. Set *preserve_metadata* to true
|
||||||
to ensure that file and directory permissions, flags, last access and
|
to ensure that file and directory permissions, flags, last access and
|
||||||
|
@ -1604,7 +1597,7 @@ Copying, moving and deleting
|
||||||
|
|
||||||
|
|
||||||
.. method:: Path.copy_into(target_dir, *, follow_symlinks=True, \
|
.. method:: Path.copy_into(target_dir, *, follow_symlinks=True, \
|
||||||
dirs_exist_ok=False, preserve_metadata=False)
|
preserve_metadata=False)
|
||||||
|
|
||||||
Copy this file or directory tree into the given *target_dir*, which should
|
Copy this file or directory tree into the given *target_dir*, which should
|
||||||
be an existing directory. Other arguments are handled identically to
|
be an existing directory. Other arguments are handled identically to
|
||||||
|
|
|
@ -340,19 +340,18 @@ class ReadablePath(JoinablePath):
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def copy(self, target, follow_symlinks=True, dirs_exist_ok=False,
|
def copy(self, target, follow_symlinks=True, preserve_metadata=False):
|
||||||
preserve_metadata=False):
|
|
||||||
"""
|
"""
|
||||||
Recursively copy this file or directory tree to the given destination.
|
Recursively copy this file or directory tree to the given destination.
|
||||||
"""
|
"""
|
||||||
if not hasattr(target, 'with_segments'):
|
if not hasattr(target, 'with_segments'):
|
||||||
target = self.with_segments(target)
|
target = self.with_segments(target)
|
||||||
ensure_distinct_paths(self, target)
|
ensure_distinct_paths(self, target)
|
||||||
copy_file(self, target, follow_symlinks, dirs_exist_ok, preserve_metadata)
|
copy_file(self, target, follow_symlinks, preserve_metadata)
|
||||||
return target.joinpath() # Empty join to ensure fresh metadata.
|
return target.joinpath() # Empty join to ensure fresh metadata.
|
||||||
|
|
||||||
def copy_into(self, target_dir, *, follow_symlinks=True,
|
def copy_into(self, target_dir, *, follow_symlinks=True,
|
||||||
dirs_exist_ok=False, preserve_metadata=False):
|
preserve_metadata=False):
|
||||||
"""
|
"""
|
||||||
Copy this file or directory tree into the given existing directory.
|
Copy this file or directory tree into the given existing directory.
|
||||||
"""
|
"""
|
||||||
|
@ -364,7 +363,6 @@ class ReadablePath(JoinablePath):
|
||||||
else:
|
else:
|
||||||
target = self.with_segments(target_dir, name)
|
target = self.with_segments(target_dir, name)
|
||||||
return self.copy(target, follow_symlinks=follow_symlinks,
|
return self.copy(target, follow_symlinks=follow_symlinks,
|
||||||
dirs_exist_ok=dirs_exist_ok,
|
|
||||||
preserve_metadata=preserve_metadata)
|
preserve_metadata=preserve_metadata)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1093,19 +1093,18 @@ class Path(PurePath):
|
||||||
target = self.with_segments(target)
|
target = self.with_segments(target)
|
||||||
return target
|
return target
|
||||||
|
|
||||||
def copy(self, target, follow_symlinks=True, dirs_exist_ok=False,
|
def copy(self, target, follow_symlinks=True, preserve_metadata=False):
|
||||||
preserve_metadata=False):
|
|
||||||
"""
|
"""
|
||||||
Recursively copy this file or directory tree to the given destination.
|
Recursively copy this file or directory tree to the given destination.
|
||||||
"""
|
"""
|
||||||
if not hasattr(target, 'with_segments'):
|
if not hasattr(target, 'with_segments'):
|
||||||
target = self.with_segments(target)
|
target = self.with_segments(target)
|
||||||
ensure_distinct_paths(self, target)
|
ensure_distinct_paths(self, target)
|
||||||
copy_file(self, target, follow_symlinks, dirs_exist_ok, preserve_metadata)
|
copy_file(self, target, follow_symlinks, preserve_metadata)
|
||||||
return target.joinpath() # Empty join to ensure fresh metadata.
|
return target.joinpath() # Empty join to ensure fresh metadata.
|
||||||
|
|
||||||
def copy_into(self, target_dir, *, follow_symlinks=True,
|
def copy_into(self, target_dir, *, follow_symlinks=True,
|
||||||
dirs_exist_ok=False, preserve_metadata=False):
|
preserve_metadata=False):
|
||||||
"""
|
"""
|
||||||
Copy this file or directory tree into the given existing directory.
|
Copy this file or directory tree into the given existing directory.
|
||||||
"""
|
"""
|
||||||
|
@ -1117,7 +1116,6 @@ class Path(PurePath):
|
||||||
else:
|
else:
|
||||||
target = self.with_segments(target_dir, name)
|
target = self.with_segments(target_dir, name)
|
||||||
return self.copy(target, follow_symlinks=follow_symlinks,
|
return self.copy(target, follow_symlinks=follow_symlinks,
|
||||||
dirs_exist_ok=dirs_exist_ok,
|
|
||||||
preserve_metadata=preserve_metadata)
|
preserve_metadata=preserve_metadata)
|
||||||
|
|
||||||
def move(self, target):
|
def move(self, target):
|
||||||
|
|
|
@ -242,8 +242,7 @@ def ensure_different_files(source, target):
|
||||||
raise err
|
raise err
|
||||||
|
|
||||||
|
|
||||||
def copy_file(source, target, follow_symlinks=True, dirs_exist_ok=False,
|
def copy_file(source, target, follow_symlinks=True, preserve_metadata=False):
|
||||||
preserve_metadata=False):
|
|
||||||
"""
|
"""
|
||||||
Recursively copy the given source ReadablePath to the given target WritablePath.
|
Recursively copy the given source ReadablePath to the given target WritablePath.
|
||||||
"""
|
"""
|
||||||
|
@ -254,10 +253,10 @@ def copy_file(source, target, follow_symlinks=True, dirs_exist_ok=False,
|
||||||
target._write_info(info, follow_symlinks=False)
|
target._write_info(info, follow_symlinks=False)
|
||||||
elif info.is_dir():
|
elif info.is_dir():
|
||||||
children = source.iterdir()
|
children = source.iterdir()
|
||||||
target.mkdir(exist_ok=dirs_exist_ok)
|
target.mkdir()
|
||||||
for src in children:
|
for src in children:
|
||||||
dst = target.joinpath(src.name)
|
dst = target.joinpath(src.name)
|
||||||
copy_file(src, dst, follow_symlinks, dirs_exist_ok, preserve_metadata)
|
copy_file(src, dst, follow_symlinks, preserve_metadata)
|
||||||
if preserve_metadata:
|
if preserve_metadata:
|
||||||
target._write_info(info)
|
target._write_info(info)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1495,23 +1495,6 @@ class RWPathTest(WritablePathTest, ReadablePathTest):
|
||||||
target.joinpath('dirD').mkdir()
|
target.joinpath('dirD').mkdir()
|
||||||
self.assertRaises(FileExistsError, source.copy, target)
|
self.assertRaises(FileExistsError, source.copy, target)
|
||||||
|
|
||||||
def test_copy_dir_to_existing_directory_dirs_exist_ok(self):
|
|
||||||
base = self.cls(self.base)
|
|
||||||
source = base / 'dirC'
|
|
||||||
target = base / 'copyC'
|
|
||||||
target.mkdir()
|
|
||||||
target.joinpath('dirD').mkdir()
|
|
||||||
result = source.copy(target, dirs_exist_ok=True)
|
|
||||||
self.assertEqual(result, target)
|
|
||||||
self.assertTrue(result.info.is_dir())
|
|
||||||
self.assertTrue(result.joinpath('dirD').info.is_dir())
|
|
||||||
self.assertTrue(result.joinpath('dirD', 'fileD').info.is_file())
|
|
||||||
self.assertEqual(result.joinpath('dirD', 'fileD').read_text(),
|
|
||||||
"this is file D\n")
|
|
||||||
self.assertTrue(result.joinpath('fileC').info.is_file())
|
|
||||||
self.assertTrue(result.joinpath('fileC').read_text(),
|
|
||||||
"this is file C\n")
|
|
||||||
|
|
||||||
def test_copy_dir_to_itself(self):
|
def test_copy_dir_to_itself(self):
|
||||||
base = self.cls(self.base)
|
base = self.cls(self.base)
|
||||||
source = base / 'dirC'
|
source = base / 'dirC'
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Remove *dirs_exist_ok* argument from :meth:`pathlib.Path.copy` and
|
||||||
|
:meth:`~pathlib.Path.copy_into`. These methods are new in Python 3.14.
|
Loading…
Add table
Add a link
Reference in a new issue