mirror of
https://github.com/python/cpython.git
synced 2025-07-12 13:55:34 +00:00
Issue #14626: Large refactoring of functions / parameters in the os module.
Many functions now support "dir_fd" and "follow_symlinks" parameters; some also support accepting an open file descriptor in place of of a path string. Added os.support_* collections as LBYL helpers. Removed many functions only previously seen in 3.3 alpha releases (often starting with "f" or "l", or ending with "at"). Originally suggested by Serhiy Storchaka; implemented by Larry Hastings.
This commit is contained in:
parent
f0f4742b49
commit
9cf065cfdc
9 changed files with 3413 additions and 3041 deletions
|
@ -139,27 +139,45 @@ def copystat(src, dst, symlinks=False):
|
|||
only if both `src` and `dst` are symlinks.
|
||||
|
||||
"""
|
||||
def _nop(*args, ns=None):
|
||||
def _nop(*args, ns=None, follow_symlinks=None):
|
||||
pass
|
||||
|
||||
if symlinks and os.path.islink(src) and os.path.islink(dst):
|
||||
stat_func = os.lstat
|
||||
utime_func = os.lutimes if hasattr(os, 'lutimes') else _nop
|
||||
chmod_func = os.lchmod if hasattr(os, 'lchmod') else _nop
|
||||
chflags_func = os.lchflags if hasattr(os, 'lchflags') else _nop
|
||||
# follow symlinks (aka don't not follow symlinks)
|
||||
follow = not (symlinks and os.path.islink(src) and os.path.islink(dst))
|
||||
if follow:
|
||||
# use the real function if it exists
|
||||
def lookup(name):
|
||||
return getattr(os, name, _nop)
|
||||
else:
|
||||
stat_func = os.stat
|
||||
utime_func = os.utime if hasattr(os, 'utime') else _nop
|
||||
chmod_func = os.chmod if hasattr(os, 'chmod') else _nop
|
||||
chflags_func = os.chflags if hasattr(os, 'chflags') else _nop
|
||||
# use the real function only if it exists
|
||||
# *and* it supports follow_symlinks
|
||||
def lookup(name):
|
||||
fn = getattr(os, name, _nop)
|
||||
if fn in os.supports_follow_symlinks:
|
||||
return fn
|
||||
return _nop
|
||||
|
||||
st = stat_func(src)
|
||||
st = lookup("stat")(src, follow_symlinks=follow)
|
||||
mode = stat.S_IMODE(st.st_mode)
|
||||
utime_func(dst, ns=(st.st_atime_ns, st.st_mtime_ns))
|
||||
chmod_func(dst, mode)
|
||||
lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
|
||||
follow_symlinks=follow)
|
||||
try:
|
||||
lookup("chmod")(dst, mode, follow_symlinks=follow)
|
||||
except NotImplementedError:
|
||||
# if we got a NotImplementedError, it's because
|
||||
# * follow_symlinks=False,
|
||||
# * lchown() is unavailable, and
|
||||
# * either
|
||||
# * fchownat() is unvailable or
|
||||
# * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
|
||||
# (it returned ENOSUP.)
|
||||
# therefore we're out of options--we simply cannot chown the
|
||||
# symlink. give up, suppress the error.
|
||||
# (which is what shutil always did in this circumstance.)
|
||||
pass
|
||||
if hasattr(st, 'st_flags'):
|
||||
try:
|
||||
chflags_func(dst, st.st_flags)
|
||||
lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
|
||||
except OSError as why:
|
||||
for err in 'EOPNOTSUPP', 'ENOTSUP':
|
||||
if hasattr(errno, err) and why.errno == getattr(errno, err):
|
||||
|
@ -176,20 +194,11 @@ if hasattr(os, 'listxattr'):
|
|||
If the optional flag `symlinks` is set, symlinks won't be followed.
|
||||
|
||||
"""
|
||||
if symlinks:
|
||||
listxattr = os.llistxattr
|
||||
removexattr = os.lremovexattr
|
||||
setxattr = os.lsetxattr
|
||||
getxattr = os.lgetxattr
|
||||
else:
|
||||
listxattr = os.listxattr
|
||||
removexattr = os.removexattr
|
||||
setxattr = os.setxattr
|
||||
getxattr = os.getxattr
|
||||
|
||||
for attr in listxattr(src):
|
||||
for name in os.listxattr(src, follow_symlinks=symlinks):
|
||||
try:
|
||||
setxattr(dst, attr, getxattr(src, attr))
|
||||
value = os.getxattr(src, name, follow_symlinks=symlinks)
|
||||
os.setxattr(dst, name, value, follow_symlinks=symlinks)
|
||||
except OSError as e:
|
||||
if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA):
|
||||
raise
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue