[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