Author eryksun
Recipients asvetlov, docs@python, eryksun, pitrou, r.david.murray
Date 2016-08-28.22:56:52
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1472425013.11.0.713050633245.issue27886@psf.upfronthosting.co.za>
In-reply-to
Content
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
History
Date User Action Args
2021-03-12 23:55:59eryksununlinkissue27886 messages
2016-08-28 22:56:53eryksunsetrecipients: + eryksun, pitrou, r.david.murray, asvetlov, docs@python
2016-08-28 22:56:53eryksunsetmessageid: <1472425013.11.0.713050633245.issue27886@psf.upfronthosting.co.za>
2016-08-28 22:56:53eryksunlinkissue27886 messages
2016-08-28 22:56:52eryksuncreate