[pypy-commit] pypy default: In RPython, this adds the ability to automatically redirect some

arigo noreply at buildbot.pypy.org
Sun Aug 31 12:41:09 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r73223:3c3f30ffed49
Date: 2014-08-31 12:40 +0200
http://bitbucket.org/pypy/pypy/changeset/3c3f30ffed49/

Log:	In RPython, this adds the ability to automatically redirect some
	functions from os.path to our own functions in rpython.rlib.rpath.

diff --git a/rpython/flowspace/specialcase.py b/rpython/flowspace/specialcase.py
--- a/rpython/flowspace/specialcase.py
+++ b/rpython/flowspace/specialcase.py
@@ -14,6 +14,16 @@
         SPECIAL_CASES[func] = sc_func
     return decorate
 
+def redirect_function(srcfunc, dstfuncname):
+    @register_flow_sc(srcfunc)
+    def sc_redirected_function(ctx, *args_w):
+        components = dstfuncname.split('.')
+        obj = __import__('.'.join(components[:-1]))
+        for name in components[1:]:
+            obj = getattr(obj, name)
+        return ctx.appcall(obj, *args_w)
+
+
 @register_flow_sc(__import__)
 def sc_import(ctx, *args_w):
     assert all(isinstance(arg, Constant) for arg in args_w)
@@ -44,34 +54,23 @@
         from rpython.flowspace.operation import op
         return op.getattr(w_obj, w_index).eval(ctx)
 
- at register_flow_sc(open)
-def sc_open(ctx, *args_w):
-    from rpython.rlib.rfile import create_file
-    return ctx.appcall(create_file, *args_w)
+# _________________________________________________________________________
 
- at register_flow_sc(os.fdopen)
-def sc_os_fdopen(ctx, *args_w):
-    from rpython.rlib.rfile import create_fdopen_rfile
-    return ctx.appcall(create_fdopen_rfile, *args_w)
+redirect_function(open,       'rpython.rlib.rfile.create_file')
+redirect_function(os.fdopen,  'rpython.rlib.rfile.create_fdopen_rfile')
+redirect_function(os.tmpfile, 'rpython.rlib.rfile.create_temp_rfile')
 
- at register_flow_sc(os.tmpfile)
-def sc_os_tmpfile(ctx):
-    from rpython.rlib.rfile import create_temp_rfile
-    return ctx.appcall(create_temp_rfile)
+# on top of PyPy only: 'os.remove != os.unlink'
+# (on CPython they are '==', but not identical either)
+redirect_function(os.remove,  'os.unlink')
 
- at register_flow_sc(os.remove)
-def sc_os_remove(ctx, *args_w):
-    # on top of PyPy only: 'os.remove != os.unlink'
-    # (on CPython they are '==', but not identical either)
-    return ctx.appcall(os.unlink, *args_w)
+redirect_function(os.path.isdir,   'rpython.rlib.rpath.risdir')
+redirect_function(os.path.isabs,   'rpython.rlib.rpath.risabs')
+redirect_function(os.path.abspath, 'rpython.rlib.rpath.rabspath')
+redirect_function(os.path.join,    'rpython.rlib.rpath.rjoin')
+if hasattr(os.path, 'splitdrive'):
+    redirect_function(os.path.splitdrive, 'rpython.rlib.rpath.rsplitdrive')
 
-if os.name == 'nt':
-    @register_flow_sc(os.path.isdir)
-    def sc_os_path_isdir(ctx, *args_w):
-        # Cpython win32 reroutes os.path.isdir to nt._isdir
-        # which is not rpython
-        import genericpath
-        return ctx.appcall(genericpath.isdir, *args_w)
 # _________________________________________________________________________
 # a simplified version of the basic printing routines, for RPython programs
 class StdOutBuffer:
diff --git a/rpython/flowspace/test/test_objspace.py b/rpython/flowspace/test/test_objspace.py
--- a/rpython/flowspace/test/test_objspace.py
+++ b/rpython/flowspace/test/test_objspace.py
@@ -1265,6 +1265,18 @@
         assert ops[1].opname == 'simple_call'
         assert ops[1].args[0].value is os.unlink
 
+    def test_rabspath(self):
+        import os.path
+        def f(s):
+            return os.path.abspath(s)
+        graph = self.codetest(f)
+        simplify_graph(graph)
+        ops = graph.startblock.operations
+        assert ops[0].opname == 'simple_call'
+        #
+        from rpython.rlib import rpath
+        assert ops[0].args[0].value is rpath.rabspath
+
     def test_constfold_in(self):
         def f():
             if 'x' in "xyz":
diff --git a/rpython/rlib/rpath.py b/rpython/rlib/rpath.py
--- a/rpython/rlib/rpath.py
+++ b/rpython/rlib/rpath.py
@@ -2,10 +2,29 @@
 Minimal (and limited) RPython version of some functions contained in os.path.
 """
 
-import os
+import os, stat
 from rpython.rlib import rposix
 
 
+# ____________________________________________________________
+#
+# Generic implementations in RPython for both POSIX and NT
+#
+
+def risdir(s):
+    """Return true if the pathname refers to an existing directory."""
+    try:
+        st = os.stat(s)
+    except OSError:
+        return False
+    return stat.S_ISDIR(st.st_mode)
+
+
+# ____________________________________________________________
+#
+# POSIX-only implementations
+#
+
 def _posix_risabs(s):
     """Test whether a path is absolute"""
     return s.startswith('/')
@@ -36,6 +55,11 @@
     return path
 
 
+# ____________________________________________________________
+#
+# NT-only implementations
+#
+
 def _nt_risabs(s):
     """Test whether a path is absolute"""
     s = _nt_rsplitdrive(s)[1]
@@ -108,6 +132,9 @@
     return result_drive + result_path
 
 
+# ____________________________________________________________
+
+
 if os.name == 'posix':
     sep = altsep = '/'
     risabs      = _posix_risabs
diff --git a/rpython/rlib/test/test_rpath.py b/rpython/rlib/test/test_rpath.py
--- a/rpython/rlib/test/test_rpath.py
+++ b/rpython/rlib/test/test_rpath.py
@@ -44,3 +44,8 @@
     assert rpath._nt_risabs('\\foo\\bar')
     assert rpath._nt_risabs('C:\\FOO')
     assert not rpath._nt_risabs('C:FOO')
+
+def test_risdir(tmpdir):
+    assert rpath.risdir(tmpdir)
+    assert not rpath.risdir('_some_non_existant_file_')
+    assert not rpath.risdir(os.path.join(tmpdir, '_some_non_existant_file_'))


More information about the pypy-commit mailing list