Author: Ronan Lamy <[email protected]>
Branch: follow_symlinks
Changeset: r83660:3612d36ef882
Date: 2016-04-14 02:16 +0100
http://bitbucket.org/pypy/pypy/changeset/3612d36ef882/

Log:    Simplify stat(), fix error messages, add missing lstat()
        functionality

diff --git a/pypy/module/posix/interp_posix.py 
b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -124,43 +124,44 @@
 
 
 class Path(object):
-    _immutable_fields_ = ['as_fd', 'as_bytes', 'as_unicode']
+    _immutable_fields_ = ['as_fd', 'as_bytes', 'as_unicode', 'w_path']
 
-    def __init__(self, fd, bytes, unicode):
+    def __init__(self, fd, bytes, unicode, w_path):
         self.as_fd = fd
         self.as_bytes = bytes
         self.as_unicode = unicode
+        self.w_path = w_path
 
 class _PathOrFd(Unwrapper):
     def unwrap(self, space, w_value):
         if _WIN32:
             try:
                 path_u = space.unicode_w(w_value)
-                return Path(-1, None, path_u)
+                return Path(-1, None, path_u, w_value)
             except OperationError:
                 pass
         try:
             path_b = space.fsencode_w(w_value)
-            return Path(-1, path_b, None)
+            return Path(-1, path_b, None, w_value)
         except OperationError:
             pass
         if not space.isinstance_w(w_value, space.w_int):
             raise oefmt(space.w_TypeError,
                 "argument should be string, bytes or integer, not %T", w_value)
         fd = unwrap_fd(space, w_value)
-        return Path(fd, None, None)
+        return Path(fd, None, None, w_value)
 
 class _JustPath(Unwrapper):
     def unwrap(self, space, w_value):
         if _WIN32:
             try:
                 path_u = space.unicode_w(w_value)
-                return Path(-1, None, path_u)
+                return Path(-1, None, path_u, w_value)
             except OperationError:
                 pass
         try:
             path_b = space.fsencode_w(w_value)
-            return Path(-1, path_b, None)
+            return Path(-1, path_b, None, w_value)
         except OperationError:
             raise oefmt(space.w_TypeError, "illegal type for path parameter")
 
@@ -409,8 +410,11 @@
     else:
         return build_stat_result(space, st)
 
-@unwrap_spec(dir_fd=DirFD(rposix.HAVE_FSTATAT), follow_symlinks=kwonly(bool))
-def stat(space, w_path, dir_fd=DEFAULT_DIR_FD, follow_symlinks=True):
+@unwrap_spec(
+    path=path_or_fd(allow_fd=True),
+    dir_fd=DirFD(rposix.HAVE_FSTATAT),
+    follow_symlinks=kwonly(bool))
+def stat(space, path, dir_fd=DEFAULT_DIR_FD, follow_symlinks=True):
     """stat(path, *, dir_fd=None, follow_symlinks=True) -> stat result
 
 Perform a stat system call on the given path.
@@ -426,42 +430,43 @@
   link points to.
 It is an error to use dir_fd or follow_symlinks when specifying path as
   an open file descriptor."""
-    if follow_symlinks and dir_fd == DEFAULT_DIR_FD:
-        try:
-            st = dispatch_filename(rposix_stat.stat, 0,
-                                allow_fd_fn=rposix_stat.fstat)(space, w_path)
-        except OSError as e:
-            raise wrap_oserror2(space, e, w_path)
+    return do_stat(space, "stat", path, dir_fd, follow_symlinks)
+
[email protected](1)
+def do_stat(space, funcname, path, dir_fd, follow_symlinks):
+    """Common implementation for stat() and lstat()"""
+    try:
+        if path.as_fd != -1:
+            if dir_fd != DEFAULT_DIR_FD:
+                raise oefmt(space.w_ValueError,
+                    "%s: can't specify both dir_fd and fd", funcname)
+            if not follow_symlinks:
+                raise oefmt(space.w_ValueError,
+                    "%s: cannot use fd and follow_symlinks together", funcname)
+            st = rposix_stat.fstat(path.as_fd)
+        elif follow_symlinks and dir_fd == DEFAULT_DIR_FD:
+            st = call_rposix(rposix_stat.stat, path)
+        elif not follow_symlinks and dir_fd == DEFAULT_DIR_FD:
+            st = call_rposix(rposix_stat.lstat, path)
+        elif rposix.HAVE_FSTATAT:
+            st = call_rposix(rposix_stat.fstatat, path, dir_fd, 
follow_symlinks)
         else:
-            return build_stat_result(space, st)
-
-    if not follow_symlinks and dir_fd == DEFAULT_DIR_FD:
-        return lstat(space, w_path)
-
-    if rposix.HAVE_FSTATAT:
-        try:
-            path = space.fsencode_w(w_path)
-            st = rposix_stat.fstatat(path, dir_fd, follow_symlinks)
-        except OSError as e:
-            raise wrap_oserror2(space, e, w_path)
+            raise oefmt(space.w_NotImplementedError,
+                "%s: unsupported argument combination", funcname)
+    except OSError as e:
+        raise wrap_oserror2(space, e, path.w_path)
+    else:
         return build_stat_result(space, st)
 
-    raise oefmt(space.w_NotImplementedError,
-        "stat: unsupported argument combination")
-
-@unwrap_spec(dir_fd=DirFD(available=False))
-def lstat(space, w_path, dir_fd=DEFAULT_DIR_FD):
+@unwrap_spec(
+    path=path_or_fd(allow_fd=False),
+    dir_fd=DirFD(rposix.HAVE_FSTATAT))
+def lstat(space, path, dir_fd=DEFAULT_DIR_FD):
     """lstat(path, *, dir_fd=None) -> stat result
 
 Like stat(), but do not follow symbolic links.
 Equivalent to stat(path, follow_symlinks=False)."""
-
-    try:
-        st = dispatch_filename(rposix_stat.lstat)(space, w_path)
-    except OSError, e:
-        raise wrap_oserror2(space, e, w_path)
-    else:
-        return build_stat_result(space, st)
+    return do_stat(space, "lstat", path, dir_fd, False)
 
 class StatState(object):
     def __init__(self, space):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to