[pypy-svn] pypy default: Implement os.mkdir with the Win32 API

amauryfa commits-noreply at bitbucket.org
Thu Jan 20 19:36:50 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r41070:8cf11c9e2892
Date: 2011-01-20 17:05 +0100
http://bitbucket.org/pypy/pypy/changeset/8cf11c9e2892/

Log:	Implement os.mkdir with the Win32 API

diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -73,6 +73,7 @@
     charp2str = staticmethod(rffi.charp2str)
     str2charp = staticmethod(rffi.str2charp)
     free_charp = staticmethod(rffi.free_charp)
+    scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
 
     @staticmethod
     def posix_function_name(name):
@@ -89,6 +90,7 @@
     charp2str = staticmethod(rffi.wcharp2unicode)
     str2charp = staticmethod(rffi.unicode2wcharp)
     free_charp = staticmethod(rffi.free_wcharp)
+    scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
 
     @staticmethod
     def posix_function_name(name):
@@ -1292,24 +1294,25 @@
 
     @registering_str_unicode(os.mkdir)
     def register_os_mkdir(self, traits):
-        if os.name == 'nt':
-            ARG2 = []         # no 'mode' argument on Windows - just ignored
+        os_mkdir = self.llexternal(traits.posix_function_name('mkdir'),
+                                   [traits.CCHARP, rffi.MODE_T], rffi.INT)
+
+        if sys.platform == 'win32':
+            from pypy.rpython.module.ll_win32file import make_win32_traits
+            win32traits = make_win32_traits(traits)
+
+            @func_renamer('mkdir_llimpl_%s' % traits.str.__name__)
+            def os_mkdir_llimpl(path, mode):
+                if not win32traits.CreateDirectory(path, None):
+                    raise rwin32.lastWindowsError()
         else:
-            ARG2 = [rffi.MODE_T]
-        os_mkdir = self.llexternal(traits.posix_function_name('mkdir'),
-                                   [traits.CCHARP] + ARG2, rffi.INT)
-        IGNORE_MODE = len(ARG2) == 0
+            def os_mkdir_llimpl(pathname, mode):
+                res = os_mkdir(pathname, mode)
+                res = rffi.cast(lltype.Signed, res)
+                if res < 0:
+                    raise OSError(rposix.get_errno(), "os_mkdir failed")
 
-        def mkdir_llimpl(pathname, mode):
-            if IGNORE_MODE:
-                res = os_mkdir(pathname)
-            else:
-                res = os_mkdir(pathname, mode)
-            res = rffi.cast(lltype.Signed, res)
-            if res < 0:
-                raise OSError(rposix.get_errno(), "os_mkdir failed")
-
-        return extdef([traits.str, int], s_None, llimpl=mkdir_llimpl,
+        return extdef([traits.str, int], s_None, llimpl=os_mkdir_llimpl,
                       export_name=traits.ll_os_name('mkdir'))
 
     @registering_str_unicode(os.rmdir)

diff --git a/pypy/rpython/module/ll_win32file.py b/pypy/rpython/module/ll_win32file.py
--- a/pypy/rpython/module/ll_win32file.py
+++ b/pypy/rpython/module/ll_win32file.py
@@ -139,6 +139,11 @@
             [traits.CCHARP],
             rwin32.BOOL)
 
+        CreateDirectory = external(
+            'CreateDirectory' + suffix,
+            [traits.CCHARP, rffi.VOIDP],
+            rwin32.BOOL)
+
         SetEnvironmentVariable = external(
             'SetEnvironmentVariable' + suffix,
             [traits.CCHARP, traits.CCHARP],
@@ -232,14 +237,14 @@
         if not win32traits.SetCurrentDirectory(path):
             raise rwin32.lastWindowsError()
 
-        with rffi.scoped_alloc_buffer(rwin32.MAX_PATH) as path:
+        with traits.scoped_alloc_buffer(rwin32.MAX_PATH) as path:
             res = win32traits.GetCurrentDirectory(rwin32.MAX_PATH + 1, path.raw)
             if not res:
                 raise rwin32.lastWindowsError()
             if res <= rwin32.MAX_PATH + 1:
                 new_path = path.str(rffi.cast(lltype.Signed, res))
             else:
-                with rffi.scoped_alloc_buffer(rwin32.MAX_PATH) as path:
+                with traits.scoped_alloc_buffer(rwin32.MAX_PATH) as path:
                     res = win32traits.GetCurrentDirectory(res, path.raw)
                     if not res:
                         raise rwin32.lastWindowsError()

diff --git a/pypy/rpython/module/test/test_ll_os.py b/pypy/rpython/module/test/test_ll_os.py
--- a/pypy/rpython/module/test/test_ll_os.py
+++ b/pypy/rpython/module/test/test_ll_os.py
@@ -82,6 +82,14 @@
     finally:
         os.chdir(pwd)
 
+def test_mkdir():
+    filename = str(udir.join('test_mkdir.dir'))
+    getllimpl(os.mkdir)(filename, 0)
+    exc = raises(OSError, getllimpl(os.mkdir), filename, 0)
+    assert exc.value.errno == errno.EEXIST
+    if sys.platform == 'win32':
+        assert exc.type is WindowsError
+
 def test_strerror():
     data = getllimpl(os.strerror)(2)
     assert data == os.strerror(2)


More information about the Pypy-commit mailing list