[pypy-commit] pypy more-rposix: os.getcwd() and os.getcwdu()

amauryfa noreply at buildbot.pypy.org
Fri Nov 7 22:37:16 CET 2014


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: more-rposix
Changeset: r74389:abe22db32a60
Date: 2014-11-07 22:08 +0100
http://bitbucket.org/pypy/pypy/changeset/abe22db32a60/

Log:	os.getcwd() and os.getcwdu()

diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -243,11 +243,24 @@
             return True
         else:
             return path.is_unicode
+
+    @specialize.argtype(0)
+    def _preferred_traits(path):
+        from rpython.rtyper.module.support import StringTraits, UnicodeTraits
+        if _prefer_unicode(path):
+            return UnicodeTraits()
+        else:
+            return StringTraits()
 else:
     @specialize.argtype(0)
     def _prefer_unicode(path):
         return False
 
+    @specialize.argtype(0)
+    def _preferred_traits(path):
+        from rpython.rtyper.module.support import StringTraits
+        return StringTraits()
+    
 @specialize.argtype(0)
 def stat(path):
     return os.stat(_as_bytes(path))
@@ -454,6 +467,65 @@
         error = c_access(_as_bytes0(path), mode)
     return error == 0
 
+# This Win32 function is not exposed via os, but needed to get a
+# correct implementation of os.path.abspath.
+ at specialize.argtype(0)
+def getfullpathname(path):
+    length = rwin32.MAX_PATH + 1
+    traits = _get_preferred_traits(path)
+    with traits.scoped_alloc_buffer(count) as buf:
+        res = win32traits.GetFullPathName(
+            path, rffi.cast(rwin32.DWORD, length),
+            buf.raw, lltype.nullptr(win32traits.LPSTRP.TO))
+        if res == 0:
+            raise rwin32.lastWindowsError("_getfullpathname failed")
+        return buf.str()
+
+c_getcwd = external(UNDERSCORE_ON_WIN32 + 'getcwd',
+                    [rffi.CCHARP, rffi.SIZE_T], rffi.CCHARP)
+c_wgetcwd = external(UNDERSCORE_ON_WIN32 + 'wgetcwd',
+                     [rffi.CWCHARP, rffi.SIZE_T], rffi.CWCHARP)
+
+ at replace_os_function('getcwd')
+def getcwd():
+    bufsize = 256
+    while True:
+        buf = lltype.malloc(rffi.CCHARP.TO, bufsize, flavor='raw')
+        res = c_getcwd(buf, bufsize)
+        if res:
+            break   # ok
+        error = get_errno()
+        lltype.free(buf, flavor='raw')
+        if error != errno.ERANGE:
+            raise OSError(error, "getcwd failed")
+        # else try again with a larger buffer, up to some sane limit
+        bufsize *= 4
+        if bufsize > 1024*1024:  # xxx hard-coded upper limit
+            raise OSError(error, "getcwd result too large")
+    result = rffi.charp2str(res)
+    lltype.free(buf, flavor='raw')
+    return result
+
+ at replace_os_function('getcwdu')
+def getcwdu():
+    bufsize = 256
+    while True:
+        buf = lltype.malloc(rffi.CWCHARP.TO, bufsize, flavor='raw')
+        res = c_wgetcwd(buf, bufsize)
+        if res:
+            break   # ok
+        error = rposix.get_errno()
+        lltype.free(buf, flavor='raw')
+        if error != errno.ERANGE:
+            raise OSError(error, "getcwd failed")
+        # else try again with a larger buffer, up to some sane limit
+        bufsize *= 4
+        if bufsize > 1024*1024:  # xxx hard-coded upper limit
+            raise OSError(error, "getcwd result too large")
+    result = rffi.wcharp2unicode(res)
+    lltype.free(buf, flavor='raw')
+    return result
+
 #___________________________________________________________________
 
 c_execv = external('execv', [rffi.CCHARP, rffi.CCHARPP], rffi.INT)
@@ -680,16 +752,9 @@
         handle_posix_error('utime', error)
     else:  # _WIN32 case
         from rpython.rlib.rwin32file import make_win32_traits
-        if _prefer_unicode(path):
-            # XXX remove dependency on rtyper.module.  The "traits"
-            # are just used for CreateFile anyway.
-            from rpython.rtyper.module.support import UnicodeTraits
-            win32traits = make_win32_traits(UnicodeTraits())
-            path = _as_unicode0(path)
-        else:
-            from rpython.rtyper.module.support import StringTraits
-            win32traits = make_win32_traits(StringTraits())
-            path = _as_bytes0(path)
+        traits = _preferred_traits(path)
+        win32traits = make_win32_traits(traits)
+        path = traits.as_str0(path)
         hFile = win32traits.CreateFile(path,
                            win32traits.FILE_WRITE_ATTRIBUTES, 0,
                            None, win32traits.OPEN_EXISTING,
diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py
--- a/rpython/rtyper/module/ll_os.py
+++ b/rpython/rtyper/module/ll_os.py
@@ -173,75 +173,6 @@
                 separate_module_sources = ["\n".join(defs)]
             ))
 
-    @registering_str_unicode(getattr(posix, '_getfullpathname', None),
-                             condition=sys.platform=='win32')
-    def register_posix__getfullpathname(self, traits):
-        # this nt function is not exposed via os, but needed
-        # to get a correct implementation of os.path.abspath
-        from rpython.rtyper.module.ll_win32file import make_getfullpathname_impl
-        getfullpathname_llimpl = make_getfullpathname_impl(traits)
-
-        return extdef([traits.str0],  # a single argument which is a str
-                      traits.str0,    # returns a string
-                      traits.ll_os_name('_getfullpathname'),
-                      llimpl=getfullpathname_llimpl)
-
-    @registering(os.getcwd)
-    def register_os_getcwd(self):
-        os_getcwd = self.llexternal(UNDERSCORE_ON_WIN32 + 'getcwd',
-                                    [rffi.CCHARP, rffi.SIZE_T],
-                                    rffi.CCHARP)
-
-        def os_getcwd_llimpl():
-            bufsize = 256
-            while True:
-                buf = lltype.malloc(rffi.CCHARP.TO, bufsize, flavor='raw')
-                res = os_getcwd(buf, rffi.cast(rffi.SIZE_T, bufsize))
-                if res:
-                    break   # ok
-                error = rposix.get_errno()
-                lltype.free(buf, flavor='raw')
-                if error != errno.ERANGE:
-                    raise OSError(error, "getcwd failed")
-                # else try again with a larger buffer, up to some sane limit
-                bufsize *= 4
-                if bufsize > 1024*1024:  # xxx hard-coded upper limit
-                    raise OSError(error, "getcwd result too large")
-            result = rffi.charp2str(res)
-            lltype.free(buf, flavor='raw')
-            return result
-
-        return extdef([], str0,
-                      "ll_os.ll_os_getcwd", llimpl=os_getcwd_llimpl)
-
-    @registering(os.getcwdu, condition=sys.platform=='win32')
-    def register_os_getcwdu(self):
-        os_wgetcwd = self.llexternal(UNDERSCORE_ON_WIN32 + 'wgetcwd',
-                                     [rffi.CWCHARP, rffi.SIZE_T],
-                                     rffi.CWCHARP)
-
-        def os_getcwd_llimpl():
-            bufsize = 256
-            while True:
-                buf = lltype.malloc(rffi.CWCHARP.TO, bufsize, flavor='raw')
-                res = os_wgetcwd(buf, rffi.cast(rffi.SIZE_T, bufsize))
-                if res:
-                    break   # ok
-                error = rposix.get_errno()
-                lltype.free(buf, flavor='raw')
-                if error != errno.ERANGE:
-                    raise OSError(error, "getcwd failed")
-                # else try again with a larger buffer, up to some sane limit
-                bufsize *= 4
-                if bufsize > 1024*1024:  # xxx hard-coded upper limit
-                    raise OSError(error, "getcwd result too large")
-            result = rffi.wcharp2unicode(res)
-            lltype.free(buf, flavor='raw')
-            return result
-
-        return extdef([], unicode,
-                      "ll_os.ll_os_wgetcwd", llimpl=os_getcwd_llimpl)
-
     @registering_str_unicode(os.listdir)
     def register_os_listdir(self, traits):
         # we need a different approach on Windows and on Posix
diff --git a/rpython/rtyper/module/support.py b/rpython/rtyper/module/support.py
--- a/rpython/rtyper/module/support.py
+++ b/rpython/rtyper/module/support.py
@@ -2,6 +2,7 @@
 
 from rpython.annotator import model as annmodel
 from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib.objectmodel import specialize
 
 _WIN32 = sys.platform.startswith('win')
 UNDERSCORE_ON_WIN32 = '_' if _WIN32 else ''
@@ -63,6 +64,22 @@
     def ll_os_name(name):
         return 'll_os.ll_os_' + name
 
+    @classmethod
+    @specialize.argtype(1)
+    def as_str(cls, path):
+        assert path is not None
+        if isinstance(path, unicode):
+            return path
+        else:
+            return path.as_unicode()
+    
+    @classmethod
+    @specialize.argtype(1)
+    def as_str0(cls, path):
+        res = cls.as_str(path)
+        rstring.check_str0(res)
+        return res
+
 class UnicodeTraits:
     str = unicode
     str0 = annmodel.s_Unicode0
@@ -83,6 +100,24 @@
     def ll_os_name(name):
         return 'll_os.ll_os_w' + name
 
+    @classmethod
+    def as_str(cls, path):
+        assert path is not None
+        if isinstance(path, str):
+            return path
+        elif isinstance(path, unicode):
+            # This never happens in PyPy's Python interpreter!
+            # Only in raw RPython code that uses unicode strings.
+            # We implement python2 behavior: silently convert to ascii.
+            return path.encode('ascii')
+        else:
+            return path.as_bytes()
+    
+    @classmethod
+    def as_str0(cls, path):
+        res = cls.as_str(path)
+        rstring.check_str0(res)
+        return res
 
 def ll_strcpy(dst_s, src_s, n):
     dstchars = dst_s.chars
diff --git a/rpython/rtyper/module/test/test_ll_os.py b/rpython/rtyper/module/test/test_ll_os.py
--- a/rpython/rtyper/module/test/test_ll_os.py
+++ b/rpython/rtyper/module/test/test_ll_os.py
@@ -95,8 +95,7 @@
     assert not data.endswith(stuff)
 
 def test_getcwd():
-    data = getllimpl(os.getcwd)()
-    assert data == os.getcwd()
+    assert rposix.getcwd() == os.getcwd()
 
 def test_chdir():
     def check_special_envvar():


More information about the pypy-commit mailing list