Author: Ronan Lamy <[email protected]>
Branch: follow_symlinks
Changeset: r83372:d8c010696602
Date: 2016-03-25 20:42 +0000
http://bitbucket.org/pypy/pypy/changeset/d8c010696602/
Log: Implement missing features in chmod()
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
@@ -1,6 +1,7 @@
import os
import sys
from math import modf
+from errno import ENOTSUP, EOPNOTSUPP
from rpython.rlib import rposix, rposix_stat
from rpython.rlib import objectmodel, rurandom
@@ -113,19 +114,22 @@
DEFAULT_DIR_FD = -100
DIR_FD_AVAILABLE = False
-def _unwrap_fd(space, w_value):
+def unwrap_fd(space, w_value):
+ return space.c_int_w(w_value)
+
+def _unwrap_dirfd(space, w_value):
if space.is_none(w_value):
return DEFAULT_DIR_FD
else:
- return space.c_int_w(w_value)
+ return unwrap_fd(space, w_value)
class _DirFD(Unwrapper):
def unwrap(self, space, w_value):
- return _unwrap_fd(space, w_value)
+ return _unwrap_dirfd(space, w_value)
class _DirFD_Unavailable(Unwrapper):
def unwrap(self, space, w_value):
- dir_fd = _unwrap_fd(space, w_value)
+ dir_fd = unwrap_fd(space, w_value)
if dir_fd == DEFAULT_DIR_FD:
return dir_fd
else:
@@ -140,7 +144,7 @@
def argument_unavailable(space, funcname, arg):
return oefmt(
space.w_NotImplementedError,
- "%s: %s unavailable on this platform" % (funcname, arg))
+ "%s: %s unavailable on this platform", funcname, arg)
@unwrap_spec(flags=c_int, mode=c_int, dir_fd=DirFD(rposix.HAVE_OPENAT))
def open(space, w_path, flags, mode=0777, dir_fd=DEFAULT_DIR_FD):
@@ -477,9 +481,9 @@
of R_OK, W_OK, and X_OK."""
if not rposix.HAVE_FACCESSAT:
if not follow_symlinks:
- raise argument_unavailable("access", "follow_symlinks")
+ raise argument_unavailable(space, "access", "follow_symlinks")
if effective_ids:
- raise argument_unavailable("access", "effective_ids")
+ raise argument_unavailable(space, "access", "effective_ids")
try:
if dir_fd == DEFAULT_DIR_FD and follow_symlinks and not effective_ids:
@@ -773,7 +777,7 @@
raise wrap_oserror(space, e)
return space.newtuple([space.wrap(fd1), space.wrap(fd2)])
-@unwrap_spec(mode=c_int, dir_fd=DirFD(available=False),
follow_symlinks=kwonly(bool))
+@unwrap_spec(mode=c_int, dir_fd=DirFD(rposix.HAVE_FCHMODAT),
follow_symlinks=kwonly(bool))
def chmod(space, w_path, mode, dir_fd=DEFAULT_DIR_FD, follow_symlinks=True):
"""chmod(path, mode, *, dir_fd=None, follow_symlinks=True)
@@ -791,21 +795,55 @@
an open file descriptor.
dir_fd and follow_symlinks may not be implemented on your platform.
If they are unavailable, using them will raise a NotImplementedError."""
+ if not rposix.HAVE_FCHMODAT:
+ if not follow_symlinks:
+ raise argument_unavailable(space, "chmod", "follow_symlinks")
+ else:
+ try:
+ dispatch_filename(rposix.chmod)(space, w_path, mode)
+ return
+ except OSError as e:
+ raise wrap_oserror2(space, e, w_path)
+
try:
- dispatch_filename(rposix.chmod)(space, w_path, mode)
- except OSError, e:
- raise wrap_oserror2(space, e, w_path)
+ path = space.fsencode_w(w_path)
+ except OperationError as operr:
+ if not space.isinstance_w(w_path, space.w_int):
+ raise oefmt(space.w_TypeError,
+ "argument should be string, bytes or integer, not %T", w_path)
+ fd = unwrap_fd(space, w_path)
+ _chmod_fd(space, fd, mode)
+ else:
+ try:
+ _chmod_path(path, mode, dir_fd, follow_symlinks)
+ except OSError as e:
+ if not follow_symlinks and e.errno in (ENOTSUP, EOPNOTSUPP):
+ # fchmodat() doesn't actually implement follow_symlinks=False
+ # so raise NotImplementedError in this case
+ raise argument_unavailable(space, "chmod", "follow_symlinks")
+ else:
+ raise wrap_oserror2(space, e, w_path)
-@unwrap_spec(mode=c_int)
-def fchmod(space, w_fd, mode):
- """Change the access permissions of the file given by file
-descriptor fd."""
- fd = space.c_filedescriptor_w(w_fd)
+def _chmod_path(path, mode, dir_fd, follow_symlinks):
+ if dir_fd != DEFAULT_DIR_FD or not follow_symlinks:
+ rposix.fchmodat(path, mode, dir_fd, follow_symlinks)
+ else:
+ rposix.chmod(path, mode)
+
+def _chmod_fd(space, fd, mode):
try:
os.fchmod(fd, mode)
- except OSError, e:
+ except OSError as e:
raise wrap_oserror(space, e)
+
+@unwrap_spec(fd=c_int, mode=c_int)
+def fchmod(space, fd, mode):
+ """\
+ Change the access permissions of the file given by file descriptor fd.
+ """
+ _chmod_fd(space, fd, mode)
+
@unwrap_spec(src_dir_fd=DirFD(available=False),
dst_dir_fd=DirFD(available=False))
def rename(space, w_old, w_new,
src_dir_fd=DEFAULT_DIR_FD, dst_dir_fd=DEFAULT_DIR_FD):
@@ -1197,7 +1235,7 @@
raise wrap_oserror2(space, e, w_path)
if not follow_symlinks:
- raise argument_unavailable("utime", "follow_symlinks")
+ raise argument_unavailable(space, "utime", "follow_symlinks")
if not space.is_w(w_ns, space.w_None):
raise oefmt(space.w_NotImplementedError,
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit