@@ -29,7 +29,7 @@
2929frompathlib._osimport (
3030PathInfo, DirEntryInfo,
3131ensure_different_files, ensure_distinct_paths,
32-copy_file, copy_info,
32+copyfile2, copyfileobj, magic_open, copy_info,
3333)
34343535@@ -810,12 +810,6 @@ def write_text(self, data, encoding=None, errors=None, newline=None):
810810withself.open(mode='w', encoding=encoding, errors=errors, newline=newline) asf:
811811returnf.write(data)
812812813-def_write_info(self, info, follow_symlinks=True):
814-"""
815- Write the given PathInfo to this path.
816- """
817-copy_info(info, self, follow_symlinks=follow_symlinks)
818-819813_remove_leading_dot=operator.itemgetter(slice(2, None))
820814_remove_trailing_slash=operator.itemgetter(slice(-1))
821815@@ -1100,18 +1094,21 @@ def replace(self, target):
11001094target=self.with_segments(target)
11011095returntarget
110210961103-defcopy(self, target, follow_symlinks=True, preserve_metadata=False):
1097+defcopy(self, target, **kwargs):
11041098"""
11051099 Recursively copy this file or directory tree to the given destination.
11061100 """
11071101ifnothasattr(target, 'with_segments'):
11081102target=self.with_segments(target)
11091103ensure_distinct_paths(self, target)
1110-copy_file(self, target, follow_symlinks, preserve_metadata)
1104+try:
1105+copy_to_target=target._copy_from
1106+exceptAttributeError:
1107+raiseTypeError(f"Target path is not writable: {target!r}") fromNone
1108+copy_to_target(self, **kwargs)
11111109returntarget.joinpath() # Empty join to ensure fresh metadata.
111211101113-defcopy_into(self, target_dir, *, follow_symlinks=True,
1114-preserve_metadata=False):
1111+defcopy_into(self, target_dir, **kwargs):
11151112"""
11161113 Copy this file or directory tree into the given existing directory.
11171114 """
@@ -1122,8 +1119,59 @@ def copy_into(self, target_dir, *, follow_symlinks=True,
11221119target=target_dir/name
11231120else:
11241121target=self.with_segments(target_dir, name)
1125-returnself.copy(target, follow_symlinks=follow_symlinks,
1126-preserve_metadata=preserve_metadata)
1122+returnself.copy(target, **kwargs)
1123+1124+def_copy_from(self, source, follow_symlinks=True, preserve_metadata=False):
1125+"""
1126+ Recursively copy the given path to this path.
1127+ """
1128+ifnotfollow_symlinksandsource.info.is_symlink():
1129+self._copy_from_symlink(source, preserve_metadata)
1130+elifsource.info.is_dir():
1131+children=source.iterdir()
1132+os.mkdir(self)
1133+forchildinchildren:
1134+self.joinpath(child.name)._copy_from(
1135+child, follow_symlinks, preserve_metadata)
1136+ifpreserve_metadata:
1137+copy_info(source.info, self)
1138+else:
1139+self._copy_from_file(source, preserve_metadata)
1140+1141+def_copy_from_file(self, source, preserve_metadata=False):
1142+ensure_different_files(source, self)
1143+withmagic_open(source, 'rb') assource_f:
1144+withopen(self, 'wb') astarget_f:
1145+copyfileobj(source_f, target_f)
1146+ifpreserve_metadata:
1147+copy_info(source.info, self)
1148+1149+ifcopyfile2:
1150+# Use fast OS routine for local file copying where available.
1151+_copy_from_file_fallback=_copy_from_file
1152+def_copy_from_file(self, source, preserve_metadata=False):
1153+try:
1154+source=os.fspath(source)
1155+exceptTypeError:
1156+pass
1157+else:
1158+copyfile2(source, str(self))
1159+return
1160+self._copy_from_file_fallback(source, preserve_metadata)
1161+1162+ifos.name=='nt':
1163+# If a directory-symlink is copied *before* its target, then
1164+# os.symlink() incorrectly creates a file-symlink on Windows. Avoid
1165+# this by passing *target_is_dir* to os.symlink() on Windows.
1166+def_copy_from_symlink(self, source, preserve_metadata=False):
1167+os.symlink(str(source.readlink()), self, source.info.is_dir())
1168+ifpreserve_metadata:
1169+copy_info(source.info, self, follow_symlinks=False)
1170+else:
1171+def_copy_from_symlink(self, source, preserve_metadata=False):
1172+os.symlink(str(source.readlink()), self)
1173+ifpreserve_metadata:
1174+copy_info(source.info, self, follow_symlinks=False)
1127117511281176defmove(self, target):
11291177"""