Message273845
Having rename() in pathlib is fine as long as it links to the os docs. This probably needs a new issue, but I do see room for improvement in the latter.
For Unix, the os.rename and os.replace docs should clarify that an empty destination directory can be replaced by another directory. For example:
>>> os.mkdir('foo1')
>>> os.mkdir('foo2')
>>> os.rename('foo1', 'foo2')
The specification of rename [1] states that "[i]f the *old* argument points to the pathname of a directory, the *new* argument shall not point to the pathname of a file that is not a directory". It further specifies that "[i]f *new* names an existing directory, it shall be required to be an empty directory". Windows, on the other hand, doesn't allow replacing a directory, even an empty one. The wording for os.rename and os.replace could be changed to something like: "[i]f dst is a directory, OSError will be raised, except not on Unix if src is a directory and dst is empty".
Windows MoveFileEx calls NtSetInformationFile to set the FileRenameInformation [2]. The MSDN docs do not explicitly require that the operation is atomic, unlike POSIX rename. I think it's a reasonable expectation that a Windows filesystem should rename atomically, and that's probably the case. However, it should be clear that only Unix guarantees this, e.g. "[i]f successful, on Unix the renaming will be an atomic operation, as required by POSIX".
MSDN claims that a rename will fail in the following cases:
A file or directory can only be renamed within a volume.
Even if ReplaceIfExists is set to TRUE, the rename operation
will still fail if a file with the same name already exists
and is a directory, a read-only file, or a currently
executing file.
A file cannot be renamed if it has any open handles, unless it
is only open because of a batch opportunistic lock (oplock)
and the batch oplock can be broken immediately.
A file cannot be renamed if a file with the same name exists
and has open handles (except in the batch-oplock case
described earlier).
A directory cannot be renamed if it or any of its
subdirectories contains a file that has open handles (except
in the batch-oplock case described earlier).
For the third case, actually an open file can be renamed if delete/rename access is shared. For example:
>>> with open('foo1', 'w') as f: f.write('foo1')
...
4
Open the file with shared delete access:
>>> SHARE_ALL = 7
>>> _winapi.CreateFile('foo1', 0x80000000, SHARE_ALL, 0, 3, 0, 0)
224
and rename/replace succeeds:
>>> os.replace('foo1', 'foo2')
>>> open('foo2').read()
'foo1'
Anyway, the os.replace docs could state in general that: "[o]n Windows, a PermissionError will be raised if dst is a read-only file, or if either src or dst is currently open, or if src is a directory with an open file".
[1]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html
[2]: https://msdn.microsoft.com/en-us/library/ff540344 |
|
Date |
User |
Action |
Args |
2021-03-12 23:55:59 | eryksun | unlink | issue27886 messages |
2016-08-28 22:56:53 | eryksun | set | recipients:
+ eryksun, pitrou, r.david.murray, asvetlov, docs@python |
2016-08-28 22:56:53 | eryksun | set | messageid: <1472425013.11.0.713050633245.issue27886@psf.upfronthosting.co.za> |
2016-08-28 22:56:53 | eryksun | link | issue27886 messages |
2016-08-28 22:56:52 | eryksun | create | |
|