summaryrefslogtreecommitdiffstats
path: root/Lib/shutil.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2022-03-09 12:29:33 (GMT)
committerGitHub <noreply@github.com>2022-03-09 12:29:33 (GMT)
commit02fbaf4887deaf0207a5805d3736e0124a694c14 (patch)
tree347a9fc4b3c3150cf1a41eb2b765a7c8f1d5aa3c /Lib/shutil.py
parent5eb03b1b5124659ee63eac7bc03f76cf2c7f9439 (diff)
downloadcpython-02fbaf4887deaf0207a5805d3736e0124a694c14.zip
cpython-02fbaf4887deaf0207a5805d3736e0124a694c14.tar.gz
cpython-02fbaf4887deaf0207a5805d3736e0124a694c14.tar.bz2
bpo-46245: Add optional parameter dir_fd in shutil.rmtree() (GH-30365)
Diffstat (limited to 'Lib/shutil.py')
-rw-r--r--Lib/shutil.py17
1 files changed, 12 insertions, 5 deletions
diff --git a/Lib/shutil.py b/Lib/shutil.py
index eb768f9..22bd86d 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -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