[pypy-svn] r76161 - in pypy/branch/unicode_filename-2/pypy: rlib rlib/test rpython rpython/lltypesystem rpython/module

afa at codespeak.net afa at codespeak.net
Mon Jul 12 22:01:57 CEST 2010


Author: afa
Date: Mon Jul 12 22:01:55 2010
New Revision: 76161

Added:
   pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py
Modified:
   pypy/branch/unicode_filename-2/pypy/rlib/rposix.py
   pypy/branch/unicode_filename-2/pypy/rpython/extfunc.py
   pypy/branch/unicode_filename-2/pypy/rpython/lltypesystem/rffi.py
   pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py
Log:
Add rlib.rposix.open(), which accept strings, and unicode "with default encoding".

The default implementation simply calls the encode() method and passes the
result to os.open(); but ll_os can provide a function that directly accepts
unicode.


Modified: pypy/branch/unicode_filename-2/pypy/rlib/rposix.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rlib/rposix.py	(original)
+++ pypy/branch/unicode_filename-2/pypy/rlib/rposix.py	Mon Jul 12 22:01:55 2010
@@ -3,6 +3,7 @@
 from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.objectmodel import specialize
 
 class CConstantErrno(CConstant):
     # these accessors are used when calling get_errno() or set_errno()
@@ -42,3 +43,13 @@
             os.close(fd)
         except OSError:
             pass
+
+
+# pypy.rpython.module.ll_os.py may force the annotator to flow a different
+# function that directly handle unicode strings.
+ at specialize.argtype(0)
+def open(path, flags, mode):
+    if isinstance(path, str):
+        return os.open(path, flags, mode)
+    else:
+        return os.open(path.encode(), flags, mode)

Added: pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py
==============================================================================
--- (empty file)
+++ pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py	Mon Jul 12 22:01:55 2010
@@ -0,0 +1,39 @@
+from pypy.rpython.test.test_llinterp import interpret
+from pypy.tool.udir import udir
+from pypy.rlib import rposix
+import os
+
+def ll_to_string(s):
+    return ''.join(s.chars)
+
+class TestPosixUnicode:
+    def test_access(self):
+        ufilename = (unicode(udir.join('test_open')) +
+                     u'\u65e5\u672c.txt') # "Japan"
+        f = file(ufilename, 'w')
+        f.write("test")
+        f.close()
+        filename = str(udir.join('test_open'))
+
+        class UnicodeWithEncoding:
+            def __init__(self, unistr):
+                self.unistr = unistr
+
+            def encode(self):
+                from pypy.rlib.runicode import unicode_encode_utf_8
+                return unicode_encode_utf_8(self.unistr, len(self.unistr),
+                                            "strict")
+        path = UnicodeWithEncoding(ufilename)
+
+        def f():
+            try:
+                fd = rposix.open(path, os.O_RDONLY, 0777)
+                try:
+                    text = os.read(fd, 50)
+                    return text
+                finally:
+                    os.close(fd)
+            except OSError:
+                return ''
+
+        assert ll_to_string(interpret(f, [])) == "test"

Modified: pypy/branch/unicode_filename-2/pypy/rpython/extfunc.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rpython/extfunc.py	(original)
+++ pypy/branch/unicode_filename-2/pypy/rpython/extfunc.py	Mon Jul 12 22:01:55 2010
@@ -52,7 +52,10 @@
                         return super(ExtRegistryEntry, self).__getattr__(attr)
                     raise exc, exc_inst, tb
 
-def registering(func):
+def registering(func, condition=True):
+    if not condition:
+        return lambda method: None
+
     def decorator(method):
         method._registering_func = func
         return method
@@ -63,11 +66,9 @@
         func = getattr(ns, name)
     except AttributeError:
         condition = False
+        func = None
 
-    if condition:
-        return registering(func)
-    else:
-        return lambda method: None
+    return registering(func, condition=condition)
 
 class LazyRegisteringMeta(type):
     def __new__(self, _name, _type, _vars):

Modified: pypy/branch/unicode_filename-2/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/branch/unicode_filename-2/pypy/rpython/lltypesystem/rffi.py	Mon Jul 12 22:01:55 2010
@@ -176,6 +176,15 @@
                     # XXX leaks if a str2charp() fails with MemoryError
                     # and was not the first in this function
                     freeme = arg
+            elif TARGET == CWCHARP:
+                if arg is None:
+                    arg = lltype.nullptr(CWCHARP.TO)   # None => (wchar_t*)NULL
+                    freeme = arg
+                elif isinstance(arg, unicode):
+                    arg = unicode2wcharp(arg)
+                    # XXX leaks if a unicode2wcharp() fails with MemoryError
+                    # and was not the first in this function
+                    freeme = arg
             elif _isfunctype(TARGET) and not _isllptr(arg):
                 # XXX pass additional arguments
                 if invoke_around_handlers:

Modified: pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py	(original)
+++ pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py	Mon Jul 12 22:01:55 2010
@@ -7,7 +7,7 @@
 
 import os, sys, errno
 from pypy.rpython.module.support import ll_strcpy, OOSupport
-from pypy.tool.sourcetools import func_with_new_name
+from pypy.tool.sourcetools import func_with_new_name, func_renamer
 from pypy.rlib.rarithmetic import r_longlong
 from pypy.rpython.extfunc import BaseLazyRegistering
 from pypy.rpython.extfunc import registering, registering_if, extdef
@@ -26,7 +26,41 @@
 from pypy.rpython.lltypesystem.rstr import STR
 from pypy.rpython.annlowlevel import llstr
 from pypy.rlib import rgc
-from pypy.rlib.objectmodel import keepalive_until_here
+from pypy.rlib.objectmodel import keepalive_until_here, specialize
+from pypy.rlib.unroll import unrolling_iterable
+
+def registering_unicode_version(func, nbargs, argnums, condition=True):
+    """
+    Registers an implementation of func() which directly accepts unicode
+    strings.  Replaces the corresponding function in pypy.rlib.rposix.
+    """
+    def unicodefunc(*args):
+        raise NotImplementedError
+
+    argnum = argnums[0]
+    unrolling_args = unrolling_iterable(enumerate([i in argnums
+                                                   for i in range(nbargs)]))
+
+    func_name = func.__name__
+    rposix_func = getattr(rposix, func_name)
+
+    @specialize.argtype(*argnums)
+    @func_renamer(func.__name__)
+    def new_func(*args):
+        if isinstance(args[argnum], str):
+            return func(*args)
+        else:
+            real_args = ()
+            for i, isunicode in unrolling_args:
+                if isunicode:
+                    real_args += (args[i].unistr,)
+                else:
+                    real_args += (args[i],)
+            return unicodefunc(*real_args)
+    if condition:
+        rposix_func._flowspace_rewrite_directly_as_ = new_func
+
+    return registering(unicodefunc, condition=condition)
 
 posix = __import__(os.name)
 
@@ -705,6 +739,20 @@
         return extdef([str, int, int], int, "ll_os.ll_os_open",
                       llimpl=os_open_llimpl, oofakeimpl=os_open_oofakeimpl)
 
+    @registering_unicode_version(os.open, 3, [0], sys.platform=='win32')
+    def register_os_open_unicode(self):
+        os_wopen = self.llexternal(underscore_on_windows+'wopen',
+                                  [rffi.CWCHARP, rffi.INT, rffi.MODE_T],
+                                  rffi.INT)
+        def os_wopen_llimpl(path, flags, mode):
+            result = rffi.cast(rffi.LONG, os_wopen(path, flags, mode))
+            if result == -1:
+                raise OSError(rposix.get_errno(), "os_open failed")
+            return result
+
+        return extdef([unicode, int, int], int, "ll_os.ll_os_wopen",
+                      llimpl=os_wopen_llimpl)
+
 # ------------------------------- os.read -------------------------------
 
     @registering(os.read)



More information about the Pypy-commit mailing list