bpo-42367: Restore os.makedirs() ability to apply *mode* recursively
Allow os.makedirs() to apply the *mode* argument to any intermediate directories that are created.
This commit is contained in:
parent
46b5c6be29
commit
128ff8b466
|
@ -2055,7 +2055,8 @@ features:
|
|||
Accepts a :term:`path-like object`.
|
||||
|
||||
|
||||
.. function:: makedirs(name, mode=0o777, exist_ok=False)
|
||||
.. function:: makedirs(name, mode=0o777, exist_ok=False, *, \
|
||||
recursive_mode=False)
|
||||
|
||||
.. index::
|
||||
single: directory; creating
|
||||
|
@ -2073,6 +2074,9 @@ features:
|
|||
If *exist_ok* is ``False`` (the default), an :exc:`FileExistsError` is
|
||||
raised if the target directory already exists.
|
||||
|
||||
If *recursive_mode* is ``True``, the *mode* argument will affect the file
|
||||
permission bits of any newly-created, intermediate-level directories.
|
||||
|
||||
.. note::
|
||||
|
||||
:func:`makedirs` will become confused if the path elements to create
|
||||
|
@ -2099,6 +2103,9 @@ features:
|
|||
The *mode* argument no longer affects the file permission bits of
|
||||
newly-created intermediate-level directories.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
The *recursive_mode* parameter.
|
||||
|
||||
|
||||
.. function:: mkfifo(path, mode=0o666, *, dir_fd=None)
|
||||
|
||||
|
|
|
@ -259,6 +259,9 @@ descriptors without copying between kernel address space and user
|
|||
address space, where one of the file descriptors must refer to a
|
||||
pipe. (Contributed by Pablo Galindo in :issue:`41625`.)
|
||||
|
||||
The :func:`os.makedirs` function now has a *recursive_mode* parameter.
|
||||
(Contributed by Zackery Spytz in :issue:`42367`.)
|
||||
|
||||
pathlib
|
||||
-------
|
||||
|
||||
|
|
14
Lib/os.py
14
Lib/os.py
|
@ -197,14 +197,16 @@ SEEK_END = 2
|
|||
# Super directory utilities.
|
||||
# (Inspired by Eric Raymond; the doc strings are mostly his)
|
||||
|
||||
def makedirs(name, mode=0o777, exist_ok=False):
|
||||
"""makedirs(name [, mode=0o777][, exist_ok=False])
|
||||
def makedirs(name, mode=0o777, exist_ok=False, *, recursive_mode=False):
|
||||
"""makedirs(name [, mode=0o777][, exist_ok=False][, recursive_mode=False])
|
||||
|
||||
Super-mkdir; create a leaf directory and all intermediate ones. Works like
|
||||
mkdir, except that any intermediate path segment (not just the rightmost)
|
||||
will be created if it does not exist. If the target directory already
|
||||
exists, raise an OSError if exist_ok is False. Otherwise no exception is
|
||||
raised. This is recursive.
|
||||
raised. If recursive_mode is True, the mode argument will affect the file
|
||||
permission bits of any newly-created, intermediate-level directories. This
|
||||
is recursive.
|
||||
|
||||
"""
|
||||
head, tail = path.split(name)
|
||||
|
@ -212,7 +214,11 @@ def makedirs(name, mode=0o777, exist_ok=False):
|
|||
head, tail = path.split(head)
|
||||
if head and tail and not path.exists(head):
|
||||
try:
|
||||
makedirs(head, exist_ok=exist_ok)
|
||||
if recursive_mode:
|
||||
makedirs(head, mode=mode, exist_ok=exist_ok,
|
||||
recursive_mode=True)
|
||||
else:
|
||||
makedirs(head, exist_ok=exist_ok)
|
||||
except FileExistsError:
|
||||
# Defeats race condition when another thread created the path
|
||||
pass
|
||||
|
|
|
@ -1572,16 +1572,19 @@ class MakedirTests(unittest.TestCase):
|
|||
os.makedirs(path)
|
||||
|
||||
def test_mode(self):
|
||||
parent = os.path.join(os_helper.TESTFN, 'dir1')
|
||||
path = os.path.join(parent, 'dir2')
|
||||
with os_helper.temp_umask(0o002):
|
||||
base = os_helper.TESTFN
|
||||
parent = os.path.join(base, 'dir1')
|
||||
path = os.path.join(parent, 'dir2')
|
||||
os.makedirs(path, 0o555)
|
||||
self.assertTrue(os.path.exists(path))
|
||||
self.assertTrue(os.path.isdir(path))
|
||||
if os.name != 'nt':
|
||||
self.assertEqual(os.stat(path).st_mode & 0o777, 0o555)
|
||||
self.assertEqual(os.stat(parent).st_mode & 0o777, 0o775)
|
||||
for mode, recursive_mode, path_mode, parent_mode in \
|
||||
(0o555, False, 0o555, 0o775), (0o770, True, 0o770, 0o770):
|
||||
os.makedirs(path, mode, recursive_mode=recursive_mode)
|
||||
self.assertTrue(os.path.exists(path))
|
||||
self.assertTrue(os.path.isdir(path))
|
||||
if os.name != 'nt':
|
||||
self.assertEqual(os.stat(path).st_mode & 0o777, path_mode)
|
||||
self.assertEqual(os.stat(parent).st_mode & 0o777,
|
||||
parent_mode)
|
||||
shutil.rmtree(parent)
|
||||
|
||||
def test_exist_ok_existing_directory(self):
|
||||
path = os.path.join(os_helper.TESTFN, 'dir1')
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
The :func:`os.makedirs` function now has a *recursive_mode* parameter.
|
Loading…
Reference in New Issue