[pypy-svn] pypy default: Rewrite nanos.py: instead of directly importing from the os module

arigo commits-noreply at bitbucket.org
Sat Feb 5 14:07:52 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r41629:d5bac79d645e
Date: 2011-02-05 13:28 +0100
http://bitbucket.org/pypy/pypy/changeset/d5bac79d645e/

Log:	Rewrite nanos.py: instead of directly importing from the os module
	and expecting geninterp to do the right thing (i.e. filter out the
	unneeded parts and keep only the declaration of the functions
	actually used), we have to copy explicitly parts of posixpath.py or
	ntpath.py. This is a bit saner anyway, even though it means more
	code. Fixes test_nanos.py at least.

diff --git a/pypy/translator/goal/nanos.py b/pypy/translator/goal/nanos.py
--- a/pypy/translator/goal/nanos.py
+++ b/pypy/translator/goal/nanos.py
@@ -28,17 +28,169 @@
 from pypy.interpreter.gateway import applevel, ObjSpace, W_Root, interp2app
 import os, py
 
-app_os_path = applevel(r'''
-    from os.path import dirname, join, abspath, isfile, islink
-''', filename=__file__)
+if os.name == 'posix':
+    # code copied from posixpath.py
+    app_os_path = applevel("""
+        from posix import getcwd, stat, lstat, error
 
-app_os = applevel(r'''
-    from os import sep, pathsep, getenv, name, fdopen
-    try:
-        from os import readlink
-    except ImportError:
-        pass
-''', filename=__file__)
+        def dirname(p):
+            i = p.rfind('/') + 1
+            head = p[:i]
+            if head and head != '/'*len(head):
+                head = head.rstrip('/')
+            return head
+
+        def join(path, b):
+            if b.startswith('/'):
+                path = b
+            elif path == '' or path.endswith('/'):
+                path +=  b
+            else:
+                path += '/' + b
+            return path
+
+        def abspath(path):
+            if not path.startswith('/'):
+                cwd = getcwd()
+                path = join(cwd, path)
+            return path       # this version does not call normpath()!
+
+        def isfile(path):
+            try:
+                st = stat(path)
+            except error:
+                return False
+            return (st.st_mode & 0170000) == 0100000      # S_ISREG
+
+        def islink(path):
+            try:
+                st = lstat(path)
+            except error:
+                return False
+            return (st.st_mode & 0170000) == 0120000      # S_ISLNK
+
+    """, filename=__file__)
+
+    app_os = applevel("""
+        sep = '/'
+        pathsep = ':'
+        name = 'posix'
+        from posix import fdopen, readlink
+    """, filename=__file__)
+
+elif os.name == 'nt':
+    # code copied from ntpath.py
+    app_os_path = applevel("""
+        from nt import _getfullpathname, getcwd, stat, lstat, error
+
+        def splitdrive(p):
+            if p[1:2] == ':':
+                return p[0:2], p[2:]
+            return '', p
+
+        def isabs(s):
+            s = splitdrive(s)[1]
+            return s != '' and s[:1] in '/\\'
+
+        def dirname(p):
+            d, p = splitdrive(p)
+            # set i to index beyond p's last slash
+            i = len(p)
+            while i and p[i-1] not in '/\\':
+                i = i - 1
+            head = p[:i]
+            # remove trailing slashes from head, unless it's all slashes
+            head2 = head
+            while head2 and head2[-1] in '/\\':
+                head2 = head2[:-1]
+            head = head2 or head
+            return d + head
+
+        def join(path, b):
+            b_wins = 0  # set to 1 iff b makes path irrelevant
+            if path == "":
+                b_wins = 1
+
+            elif isabs(b):
+                # This probably wipes out path so far.  However, it's more
+                # complicated if path begins with a drive letter:
+                #     1. join('c:', '/a') == 'c:/a'
+                #     2. join('c:/', '/a') == 'c:/a'
+                # But
+                #     3. join('c:/a', '/b') == '/b'
+                #     4. join('c:', 'd:/') = 'd:/'
+                #     5. join('c:/', 'd:/') = 'd:/'
+                if path[1:2] != ":" or b[1:2] == ":":
+                    # Path doesn't start with a drive letter, or cases 4 and 5.
+                    b_wins = 1
+
+                # Else path has a drive letter, and b doesn't but is absolute.
+                elif len(path) > 3 or (len(path) == 3 and
+                                       path[-1] not in "/\\"):
+                    # case 3
+                    b_wins = 1
+
+            if b_wins:
+                path = b
+            else:
+                # Join, and ensure there's a separator.
+                assert len(path) > 0
+                if path[-1] in "/\\":
+                    if b and b[0] in "/\\":
+                        path += b[1:]
+                    else:
+                        path += b
+                elif path[-1] == ":":
+                    path += b
+                elif b:
+                    if b[0] in "/\\":
+                        path += b
+                    else:
+                        path += "\\" + b
+                else:
+                    # path is not empty and does not end with a backslash,
+                    # but b is empty; since, e.g., split('a/') produces
+                    # ('a', ''), it's best if join() adds a backslash in
+                    # this case.
+                    path += '\\'
+
+            return path
+
+        def abspath(path):
+            if path: # Empty path must return current working directory.
+                try:
+                    path = _getfullpathname(path)
+                except WindowsError:
+                    pass # Bad path - return unchanged.
+            else:
+                path = getcwd()
+            return path       # this version does not call normpath()!
+
+        def isfile(path):
+            try:
+                st = stat(path)
+            except error:
+                return False
+            return (st.st_mode & 0170000) == 0100000      # S_ISREG
+
+        def islink(path):
+            try:
+                st = lstat(path)
+            except error:
+                return False
+            return (st.st_mode & 0170000) == 0120000      # S_ISLNK
+
+    """, filename=__file__)
+
+    app_os = applevel("""
+        sep = '\\'
+        pathsep = ';'
+        name = 'nt'
+        from posix import fdopen
+    """, filename=__file__)
+
+else:
+    raise NotImplementedError("os.name == %r" % (os.name,))
 
 def getenv(space, w_name):
     name = space.str_w(w_name)


More information about the Pypy-commit mailing list