-
-
Notifications
You must be signed in to change notification settings - Fork 29.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support moving across filesystems in pathlib.Path, as shutil.move() does #73991
Comments
|
Trying to use Pathlib and Path.replace on Windows if drive are different leads to an issue: This is a known situation of os.rename, and workaround I found is to use shutil or to copy/delete manually in two steps (e.g. http://stackoverflow.com/questions/21116510/python-oserror-winerror-17-the-system-cannot-move-the-file-to-a-different-d) When using Pathlib, it's not that easy to workaround using shutil (even if thanks to Brett Cannon now shutil accepts Path in Py3.6, not everybody has Py3.6). At least this should be documented with a recommendation for that situation. I love Pathlib and it's too bad my code becomes complicated when it was so simple :( |
|
Just to confirm, I was able to workaround it with Py3.6: # client_generated_path.replace(destination_folder)
shutil.move(client_generated_path, destination_folder)It is reasonable to think about adding a similar feature to pathlib if it doesn't support it and just special-case the drive-to-drive scenario for Windows |
|
Moving a file across volumes isn't atomic. Getting an exception in this case can be useful. There could be a "strict" keyword-only parameter that defaults to False. If it's true, then replace() won't try to move the file. |
|
I agree this needs to be different from replace(), due to not being atomic. That makes it an enhancement, so I'm removing 3.5. I'm +1 on Path supporting something like shutil.move(). |
|
I also support the idea of getting something like shutil.move() into pathlib. |
|
I should also mention that rename() (https://docs.python.org/3/library/pathlib.html#pathlib.Path.rename) and replace() (https://docs.python.org/3/library/pathlib.html#pathlib.Path.replace) already do exist, so it might be best to add a keyword-only flag to one of those for this use-case. |
|
I'm also +1 on adding def move(src, dst, copy_function=copy2):
return pathlib.Path(src).move(dst, copy_function=copy2)I'm interested in this approach because I'm hoping to add a To achieve this we'd need to make pathlib accept We'd also need to move other shutil functions that On |
Sounds reasonable to me, though would we want to include |
|
I think @barneygale 's plan is sound. |
|
I agree with @zooba, exposing the |
|
I agree about def copy(self, dst, *, follow_symlinks=True, copy_mode=True, copy_stat=False):
...
def move(self, dst, *, atomic=False, **kwargs):
if atomic:
return os.rename(self, dst)
self.copy(dst, **kwargs)
self.unlink() |
|
I don't like the For example, on Windows we explicitly disallow If we were to define semantics for We should make these functions an improvement in semantics, not just discoverability, and ideally more appropriate for whatever platform they're being used on than the POSIX semantics inherent to posixmodule. So I think the only option we want on Similarly, I think we should simplify Footnotes
|
|
My example was a bit rubbish - here's a corrected version: def copy(self, dst, *, follow_symlinks=True, copy_mode=True, copy_stat=True):
...
def move(self, dst, *, atomic=False, **kwargs):
try:
return os.rename(self, dst)
except OSError:
if atomic:
raise # Move can't be achieved atomically
self.copy(dst, **kwargs)
self.unlink()So I think I agree with you on removing copy_mode and copy_stat. |
|
I suppose one could argue that folks should just use |
Yeah, I'll argue that one ;) We'll have to explain that |
|
Should we deprecate |
…thon#121444) Follow-up to python#120806. Use `os_helper.skip_unless_xattr` to skip testing xattr preservation when unsupported.
Add a `Path.copy()` method that copies the content of one file to another. This method is similar to `shutil.copyfile()` but differs in the following ways: - Uses `fcntl.FICLONE` where available (see pythonGH-81338) - Uses `os.copy_file_range` where available (see pythonGH-81340) - Uses `_winapi.CopyFile2` where available, even though this copies more metadata than the other implementations. This makes `WindowsPath.copy()` more similar to `shutil.copy2()`. The method is presently _less_ specified than the `shutil` functions to allow OS-specific optimizations that might copy more or less metadata. Incorporates code from pythonGH-81338 and pythonGH-93152. Co-authored-by: Eryk Sun <eryksun@gmail.com>
…ython#120517) Preparatory work for moving `_rmtree_unsafe()` and `_rmtree_safe_fd()` to `pathlib._os` so that they can be used from both `shutil` and `pathlib`. Move implementation-specific setup from `rmtree()` into the safe/unsafe functions, and give them the same signature `(path, dir_fd, onexc)`. In the tests, mock `os.open` rather than `_rmtree_safe_fd()` to ensure the FD-based walk is used, and replace a couple references to `shutil._use_fd_functions` with `shutil.rmtree.avoids_symlink_attacks` (which has the same value). No change of behaviour.
…r()` (python#120715) In preparation for the addition of `PathBase.rmtree()`, implement `DummyPath.unlink()` and `rmdir()`, and move corresponding tests into `test_pathlib_abc` so they're run against `DummyPath`.
…python#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.
Add `pathlib.Path.copytree()` method, which recursively copies one directory to another. This differs from `shutil.copytree()` in the following respects: 1. Our method has a *follow_symlinks* argument, whereas shutil's has a *symlinks* argument with an inverted meaning. 2. Our method lacks something like a *copy_function* argument. It always uses `Path.copy()` to copy files. 3. Our method lacks something like a *ignore_dangling_symlinks* argument. Instead, users can filter out danging symlinks with *ignore*, or ignore exceptions with *on_error* 4. Our *ignore* argument is a callable that accepts a single path object, whereas shutil's accepts a path and a list of child filenames. 5. We add an *on_error* argument, which is a callable that accepts an `OSError` instance. (`Path.walk()` also accepts such a callable). Co-authored-by: Nice Zombies <nineteendo19d0@gmail.com>
…ython#120807) Check for `ERROR_INVALID_PARAMETER` when calling `_winapi.CopyFile2()` and raise `UnsupportedOperation`. In `Path.copy()`, handle this exception and fall back to the `PathBase.copy()` implementation.
…ython#120806) Add *preserve_metadata* keyword-only argument to `pathlib.Path.copy()`, defaulting to false. When set to true, we copy timestamps, permissions, extended attributes and flags where available, like `shutil.copystat()`. The argument has no effect on Windows, where metadata is always copied. Internally (in the pathlib ABCs), path types gain `_readable_metadata` and `_writable_metadata` attributes. These sets of strings describe what kinds of metadata can be retrieved and stored. We take an intersection of `source._readable_metadata` and `target._writable_metadata` to minimise reads/writes. A new `_read_metadata()` method accepts a set of metadata keys and returns a dict with those keys, and a new `_write_metadata()` method accepts a dict of metadata. We *might* make these public in future, but it's hard to justify while the ABCs are still private.
…thon#121444) Follow-up to python#120806. Use `os_helper.skip_unless_xattr` to skip testing xattr preservation when unsupported.
Add a `Path.rmtree()` method that removes an entire directory tree, like `shutil.rmtree()`. The signature of the optional *on_error* argument matches the `Path.walk()` argument of the same name, but differs from the *onexc* and *onerror* arguments to `shutil.rmtree()`. Consistency within pathlib is probably more important. In the private pathlib ABCs, we add an implementation based on `walk()`. Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
…121438) Add *preserve_metadata* keyword-only argument to `pathlib.Path.copytree()`, defaulting to false. When set to true, we copy timestamps, permissions, extended attributes and flags where available, like `shutil.copystat()`.
Add a `Path.move()` method that moves a file or directory tree and returns a new `Path` instance. This method is similar to `shutil.move()`, except that it doesn't accept a *copy_function* argument, and it doesn't support copying into an existing directory.
Add a `Path.move()` method that moves a file or directory tree and returns a new `Path` instance. This method is similar to `shutil.move()`, except that it doesn't accept a *copy_function* argument, and it doesn't support copying into an existing directory.
|
I've been closely following the
(new methods shown in italics) Having given it some thought, I have the following concerns:
And so I'd like to propose that:
This would result in:
Thoughts? |
|
(Also, if we wanted to add support for moving/copying into an existing directory via new methods, it would be better to have |
|
+1 from me on the revised names and the Do we even need a |
Good point - perhaps not! |
Rename `pathlib.Path.rmtree()` to `delete()`, and add support for deleting non-directories. This simplifies the interface for users, and nicely complements the upcoming `move()` and `copy()` methods (which will also accept any type of file.)
Rename `pathlib.Path.copy()` to `_copy_file()` (i.e. make it private.) Rename `pathlib.Path.copytree()` to `copy()`, and add support for copying non-directories. This simplifies the interface for users, and nicely complements the upcoming `move()` and `delete()` methods (which will also accept any type of file.)
Rename `pathlib.Path.rmtree()` to `delete()`, and add support for deleting non-directories. This simplifies the interface for users, and nicely complements the upcoming `move()` and `copy()` methods (which will also accept any type of file.)
Rename `pathlib.Path.copy()` to `_copy_file()` (i.e. make it private.) Rename `pathlib.Path.copytree()` to `copy()`, and add support for copying non-directories. This simplifies the interface for users, and nicely complements the upcoming `move()` and `delete()` methods (which will also accept any type of file.) Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs
pathlib.Path.copy()#119058pathlib.Path.rmtree()#119060os.copy()and friends #119079shutil._rmtree_[un]safe(). #120517pathlib.Path.copy()#120519DummyPath.unlink()andrmdir()#120715pathlib.Path.copytree()#120718pathlib.Path.copy()#120806pathlib.Path.copytree()#121438pathlib.Path.move()#122073pathlib.Path.rmtree()intodelete()#122368pathlib.Path.copytree()intocopy()#122369pathlib.Path.copy()#122924The text was updated successfully, but these errors were encountered: