[pypy-commit] pypy py3k: add replace() for win32

mattip pypy.commits at gmail.com
Fri May 20 12:50:45 EDT 2016


Author: Matti Picus <matti.picus at gmail.com>
Branch: py3k
Changeset: r84536:0fadbd4f5524
Date: 2016-05-20 18:23 +0300
http://bitbucket.org/pypy/pypy/changeset/0fadbd4f5524/

Log:	add replace() for win32 (grafted from
	54617a9d23bb8b70763929b214ab24eba547ccc3)

diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -1045,15 +1045,23 @@
         win32traits = make_win32_traits(traits)
         path1 = traits.as_str0(path1)
         path2 = traits.as_str0(path2)
-        if not win32traits.MoveFile(path1, path2):
+        if not win32traits.MoveFileEx(path1, path2, 0):
             raise rwin32.lastSavedWindowsError()
 
 @specialize.argtype(0, 1)
 def replace(path1, path2):
-    if os.name == 'nt':
-        raise NotImplementedError(
-            'On windows, os.replace() should overwrite the destination')
-    return rename(path1, path2)
+    if _WIN32:
+        traits = _preferred_traits(path1)
+        win32traits = make_win32_traits(traits)
+        path1 = traits.as_str0(path1)
+        path2 = traits.as_str0(path2)
+        ret = win32traits.MoveFileEx(path1, path2,
+                     win32traits.MOVEFILE_REPLACE_EXISTING)
+        if not ret:
+            raise rwin32.lastSavedWindowsError()
+    else:
+        ret = rename(path1, path2)
+    return ret
 
 #___________________________________________________________________
 
diff --git a/rpython/rlib/rwin32file.py b/rpython/rlib/rwin32file.py
--- a/rpython/rlib/rwin32file.py
+++ b/rpython/rlib/rwin32file.py
@@ -45,6 +45,8 @@
             'INVALID_FILE_ATTRIBUTES')
         ERROR_SHARING_VIOLATION = platform.ConstantInteger(
             'ERROR_SHARING_VIOLATION')
+        MOVEFILE_REPLACE_EXISTING = platform.ConstantInteger(
+            'MOVEFILE_REPLACE_EXISTING')
         _S_IFDIR = platform.ConstantInteger('_S_IFDIR')
         _S_IFREG = platform.ConstantInteger('_S_IFREG')
         _S_IFCHR = platform.ConstantInteger('_S_IFCHR')
@@ -103,7 +105,7 @@
                        FILE_WRITE_ATTRIBUTES OPEN_EXISTING FILE_FLAG_BACKUP_SEMANTICS
                        VOLUME_NAME_DOS VOLUME_NAME_NT
                        ERROR_FILE_NOT_FOUND ERROR_NO_MORE_FILES
-                       ERROR_SHARING_VIOLATION
+                       ERROR_SHARING_VIOLATION MOVEFILE_REPLACE_EXISTING
                     '''.split():
             locals()[name] = config[name]
         LPWIN32_FIND_DATA    = lltype.Ptr(WIN32_FIND_DATA)
@@ -199,9 +201,9 @@
             rwin32.BOOL,
             save_err=rffi.RFFI_SAVE_LASTERROR)
 
-        MoveFile = external(
-            'MoveFile' + suffix,
-            [traits.CCHARP, traits.CCHARP],
+        MoveFileEx = external(
+            'MoveFileEx' + suffix,
+            [traits.CCHARP, traits.CCHARP, rwin32.DWORD],
             rwin32.BOOL,
             save_err=rffi.RFFI_SAVE_LASTERROR)
 
diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py
--- a/rpython/rlib/test/test_rposix.py
+++ b/rpython/rlib/test/test_rposix.py
@@ -334,6 +334,11 @@
             self.path  = UnicodeWithEncoding(self.ufilename)
             self.path2 = UnicodeWithEncoding(self.ufilename + ".new")
 
+    def _teardown_method(self, method):
+        for path in [self.ufilename + ".new", self.ufilename]:
+            if os.path.exists(path):
+                os.unlink(path)
+
     def test_open(self):
         def f():
             try:
@@ -390,6 +395,14 @@
         assert not os.path.exists(self.ufilename)
         assert os.path.exists(self.ufilename + '.new')
 
+    def test_replace(self):
+        def f():
+            return rposix.replace(self.path, self.path2)
+
+        interpret(f, [])
+        assert not os.path.exists(self.ufilename)
+        assert os.path.exists(self.ufilename + '.new')
+
     def test_listdir(self):
         udir = UnicodeWithEncoding(os.path.dirname(self.ufilename))
 


More information about the pypy-commit mailing list