mirror of https://github.com/python/cpython.git
merge 3.3 (#21082)
This commit is contained in:
commit
9dc203fff9
|
@ -1619,11 +1619,8 @@ features:
|
||||||
The default *mode* is ``0o777`` (octal). On some systems, *mode* is
|
The default *mode* is ``0o777`` (octal). On some systems, *mode* is
|
||||||
ignored. Where it is used, the current umask value is first masked out.
|
ignored. Where it is used, the current umask value is first masked out.
|
||||||
|
|
||||||
If *exist_ok* is ``False`` (the default), an :exc:`OSError` is raised if
|
If *exist_ok* is ``False`` (the default), an :exc:`OSError` is raised if the
|
||||||
the target directory already exists. If *exist_ok* is ``True`` an
|
target directory already exists.
|
||||||
:exc:`OSError` is still raised if the umask-masked *mode* is different from
|
|
||||||
the existing mode, on systems where the mode is used. :exc:`OSError` will
|
|
||||||
also be raised if the directory creation fails.
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -1635,6 +1632,13 @@ features:
|
||||||
.. versionadded:: 3.2
|
.. versionadded:: 3.2
|
||||||
The *exist_ok* parameter.
|
The *exist_ok* parameter.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.3.6
|
||||||
|
|
||||||
|
Before Python 3.3.6, if *exist_ok* was ``True`` and the directory existed,
|
||||||
|
:func:`makedirs` would still raise an error if *mode* did not match the
|
||||||
|
mode of the existing directory. Since this behavior was impossible to
|
||||||
|
implement safely, it was removed in Python 3.3.6. See :issue:`21082`.
|
||||||
|
|
||||||
|
|
||||||
.. function:: mkfifo(path, mode=0o666, *, dir_fd=None)
|
.. function:: mkfifo(path, mode=0o666, *, dir_fd=None)
|
||||||
|
|
||||||
|
|
30
Lib/os.py
30
Lib/os.py
|
@ -206,23 +206,16 @@ def _add(str, fn):
|
||||||
SEEK_CUR = 1
|
SEEK_CUR = 1
|
||||||
SEEK_END = 2
|
SEEK_END = 2
|
||||||
|
|
||||||
|
|
||||||
def _get_masked_mode(mode):
|
|
||||||
mask = umask(0)
|
|
||||||
umask(mask)
|
|
||||||
return mode & ~mask
|
|
||||||
|
|
||||||
# Super directory utilities.
|
# Super directory utilities.
|
||||||
# (Inspired by Eric Raymond; the doc strings are mostly his)
|
# (Inspired by Eric Raymond; the doc strings are mostly his)
|
||||||
|
|
||||||
def makedirs(name, mode=0o777, exist_ok=False):
|
def makedirs(name, mode=0o777, exist_ok=False):
|
||||||
"""makedirs(name [, mode=0o777][, exist_ok=False])
|
"""makedirs(name [, mode=0o777][, exist_ok=False])
|
||||||
|
|
||||||
Super-mkdir; create a leaf directory and all intermediate ones.
|
Super-mkdir; create a leaf directory and all intermediate ones. Works like
|
||||||
Works like mkdir, except that any intermediate path segment (not
|
mkdir, except that any intermediate path segment (not just the rightmost)
|
||||||
just the rightmost) will be created if it does not exist. If the
|
will be created if it does not exist. If the target directory already
|
||||||
target directory with the same mode as we specified already exists,
|
exists, raise an OSError if exist_ok is False. Otherwise no exception is
|
||||||
raises an OSError if exist_ok is False, otherwise no exception is
|
|
||||||
raised. This is recursive.
|
raised. This is recursive.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -243,20 +236,7 @@ def makedirs(name, mode=0o777, exist_ok=False):
|
||||||
try:
|
try:
|
||||||
mkdir(name, mode)
|
mkdir(name, mode)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
dir_exists = path.isdir(name)
|
if not exist_ok or e.errno != errno.EEXIST or not path.isdir(name):
|
||||||
expected_mode = _get_masked_mode(mode)
|
|
||||||
if dir_exists:
|
|
||||||
# S_ISGID is automatically copied by the OS from parent to child
|
|
||||||
# directories on mkdir. Don't consider it being set to be a mode
|
|
||||||
# mismatch as mkdir does not unset it when not specified in mode.
|
|
||||||
actual_mode = st.S_IMODE(lstat(name).st_mode) & ~st.S_ISGID
|
|
||||||
else:
|
|
||||||
actual_mode = -1
|
|
||||||
if not (e.errno == errno.EEXIST and exist_ok and dir_exists and
|
|
||||||
actual_mode == expected_mode):
|
|
||||||
if dir_exists and actual_mode != expected_mode:
|
|
||||||
e.strerror += ' (mode %o != expected mode %o)' % (
|
|
||||||
actual_mode, expected_mode)
|
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def removedirs(name):
|
def removedirs(name):
|
||||||
|
|
|
@ -901,7 +901,7 @@ def test_exist_ok_existing_directory(self):
|
||||||
os.makedirs(path, mode)
|
os.makedirs(path, mode)
|
||||||
self.assertRaises(OSError, os.makedirs, path, mode)
|
self.assertRaises(OSError, os.makedirs, path, mode)
|
||||||
self.assertRaises(OSError, os.makedirs, path, mode, exist_ok=False)
|
self.assertRaises(OSError, os.makedirs, path, mode, exist_ok=False)
|
||||||
self.assertRaises(OSError, os.makedirs, path, 0o776, exist_ok=True)
|
os.makedirs(path, 0o776, exist_ok=True)
|
||||||
os.makedirs(path, mode=mode, exist_ok=True)
|
os.makedirs(path, mode=mode, exist_ok=True)
|
||||||
os.umask(old_mask)
|
os.umask(old_mask)
|
||||||
|
|
||||||
|
@ -938,9 +938,8 @@ def test_exist_ok_s_isgid_directory(self):
|
||||||
os.makedirs(path, mode, exist_ok=True)
|
os.makedirs(path, mode, exist_ok=True)
|
||||||
# remove the bit.
|
# remove the bit.
|
||||||
os.chmod(path, stat.S_IMODE(os.lstat(path).st_mode) & ~S_ISGID)
|
os.chmod(path, stat.S_IMODE(os.lstat(path).st_mode) & ~S_ISGID)
|
||||||
with self.assertRaises(OSError):
|
# May work even when the bit is not already set when demanded.
|
||||||
# Should fail when the bit is not already set when demanded.
|
os.makedirs(path, mode | S_ISGID, exist_ok=True)
|
||||||
os.makedirs(path, mode | S_ISGID, exist_ok=True)
|
|
||||||
finally:
|
finally:
|
||||||
os.umask(old_mask)
|
os.umask(old_mask)
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,9 @@ Library
|
||||||
|
|
||||||
- Issue #20980: Stop wrapping exception when using ThreadPool.
|
- Issue #20980: Stop wrapping exception when using ThreadPool.
|
||||||
|
|
||||||
|
- Issue #21082: In os.makedirs, do not set the process-wide umask. Note this
|
||||||
|
changes behavior of makedirs when exist_ok=True.
|
||||||
|
|
||||||
- Issue #20990: Fix issues found by pyflakes for multiprocessing.
|
- Issue #20990: Fix issues found by pyflakes for multiprocessing.
|
||||||
|
|
||||||
- Issue #21015: SSL contexts will now automatically select an elliptic
|
- Issue #21015: SSL contexts will now automatically select an elliptic
|
||||||
|
|
Loading…
Reference in New Issue