Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9dc203f

Browse files
committed
merge 3.3 (#21082)
2 parents 78c8538 + 4717e21 commit 9dc203f

4 files changed

Lines changed: 20 additions & 34 deletions

File tree

Doc/library/os.rst

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,11 +1619,8 @@ features:
16191619
The default *mode* is ``0o777`` (octal). On some systems, *mode* is
16201620
ignored. Where it is used, the current umask value is first masked out.
16211621

1622-
If *exist_ok* is ``False`` (the default), an :exc:`OSError` is raised if
1623-
the target directory already exists. If *exist_ok* is ``True`` an
1624-
:exc:`OSError` is still raised if the umask-masked *mode* is different from
1625-
the existing mode, on systems where the mode is used. :exc:`OSError` will
1626-
also be raised if the directory creation fails.
1622+
If *exist_ok* is ``False`` (the default), an :exc:`OSError` is raised if the
1623+
target directory already exists.
16271624

16281625
.. note::
16291626

@@ -1635,6 +1632,13 @@ features:
16351632
.. versionadded:: 3.2
16361633
The *exist_ok* parameter.
16371634

1635+
.. versionchanged:: 3.3.6
1636+
1637+
Before Python 3.3.6, if *exist_ok* was ``True`` and the directory existed,
1638+
:func:`makedirs` would still raise an error if *mode* did not match the
1639+
mode of the existing directory. Since this behavior was impossible to
1640+
implement safely, it was removed in Python 3.3.6. See :issue:`21082`.
1641+
16381642

16391643
.. function:: mkfifo(path, mode=0o666, *, dir_fd=None)
16401644

Lib/os.py

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -206,23 +206,16 @@ def _add(str, fn):
206206
SEEK_CUR = 1
207207
SEEK_END = 2
208208

209-
210-
def _get_masked_mode(mode):
211-
mask = umask(0)
212-
umask(mask)
213-
return mode & ~mask
214-
215209
# Super directory utilities.
216210
# (Inspired by Eric Raymond; the doc strings are mostly his)
217211

218212
def makedirs(name, mode=0o777, exist_ok=False):
219213
"""makedirs(name [, mode=0o777][, exist_ok=False])
220214
221-
Super-mkdir; create a leaf directory and all intermediate ones.
222-
Works like mkdir, except that any intermediate path segment (not
223-
just the rightmost) will be created if it does not exist. If the
224-
target directory with the same mode as we specified already exists,
225-
raises an OSError if exist_ok is False, otherwise no exception is
215+
Super-mkdir; create a leaf directory and all intermediate ones. Works like
216+
mkdir, except that any intermediate path segment (not just the rightmost)
217+
will be created if it does not exist. If the target directory already
218+
exists, raise an OSError if exist_ok is False. Otherwise no exception is
226219
raised. This is recursive.
227220
228221
"""
@@ -243,20 +236,7 @@ def makedirs(name, mode=0o777, exist_ok=False):
243236
try:
244237
mkdir(name, mode)
245238
except OSError as e:
246-
dir_exists = path.isdir(name)
247-
expected_mode = _get_masked_mode(mode)
248-
if dir_exists:
249-
# S_ISGID is automatically copied by the OS from parent to child
250-
# directories on mkdir. Don't consider it being set to be a mode
251-
# mismatch as mkdir does not unset it when not specified in mode.
252-
actual_mode = st.S_IMODE(lstat(name).st_mode) & ~st.S_ISGID
253-
else:
254-
actual_mode = -1
255-
if not (e.errno == errno.EEXIST and exist_ok and dir_exists and
256-
actual_mode == expected_mode):
257-
if dir_exists and actual_mode != expected_mode:
258-
e.strerror += ' (mode %o != expected mode %o)' % (
259-
actual_mode, expected_mode)
239+
if not exist_ok or e.errno != errno.EEXIST or not path.isdir(name):
260240
raise
261241

262242
def removedirs(name):

Lib/test/test_os.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -901,7 +901,7 @@ def test_exist_ok_existing_directory(self):
901901
os.makedirs(path, mode)
902902
self.assertRaises(OSError, os.makedirs, path, mode)
903903
self.assertRaises(OSError, os.makedirs, path, mode, exist_ok=False)
904-
self.assertRaises(OSError, os.makedirs, path, 0o776, exist_ok=True)
904+
os.makedirs(path, 0o776, exist_ok=True)
905905
os.makedirs(path, mode=mode, exist_ok=True)
906906
os.umask(old_mask)
907907

@@ -938,9 +938,8 @@ def test_exist_ok_s_isgid_directory(self):
938938
os.makedirs(path, mode, exist_ok=True)
939939
# remove the bit.
940940
os.chmod(path, stat.S_IMODE(os.lstat(path).st_mode) & ~S_ISGID)
941-
with self.assertRaises(OSError):
942-
# Should fail when the bit is not already set when demanded.
943-
os.makedirs(path, mode | S_ISGID, exist_ok=True)
941+
# May work even when the bit is not already set when demanded.
942+
os.makedirs(path, mode | S_ISGID, exist_ok=True)
944943
finally:
945944
os.umask(old_mask)
946945

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ Library
3838

3939
- Issue #20980: Stop wrapping exception when using ThreadPool.
4040

41+
- Issue #21082: In os.makedirs, do not set the process-wide umask. Note this
42+
changes behavior of makedirs when exist_ok=True.
43+
4144
- Issue #20990: Fix issues found by pyflakes for multiprocessing.
4245

4346
- Issue #21015: SSL contexts will now automatically select an elliptic

0 commit comments

Comments
 (0)