mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
bpo-46245: Add optional parameter dir_fd in shutil.rmtree() (GH-30365)
This commit is contained in:
parent
5eb03b1b51
commit
02fbaf4887
5 changed files with 49 additions and 7 deletions
|
@ -684,9 +684,14 @@ _use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
|
|||
os.scandir in os.supports_fd and
|
||||
os.stat in os.supports_follow_symlinks)
|
||||
|
||||
def rmtree(path, ignore_errors=False, onerror=None):
|
||||
def rmtree(path, ignore_errors=False, onerror=None, *, dir_fd=None):
|
||||
"""Recursively delete a directory tree.
|
||||
|
||||
If dir_fd is not None, it should be a file descriptor open to a directory;
|
||||
path will then be relative to that directory.
|
||||
dir_fd may not be implemented on your platform.
|
||||
If it is unavailable, using it will raise a NotImplementedError.
|
||||
|
||||
If ignore_errors is set, errors are ignored; otherwise, if onerror
|
||||
is set, it is called to handle the error with arguments (func,
|
||||
path, exc_info) where func is platform and implementation dependent;
|
||||
|
@ -695,7 +700,7 @@ def rmtree(path, ignore_errors=False, onerror=None):
|
|||
is false and onerror is None, an exception is raised.
|
||||
|
||||
"""
|
||||
sys.audit("shutil.rmtree", path)
|
||||
sys.audit("shutil.rmtree", path, dir_fd)
|
||||
if ignore_errors:
|
||||
def onerror(*args):
|
||||
pass
|
||||
|
@ -709,12 +714,12 @@ def rmtree(path, ignore_errors=False, onerror=None):
|
|||
# Note: To guard against symlink races, we use the standard
|
||||
# lstat()/open()/fstat() trick.
|
||||
try:
|
||||
orig_st = os.lstat(path)
|
||||
orig_st = os.lstat(path, dir_fd=dir_fd)
|
||||
except Exception:
|
||||
onerror(os.lstat, path, sys.exc_info())
|
||||
return
|
||||
try:
|
||||
fd = os.open(path, os.O_RDONLY)
|
||||
fd = os.open(path, os.O_RDONLY, dir_fd=dir_fd)
|
||||
fd_closed = False
|
||||
except Exception:
|
||||
onerror(os.open, path, sys.exc_info())
|
||||
|
@ -725,7 +730,7 @@ def rmtree(path, ignore_errors=False, onerror=None):
|
|||
try:
|
||||
os.close(fd)
|
||||
fd_closed = True
|
||||
os.rmdir(path)
|
||||
os.rmdir(path, dir_fd=dir_fd)
|
||||
except OSError:
|
||||
onerror(os.rmdir, path, sys.exc_info())
|
||||
else:
|
||||
|
@ -738,6 +743,8 @@ def rmtree(path, ignore_errors=False, onerror=None):
|
|||
if not fd_closed:
|
||||
os.close(fd)
|
||||
else:
|
||||
if dir_fd is not None:
|
||||
raise NotImplementedError("dir_fd unavailable on this platform")
|
||||
try:
|
||||
if _rmtree_islink(path):
|
||||
# symlinks to directories are forbidden, see bug #1669
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue