[Python-Dev] [Python-checkins] cpython: Issue #8828: Add new function os.replace(), for cross-platform renaming with (original) (raw)
Brett Cannon brett at python.org
Mon Jan 30 22:26:30 CET 2012
- Previous message: [Python-Dev] Release cycle question
- Next message: [Python-Dev] cpython: Issue #8828: Add new function os.replace(), for cross-platform renaming with
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Should this end up being used in importlib through _os?
On Mon, Jan 30, 2012 at 16:11, antoine.pitrou <python-checkins at python.org>wrote:
http://hg.python.org/cpython/rev/80ddbd822227 changeset: 74689:80ddbd822227 user: Antoine Pitrou <solipsis at pitrou.net> date: Mon Jan 30 22:08:52 2012 +0100 summary: Issue #8828: Add new function os.replace(), for cross-platform renaming with overwriting.
files: Doc/library/os.rst | 18 +++++++++- Lib/test/testos.py | 12 ++++++ Misc/NEWS | 3 + Modules/posixmodule.c | 55 +++++++++++++++++++++--------- 4 files changed, 69 insertions(+), 19 deletions(-)
diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1889,8 +1889,9 @@ Unix flavors if src and dst are on different filesystems. If successful, the renaming will be an atomic operation (this is a POSIX requirement). On Windows, if dst already exists, :exc:
OSError
will be raised even if it is a - file; there may be no way to implement an atomic rename when dst names an - existing file. + file. + + If you want cross-platform overwriting of the destination, use :func:replace
. Availability: Unix, Windows. @@ -1908,6 +1909,19 @@ permissions needed to remove the leaf directory or file. +.. function:: replace(src, dst) + + Rename the file or directory src to dst. If dst is a directory, + :exc:OSError
will be raised. If dst exists and is a file, it will + be replaced silently if the user has permission. The operation may fail + if src and dst are on different filesystems. If successful, + the renaming will be an atomic operation (this is a POSIX requirement). + + Availability: Unix, Windows + + .. versionadded:: 3.3 + + .. function:: rmdir(path) Remove (delete) the directory path. Only works when the directory is diff --git a/Lib/test/testos.py b/Lib/test/testos.py --- a/Lib/test/testos.py +++ b/Lib/test/testos.py @@ -129,6 +129,18 @@ self.fdopenhelper('r') self.fdopenhelper('r', 100) + def testreplace(self): + TESTFN2 = support.TESTFN + ".2" + with open(support.TESTFN, 'w') as f: + f.write("1") + with open(TESTFN2, 'w') as f: + f.write("2") + self.addCleanup(os.unlink, TESTFN2) + os.replace(support.TESTFN, TESTFN2) + self.assertRaises(FileNotFoundError, os.stat, support.TESTFN) + with open(TESTFN2, 'r') as f: + self.assertEqual(f.read(), "1") + # Test attributes on return values from os.stat family. class StatAttributeTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -463,6 +463,9 @@ Library ------- +- Issue #8828: Add new function os.replace(), for cross-platform renaming + with overwriting. + - Issue #13848: open() and the FileIO constructor now check for NUL characters in the file name. Patch by Hynek Schlawack. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3280,17 +3280,16 @@ #endif /* HAVESETPRIORITY */ -PyDocSTRVAR(posixrename_doc,_ -"rename(old, new)\n\n_ -Rename a file or directory."); - -static PyObject * -posixrename(PyObject *self, PyObject *args) +static PyObject * +internalrename(PyObject *self, PyObject *args, int isreplace) { #ifdef MSWINDOWS PyObject *src, *dst; BOOL result; - if (PyArgParseTuple(args, "UU:rename", &src, &dst)) + int flags = isreplace ? MOVEFILEREPLACEEXISTING : 0; + if (PyArgParseTuple(args, + isreplace ? "UU:replace" : "UU:rename", + &src, &dst)) { wchart *wsrc, *wdst; @@ -3301,16 +3300,17 @@ if (wdst == NULL) return NULL; PyBEGINALLOWTHREADS - result = MoveFileW(wsrc, wdst); + result = MoveFileExW(wsrc, wdst, flags); PyENDALLOWTHREADS if (!result) - return win32error("rename", NULL); + return win32error(isreplace ? "replace" : "rename", NULL); PyINCREF(PyNone); return PyNone; } else { PyErrClear(); - if (!PyArgParseTuple(args, "O&O&:rename", + if (!PyArgParseTuple(args, + isreplace ? "O&O&:replace" : "O&O&:rename", PyUnicodeFSConverter, &src, PyUnicodeFSConverter, &dst)) return NULL; @@ -3319,15 +3319,15 @@ goto error; PyBEGINALLOWTHREADS - result = MoveFileA(PyBytesASSTRING(src), - PyBytesASSTRING(dst)); + result = MoveFileExA(PyBytesASSTRING(src), + PyBytesASSTRING(dst), flags); PyENDALLOWTHREADS PyXDECREF(src); PyXDECREF(dst); if (!result) - return win32error("rename", NULL); + return win32error(isreplace ? "replace" : "rename", NULL); PyINCREF(PyNone); return PyNone; @@ -3337,10 +3337,30 @@ return NULL; } #else - return posix2str(args, "O&O&:rename", rename); -#endif -} - + return posix2str(args, + isreplace ? "O&O&:replace" : "O&O&:rename", rename); +#endif +} + +PyDocSTRVAR(posixrename_doc, +"rename(old, new)\n\n_ +Rename a file or directory."); + +static PyObject * +posixrename(PyObject *self, PyObject *args) +{ + return internalrename(self, args, 0); +} + +PyDocSTRVAR(posixreplace_doc, +"replace(old, new)\n\n_ +Rename a file or directory, overwriting the destination."); + +static PyObject * +posixreplace(PyObject *self, PyObject *args) +{ + return internalrename(self, args, 1); +} PyDocSTRVAR(posixrmdir_doc, "rmdir(path)\n\n_ @@ -10555,6 +10575,7 @@ {"readlink", winreadlink, METHVARARGS, winreadlink_doc}, #endif /* !defined(HAVEREADLINK) && defined(MSWINDOWS) */ {"rename", posixrename, METHVARARGS, posixrename_doc},_ + {"replace", posixreplace, METHVARARGS, posixreplace_doc},_ {"rmdir", posixrmdir, METHVARARGS, posixrmdir_doc},_ {"stat", posixstat, METHVARARGS, posixstat_doc},_ {"statfloattimes", statfloattimes, METHVARARGS, statfloattimes_doc},_ -- Repository URL: http://hg.python.org/cpython
Python-checkins mailing list Python-checkins at python.org http://mail.python.org/mailman/listinfo/python-checkins -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-dev/attachments/20120130/8a10acf4/attachment-0001.html>
- Previous message: [Python-Dev] Release cycle question
- Next message: [Python-Dev] cpython: Issue #8828: Add new function os.replace(), for cross-platform renaming with
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]