diff options
| -rw-r--r-- | Doc/library/os.rst | 14 | ||||
| -rw-r--r-- | Lib/os.py | 30 | ||||
| -rw-r--r-- | Lib/test/test_os.py | 7 | ||||
| -rw-r--r-- | Misc/NEWS | 3 | 
4 files changed, 20 insertions, 34 deletions
| diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 8e19c25..326114f 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1619,11 +1619,8 @@ features:     The default *mode* is ``0o777`` (octal).  On some systems, *mode* is     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 -   the target directory already exists.  If *exist_ok* is ``True`` an -   :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. +   If *exist_ok* is ``False`` (the default), an :exc:`OSError` is raised if the +   target directory already exists.     .. note:: @@ -1635,6 +1632,13 @@ features:     .. versionadded:: 3.2        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) @@ -206,23 +206,16 @@ SEEK_SET = 0  SEEK_CUR = 1  SEEK_END = 2 - -def _get_masked_mode(mode): -    mask = umask(0) -    umask(mask) -    return mode & ~mask -  # 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]) -    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 with the same mode as we specified already exists, -    raises an OSError if exist_ok is False, otherwise no exception is +    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.      """ @@ -243,20 +236,7 @@ def makedirs(name, mode=0o777, exist_ok=False):      try:          mkdir(name, mode)      except OSError as e: -        dir_exists = 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) +        if not exist_ok or e.errno != errno.EEXIST or not path.isdir(name):              raise  def removedirs(name): diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 5024093..f744815 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -901,7 +901,7 @@ class MakedirTests(unittest.TestCase):          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, 0o776, exist_ok=True) +        os.makedirs(path, 0o776, exist_ok=True)          os.makedirs(path, mode=mode, exist_ok=True)          os.umask(old_mask) @@ -938,9 +938,8 @@ class MakedirTests(unittest.TestCase):              os.makedirs(path, mode, exist_ok=True)              # remove the bit.              os.chmod(path, stat.S_IMODE(os.lstat(path).st_mode) & ~S_ISGID) -            with self.assertRaises(OSError): -                # Should fail when the bit is not already set when demanded. -                os.makedirs(path, mode | S_ISGID, exist_ok=True) +            # May work even when the bit is not already set when demanded. +            os.makedirs(path, mode | S_ISGID, exist_ok=True)          finally:              os.umask(old_mask) @@ -38,6 +38,9 @@ Library  - 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 #21015: SSL contexts will now automatically select an elliptic | 
