|
41 | 41 | from upath.registry import get_upath_class |
42 | 42 | from upath.types import UNSET_DEFAULT |
43 | 43 | from upath.types import JoinablePathLike |
| 44 | +from upath.types import OnNameCollisionFunc |
44 | 45 | from upath.types import PathInfo |
45 | 46 | from upath.types import ReadablePath |
46 | 47 | from upath.types import ReadablePathLike |
@@ -1305,9 +1306,48 @@ def _copy_from( |
1305 | 1306 | self, |
1306 | 1307 | source: ReadablePath, |
1307 | 1308 | follow_symlinks: bool = True, |
| 1309 | + on_name_collision: OnNameCollisionFunc | None = None, |
1308 | 1310 | **kwargs: Any, |
1309 | 1311 | ) -> None: |
1310 | | - return super()._copy_from(source, follow_symlinks) |
| 1312 | + """ |
| 1313 | + UPath custom:: Recursively copy the given path to this path. |
| 1314 | + """ |
| 1315 | + # fixme: it would be best if this would be upstreamed |
| 1316 | + from pathlib_abc import vfsopen |
| 1317 | + from pathlib_abc import vfspath |
| 1318 | + from pathlib_abc._os import copyfileobj |
| 1319 | + from pathlib_abc._os import ensure_different_files |
| 1320 | + |
| 1321 | + stack: list[tuple[ReadablePath, WritablePath]] = [(source, self)] |
| 1322 | + while stack: |
| 1323 | + src, dst = stack.pop() |
| 1324 | + info = src.info |
| 1325 | + if not follow_symlinks and info.is_symlink(): |
| 1326 | + dst.symlink_to(vfspath(src.readlink()), src.info.is_dir()) |
| 1327 | + elif on_name_collision and info.is_file() and info.is_dir(): |
| 1328 | + dst_file, dst_dir = on_name_collision(src, dst) |
| 1329 | + if dst_file is not None: |
| 1330 | + ensure_different_files(src, dst_file) |
| 1331 | + with vfsopen(src, "rb") as source_f: |
| 1332 | + with vfsopen(dst_file, "wb") as target_f: |
| 1333 | + copyfileobj(source_f, target_f) |
| 1334 | + if dst_dir is not None: |
| 1335 | + children = src.iterdir() |
| 1336 | + dst_dir.mkdir() |
| 1337 | + # feed through dict.fromkeys to remove duplicates |
| 1338 | + for child in dict.fromkeys(children): |
| 1339 | + stack.append((child, dst_dir.joinpath(child.name))) |
| 1340 | + elif info.is_dir(): |
| 1341 | + children = src.iterdir() |
| 1342 | + dst.mkdir() |
| 1343 | + # feed through dict.fromkeys to remove duplicates |
| 1344 | + for child in dict.fromkeys(children): |
| 1345 | + stack.append((child, dst.joinpath(child.name))) |
| 1346 | + else: |
| 1347 | + ensure_different_files(src, dst) |
| 1348 | + with vfsopen(src, "rb") as source_f: |
| 1349 | + with vfsopen(dst, "wb") as target_f: |
| 1350 | + copyfileobj(source_f, target_f) |
1311 | 1351 |
|
1312 | 1352 | # --- WritablePath attributes ------------------------------------- |
1313 | 1353 |
|
|
0 commit comments