[pypy-svn] r30406 - in pypy/dist/pypy: module/posix rpython rpython/lltypesystem/module rpython/module translator/c translator/c/src translator/c/test

arigo at codespeak.net arigo at codespeak.net
Sun Jul 23 19:24:59 CEST 2006


Author: arigo
Date: Sun Jul 23 19:24:55 2006
New Revision: 30406

Modified:
   pypy/dist/pypy/module/posix/__init__.py
   pypy/dist/pypy/module/posix/interp_posix.py
   pypy/dist/pypy/rpython/extfunctable.py
   pypy/dist/pypy/rpython/lltypesystem/module/ll_os.py
   pypy/dist/pypy/rpython/module/ll_os.py
   pypy/dist/pypy/translator/c/extfunc.py
   pypy/dist/pypy/translator/c/src/ll_os.h
   pypy/dist/pypy/translator/c/test/test_extfunc.py
Log:
Put some more functions in the os module.


Modified: pypy/dist/pypy/module/posix/__init__.py
==============================================================================
--- pypy/dist/pypy/module/posix/__init__.py	(original)
+++ pypy/dist/pypy/module/posix/__init__.py	Sun Jul 23 19:24:55 2006
@@ -28,6 +28,7 @@
     'fstat'     : 'interp_posix.fstat',
     'stat'      : 'interp_posix.stat',
     'dup'       : 'interp_posix.dup',
+    'dup2'      : 'interp_posix.dup2',
     'system'    : 'interp_posix.system',
     'unlink'    : 'interp_posix.unlink',
     'remove'    : 'interp_posix.remove',
@@ -38,6 +39,9 @@
     'environ'   : 'interp_posix.get(space).w_environ',
     'listdir'   : 'interp_posix.listdir',
     'strerror'  : 'interp_posix.strerror',
+    'pipe'      : 'interp_posix.pipe',
+    'chmod'     : 'interp_posix.chmod',
+    'rename'    : 'interp_posix.rename',
     }
     if hasattr(os, 'ftruncate'):
         interpleveldefs['ftruncate'] = 'interp_posix.ftruncate'
@@ -45,6 +49,16 @@
         interpleveldefs['putenv'] = 'interp_posix.putenv'
     if hasattr(posix, 'unsetenv'): # note: emulated in os
         interpleveldefs['unsetenv'] = 'interp_posix.unsetenv'
+    if hasattr(os, 'getpid'):
+        interpleveldefs['getpid'] = 'interp_posix.getpid'
+    if hasattr(os, 'lstat'):
+        interpleveldefs['lstat'] = 'interp_posix.lstat'
+    if hasattr(os, 'link'):
+        interpleveldefs['link'] = 'interp_posix.link'
+    if hasattr(os, 'symlink'):
+        interpleveldefs['symlink'] = 'interp_posix.symlink'
+    if hasattr(os, 'readlink'):
+        interpleveldefs['readlink'] = 'interp_posix.readlink'
 
 
 for constant in dir(os):

Modified: pypy/dist/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/dist/pypy/module/posix/interp_posix.py	(original)
+++ pypy/dist/pypy/module/posix/interp_posix.py	Sun Jul 23 19:24:55 2006
@@ -131,6 +131,16 @@
         return build_stat_result(space, st)
 stat.unwrap_spec = [ObjSpace, str]
 
+def lstat(space, path):
+    "Like stat(path), but do no follow symbolic links."
+    try:
+        st = os.lstat(path)
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    else:
+        return build_stat_result(space, st)
+lstat.unwrap_spec = [ObjSpace, str]
+
 def dup(space, fd):
     """Create a copy of the file descriptor.  Return the new file
 descriptor."""
@@ -142,6 +152,14 @@
         return space.wrap(newfd)
 dup.unwrap_spec = [ObjSpace, int]
 
+def dup2(space, old_fd, new_fd):
+    """Duplicate a file descriptor."""
+    try:
+        os.dup2(old_fd, new_fd)
+    except OSError, e: 
+        raise wrap_oserror(space, e) 
+dup2.unwrap_spec = [ObjSpace, int, int]
+
 def system(space, cmd):
     """Execute the command (a string) in a subshell."""
     try:
@@ -290,3 +308,62 @@
     finally:
         dir.closedir()
 listdir.unwrap_spec = [ObjSpace, str]
+
+def pipe(space):
+    "Create a pipe.  Returns (read_end, write_end)."
+    try: 
+        fd1, fd2 = os.pipe()
+    except OSError, e: 
+        raise wrap_oserror(space, e) 
+    return space.newtuple([space.wrap(fd1), space.wrap(fd2)])
+pipe.unwrap_spec = [ObjSpace]
+
+def chmod(space, path, mode):
+    "Change the access permissions of a file."
+    try: 
+        os.chmod(path, mode)
+    except OSError, e: 
+        raise wrap_oserror(space, e) 
+chmod.unwrap_spec = [ObjSpace, str, int]
+
+def rename(space, old, new):
+    "Rename a file or directory."
+    try: 
+        os.rename(old, new)
+    except OSError, e: 
+        raise wrap_oserror(space, e) 
+rename.unwrap_spec = [ObjSpace, str, str]
+
+def getpid(space):
+    "Return the current process id."
+    try: 
+        pid = os.getpid()
+    except OSError, e: 
+        raise wrap_oserror(space, e) 
+    return space.wrap(pid)
+getpid.unwrap_spec = [ObjSpace]
+
+def link(space, src, dst):
+    "Create a hard link to a file."
+    try: 
+        os.link(src, dst)
+    except OSError, e: 
+        raise wrap_oserror(space, e) 
+link.unwrap_spec = [ObjSpace, str, str]
+
+def symlink(space, src, dst):
+    "Create a symbolic link pointing to src named dst."
+    try: 
+        os.symlink(src, dst)
+    except OSError, e: 
+        raise wrap_oserror(space, e) 
+symlink.unwrap_spec = [ObjSpace, str, str]
+
+def readlink(space, path):
+    "Return a string representing the path to which the symbolic link points."
+    try:
+        result = os.readlink(path)
+    except OSError, e: 
+        raise wrap_oserror(space, e) 
+    return space.wrap(result)
+readlink.unwrap_spec = [ObjSpace, str]

Modified: pypy/dist/pypy/rpython/extfunctable.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunctable.py	(original)
+++ pypy/dist/pypy/rpython/extfunctable.py	Sun Jul 23 19:24:55 2006
@@ -160,6 +160,12 @@
     record_call(Implementation.ll_stat_result, [SomeInteger()]*10, 'OS_STAT')
     return SomeTuple((SomeInteger(),)*10)
 
+def pipeannotation(*args):
+    from pypy.rpython.lltypesystem.module.ll_os import Implementation
+    from pypy.annotation.model import SomeInteger, SomeTuple
+    record_call(Implementation.ll_pipe_result, [SomeInteger()]*2, 'OS_PIPE')
+    return SomeTuple((SomeInteger(),)*2)
+
 def frexpannotation(*args):
     from pypy.annotation.model import SomeInteger, SomeTuple, SomeFloat
     from pypy.rpython.lltypesystem.module.ll_math import ll_frexp_result
@@ -183,6 +189,7 @@
 declare(os.write    , posannotation , 'll_os/write')
 declare(os.close    , noneannotation, 'll_os/close')
 declare(os.dup      , int           , 'll_os/dup')
+declare(os.dup2     , noneannotation, 'll_os/dup2')
 declare(os.lseek    , r_longlong    , 'll_os/lseek')
 declare(os.isatty   , bool          , 'll_os/isatty')
 if hasattr(posix, 'ftruncate'):
@@ -198,6 +205,20 @@
 declare(os.rmdir    , noneannotation, 'll_os/rmdir')
 if hasattr(posix, 'unsetenv'):   # note: faked in os
     declare(os.unsetenv , noneannotation, 'll_os/unsetenv')
+declare(os.pipe     , pipeannotation, 'll_os/pipe')
+declare(os.chmod    , noneannotation, 'll_os/chmod')
+declare(os.rename   , noneannotation, 'll_os/rename')
+if hasattr(os, 'getpid'):
+    declare(os.getpid   , int,            'll_os/getpid')
+if hasattr(os, 'lstat'):
+    declare(os.lstat    , statannotation, 'll_os/lstat')
+if hasattr(os, 'link'):
+    declare(os.link     , noneannotation, 'll_os/link')
+if hasattr(os, 'symlink'):
+    declare(os.symlink  , noneannotation, 'll_os/symlink')
+if hasattr(os, 'readlink'):
+    declare(os.readlink , str,            'll_os/readlink')
+
 declare(os.path.exists, bool        , 'll_os_path/exists')
 declare(os.path.isdir, bool         , 'll_os_path/isdir')
 declare(time.time   , float         , 'll_time/time')

Modified: pypy/dist/pypy/rpython/lltypesystem/module/ll_os.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/module/ll_os.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/module/ll_os.py	Sun Jul 23 19:24:55 2006
@@ -5,8 +5,8 @@
 from pypy.rpython.lltypesystem import lltype, rtupletype
 from pypy.rpython.rarithmetic import intmask
 
-n = 10
-STAT_RESULT = rtupletype.TUPLE_TYPE([lltype.Signed]*n).TO
+STAT_RESULT = rtupletype.TUPLE_TYPE([lltype.Signed]*10).TO
+PIPE_RESULT = rtupletype.TUPLE_TYPE([lltype.Signed]*2).TO
 
 class Implementation(BaseOS, LLSupport):
     
@@ -26,6 +26,13 @@
         return tup
     ll_stat_result = staticmethod(ll_stat_result)
 
+    def ll_pipe_result(fd1, fd2):
+        tup = lltype.malloc(PIPE_RESULT)
+        tup.item0 = fd1
+        tup.item1 = fd2
+        return tup
+    ll_pipe_result = staticmethod(ll_pipe_result)
+
     def ll_os_read(cls, fd, count):
         from pypy.rpython.lltypesystem.rstr import STR
         if count < 0:
@@ -37,3 +44,16 @@
             ll_strcpy(s, buffer, n)
             buffer = s
         return buffer
+
+    def ll_os_readlink(cls, path):
+        from pypy.rpython.lltypesystem.rstr import STR
+        bufsize = 1023
+        while 1:
+            buffer = lltype.malloc(STR, bufsize)
+            n = cls.ll_readlink_into(cls, path, buffer)
+            if n < bufsize:
+                break
+            bufsize *= 4     # overflow, try again with a bigger buffer
+        s = lltype.malloc(STR, n)
+        ll_strcpy(s, buffer, n)
+        return s

Modified: pypy/dist/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/dist/pypy/rpython/module/ll_os.py	(original)
+++ pypy/dist/pypy/rpython/module/ll_os.py	Sun Jul 23 19:24:55 2006
@@ -51,6 +51,10 @@
         return os.dup(fd)
     ll_os_dup.suggested_primitive = True
 
+    def ll_os_dup2(cls, old_fd, new_fd):
+        os.dup2(old_fd, new_fd)
+    ll_os_dup2.suggested_primitive = True
+
     def ll_os_lseek(cls, fd,pos,how):
         return r_longlong(os.lseek(fd,pos,how))
     ll_os_lseek.suggested_primitive = True
@@ -77,6 +81,13 @@
                                   stat5, stat6, stat7, stat8, stat9)
     ll_os_stat.suggested_primitive = True
 
+    def ll_os_lstat(cls, path):
+        (stat0, stat1, stat2, stat3, stat4,
+         stat5, stat6, stat7, stat8, stat9) = os.lstat(cls.from_rstr(path))
+        return cls.ll_stat_result(stat0, stat1, stat2, stat3, stat4,
+                                  stat5, stat6, stat7, stat8, stat9)
+    ll_os_lstat.suggested_primitive = True
+
     def ll_os_strerror(cls, errnum):
         return cls.to_rstr(os.strerror(errnum))
     ll_os_strerror.suggested_primitive = True
@@ -115,6 +126,39 @@
         return ros.environ(idx)
     ll_os_environ.suggested_primitive = True
 
+    def ll_os_pipe(cls):
+        fd1, fd2 = os.pipe()
+        return cls.ll_pipe_result(fd1, fd2)
+    ll_os_pipe.suggested_primitive = True
+
+    def ll_os_chmod(cls, path, mode):
+        os.chmod(cls.from_rstr(path), mode)
+    ll_os_chmod.suggested_primitive = True
+
+    def ll_os_rename(cls, path1, path2):
+        os.rename(cls.from_rstr(path1), cls.from_rstr(path2))
+    ll_os_rename.suggested_primitive = True
+
+    def ll_os_getpid(cls):
+        return os.getpid()
+    ll_os_getpid.suggested_primitive = True
+
+    def ll_os_link(cls, path1, path2):
+        os.link(cls.from_rstr(path1), cls.from_rstr(path2))
+    ll_os_link.suggested_primitive = True
+
+    def ll_os_symlink(cls, path1, path2):
+        os.symlink(cls.from_rstr(path1), cls.from_rstr(path2))
+    ll_os_symlink.suggested_primitive = True
+
+    def ll_readlink_into(cls, path, buffer):
+        data = os.readlink(cls.from_rstr(path))
+        if len(data) < len(buffer.chars):   # safely no overflow
+            _ll_strfill(buffer, data, len(data))
+        return len(data)
+    ll_readlink_into.suggested_primitive = True
+    ll_readlink_into = staticmethod(ll_readlink_into)
+
     # ____________________________________________________________
     # opendir/readdir
 

Modified: pypy/dist/pypy/translator/c/extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/extfunc.py	(original)
+++ pypy/dist/pypy/translator/c/extfunc.py	Sun Jul 23 19:24:55 2006
@@ -7,7 +7,8 @@
 from pypy.rpython.lltypesystem import rlist
 from pypy.rpython.module import ll_time, ll_math, ll_strtod
 from pypy.rpython.module import ll_stackless, ll_stack
-from pypy.rpython.lltypesystem.module.ll_os import STAT_RESULT, Implementation as impl
+from pypy.rpython.lltypesystem.module.ll_os import STAT_RESULT, PIPE_RESULT
+from pypy.rpython.lltypesystem.module.ll_os import Implementation as impl
 from pypy.rpython.lltypesystem.module import ll_math as ll_math2
 from pypy.rpython.lltypesystem.module import ll_strtod as ll_strtod2
 
@@ -26,8 +27,10 @@
     impl.ll_os_write.im_func:   'LL_os_write',
     impl.ll_os_close.im_func:   'LL_os_close',
     impl.ll_os_dup.im_func:     'LL_os_dup',
+    impl.ll_os_dup2.im_func:    'LL_os_dup2',
     impl.ll_os_stat.im_func:    'LL_os_stat',
     impl.ll_os_fstat.im_func:   'LL_os_fstat',
+    impl.ll_os_lstat.im_func:   'LL_os_lstat',
     impl.ll_os_lseek.im_func:   'LL_os_lseek',
     impl.ll_os_isatty.im_func:  'LL_os_isatty',
     impl.ll_os_ftruncate.im_func:'LL_os_ftruncate',
@@ -44,6 +47,13 @@
     impl.ll_os_opendir.im_func: 'LL_os_opendir',
     impl.ll_os_readdir.im_func: 'LL_os_readdir',
     impl.ll_os_closedir.im_func:'LL_os_closedir',
+    impl.ll_os_pipe.im_func:    'LL_os_pipe',
+    impl.ll_os_chmod.im_func:   'LL_os_chmod',
+    impl.ll_os_rename.im_func:  'LL_os_rename',
+    impl.ll_os_getpid.im_func:  'LL_os_getpid',
+    impl.ll_os_link.im_func:    'LL_os_link',
+    impl.ll_os_symlink.im_func: 'LL_os_symlink',
+    impl.ll_readlink_into:      'LL_readlink_into',
     ll_time.ll_time_clock: 'LL_time_clock',
     ll_time.ll_time_sleep: 'LL_time_sleep',
     ll_time.ll_time_time:  'LL_time_time',
@@ -101,6 +111,7 @@
     yield ('RPyFREXP_RESULT', ll_math2.FREXP_RESULT)
     yield ('RPyMODF_RESULT', ll_math2.MODF_RESULT)
     yield ('RPySTAT_RESULT', STAT_RESULT)
+    yield ('RPyPIPE_RESULT', PIPE_RESULT)
 
 def predeclare_utility_functions(db, rtyper):
     # Common utility functions

Modified: pypy/dist/pypy/translator/c/src/ll_os.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/ll_os.h	(original)
+++ pypy/dist/pypy/translator/c/src/ll_os.h	Sun Jul 23 19:24:55 2006
@@ -14,6 +14,14 @@
 #  define PATH_MAX 254
 #endif
 
+#ifndef MAXPATHLEN
+#if defined(PATH_MAX) && PATH_MAX > 1024
+#define MAXPATHLEN PATH_MAX
+#else
+#define MAXPATHLEN 1024
+#endif
+#endif /* MAXPATHLEN */
+
 /* The functions below are mapped to functions from pypy.rpython.module.*
    by the pypy.translator.c.extfunc.EXTERNALS dictionary.
    They should correspond to the functions with the suggested_primitive
@@ -33,6 +41,9 @@
 #       define STAT stat
 #       define FSTAT fstat
 #       define STRUCT_STAT struct stat
+/* plus some approximate guesses */
+#       define LSTAT lstat
+#       define HAVE_FILESYSTEM_WITH_LINKS
 #endif
 
 
@@ -43,9 +54,11 @@
 long LL_os_write(int fd, RPyString *buffer);
 void LL_os_close(int fd);
 int LL_os_dup(int fd);
+void LL_os_dup2(int old_fd, int new_fd);
 RPySTAT_RESULT* _stat_construct_result_helper(STRUCT_STAT st);
 RPySTAT_RESULT* LL_os_stat(RPyString * fname);
 RPySTAT_RESULT* LL_os_fstat(long fd);
+RPyPIPE_RESULT* LL_os_pipe(void);
 long LL_os_lseek(long fd, long pos, long how);
 int LL_os_isatty(long fd);
 RPyString *LL_os_strerror(int errnum);
@@ -55,6 +68,12 @@
 void LL_os_chdir(RPyString * path);
 void LL_os_mkdir(RPyString * path, int mode);
 void LL_os_rmdir(RPyString * path);
+void LL_os_chmod(RPyString * path, int mode);
+void LL_os_rename(RPyString * path1, RPyString * path2);
+long LL_os_getpid(void);
+void LL_os_link(RPyString * path1, RPyString * path2);
+void LL_os_symlink(RPyString * path1, RPyString * path2);
+long LL_readlink_into(RPyString *path, RPyString *buffer);
 void LL_os_putenv(RPyString * name_eq_value);
 void LL_os_unsetenv(RPyString * name);
 RPyString* LL_os_environ(int idx);
@@ -113,6 +132,13 @@
 	return fd;
 }
 
+void LL_os_dup2(int old_fd, int new_fd)
+{
+	new_fd = dup2(old_fd, new_fd);
+	if (new_fd < 0)
+		RPYTHON_RAISE_OSERROR(errno);
+}
+
 #ifdef LL_NEED_OS_STAT
 
 RPySTAT_RESULT* _stat_construct_result_helper(STRUCT_STAT st) {
@@ -144,6 +170,18 @@
   return _stat_construct_result_helper(st);
 }
 
+#ifdef LSTAT
+RPySTAT_RESULT* LL_os_lstat(RPyString * fname) {
+  STRUCT_STAT st;
+  int error = LSTAT(RPyString_AsString(fname), &st);
+  if (error != 0) {
+    RPYTHON_RAISE_OSERROR(errno);
+    return NULL;
+  }
+  return _stat_construct_result_helper(st);
+}
+#endif
+
 RPySTAT_RESULT* LL_os_fstat(long fd) {
   STRUCT_STAT st;
   int error = FSTAT(fd, &st);
@@ -156,6 +194,20 @@
 
 #endif
 
+#ifdef LL_NEED_OS_PIPE
+
+RPyPIPE_RESULT* LL_os_pipe(void) {
+	int filedes[2];
+	int error = pipe(filedes);
+	if (error != 0) {
+		RPYTHON_RAISE_OSERROR(errno);
+		return NULL;
+	}
+	return ll_pipe_result(filedes[0], filedes[1]);
+}
+
+#endif
+
 long LL_os_lseek(long fd, long pos, long how) {
 #if defined(MS_WIN64) || defined(MS_WINDOWS)
     PY_LONG_LONG res;
@@ -253,6 +305,51 @@
     }
 }
 
+void LL_os_chmod(RPyString * path, int mode) {
+    int error = chmod(RPyString_AsString(path), mode);
+    if (error != 0) {
+	RPYTHON_RAISE_OSERROR(errno);
+    }
+}
+
+void LL_os_rename(RPyString * path1, RPyString * path2) {
+    int error = rename(RPyString_AsString(path1), RPyString_AsString(path2));
+    if (error != 0) {
+	RPYTHON_RAISE_OSERROR(errno);
+    }
+}
+
+long LL_os_getpid(void) {
+	return getpid();
+}
+
+#ifdef HAVE_FILESYSTEM_WITH_LINKS
+
+void LL_os_link(RPyString * path1, RPyString * path2) {
+    int error = link(RPyString_AsString(path1), RPyString_AsString(path2));
+    if (error != 0) {
+	RPYTHON_RAISE_OSERROR(errno);
+    }
+}
+
+void LL_os_symlink(RPyString * path1, RPyString * path2) {
+    int error = symlink(RPyString_AsString(path1), RPyString_AsString(path2));
+    if (error != 0) {
+	RPYTHON_RAISE_OSERROR(errno);
+    }
+}
+
+long LL_readlink_into(RPyString *path, RPyString *buffer)
+{
+	long n = readlink(RPyString_AsString(path),
+			  RPyString_AsString(buffer), RPyString_Size(buffer));
+	if (n < 0)
+		RPYTHON_RAISE_OSERROR(errno);
+	return n;
+}
+
+#endif
+
 #ifdef HAVE_PUTENV
 /* Note that this doesn't map to os.putenv, it is the name=value
  * version of C. See ros.py for the fake implementation.

Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_extfunc.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_extfunc.py	Sun Jul 23 19:24:55 2006
@@ -458,6 +458,101 @@
         res = f1(i)
         assert res == os.strerror(i)
 
+def test_pipe_dup_dup2():
+    def does_stuff():
+        a, b = os.pipe()
+        c = os.dup(a)
+        d = os.dup(b)
+        assert a != b
+        assert a != c
+        assert a != d
+        assert b != c
+        assert b != d
+        assert c != d
+        os.close(c)
+        os.dup2(d, c)
+        e, f = os.pipe()
+        assert e != a
+        assert e != b
+        assert e != c
+        assert e != d
+        assert f != a
+        assert f != b
+        assert f != c
+        assert f != d
+        assert f != e
+        os.close(a)
+        os.close(b)
+        os.close(c)
+        os.close(d)
+        os.close(e)
+        os.close(f)
+        return 42
+    f1 = compile(does_stuff, [])
+    res = f1()
+    assert res == 42
+
+def test_os_chmod():
+    tmpfile = str(udir.join('test_os_chmod.txt'))
+    f = open(tmpfile, 'w')
+    f.close()
+    def does_stuff(mode):
+        os.chmod(tmpfile, mode)
+    f1 = compile(does_stuff, [int])
+    f1(0000)
+    assert os.stat(tmpfile).st_mode & 0777 == 0000
+    f1(0644)
+    assert os.stat(tmpfile).st_mode & 0777 == 0644
+
+def test_os_rename():
+    tmpfile1 = str(udir.join('test_os_rename_1.txt'))
+    tmpfile2 = str(udir.join('test_os_rename_2.txt'))
+    f = open(tmpfile1, 'w')
+    f.close()
+    def does_stuff():
+        os.rename(tmpfile1, tmpfile2)
+    f1 = compile(does_stuff, [])
+    f1()
+    assert os.path.exists(tmpfile2)
+    assert not os.path.exists(tmpfile1)
+
+if hasattr(os, 'getpid'):
+    def test_os_getpid():
+        def does_stuff():
+            return os.getpid()
+        f1 = compile(does_stuff, [])
+        res = f1()
+        assert res == os.getpid()
+
+if hasattr(os, 'lstat'):
+    def test_links():
+        import stat
+        tmpfile1 = str(udir.join('test_links_1.txt'))
+        tmpfile2 = str(udir.join('test_links_2.txt'))
+        tmpfile3 = str(udir.join('test_links_3.txt'))
+        f = open(tmpfile1, 'w')
+        f.close()
+        def does_stuff():
+            os.symlink(tmpfile1, tmpfile2)
+            os.link(tmpfile1, tmpfile3)
+            assert os.readlink(tmpfile2) == tmpfile1
+            flag= 0
+            st = os.lstat(tmpfile1)
+            flag = flag*10 + stat.S_ISREG(st[0])
+            flag = flag*10 + stat.S_ISLNK(st[0])
+            st = os.lstat(tmpfile2)
+            flag = flag*10 + stat.S_ISREG(st[0])
+            flag = flag*10 + stat.S_ISLNK(st[0])
+            st = os.lstat(tmpfile3)
+            flag = flag*10 + stat.S_ISREG(st[0])
+            flag = flag*10 + stat.S_ISLNK(st[0])
+            return flag
+        f1 = compile(does_stuff, [])
+        res = f1()
+        assert res == 100110
+        assert os.path.islink(tmpfile2)
+        assert not os.path.islink(tmpfile3)
+
 # ____________________________________________________________
 
 def _real_getenv(var):



More information about the Pypy-commit mailing list