Issue 9299 Add exist_ok parameter to os.makedirs to suppress 'File exists' exception. Patch by Ray Allen.

This commit is contained in:
Terry Reedy 2010-12-02 07:05:56 +00:00
parent 3cdf871a8c
commit 5a22b65117
5 changed files with 58 additions and 11 deletions

View File

@ -1143,17 +1143,20 @@ Files and Directories
Availability: Unix, Windows.
.. function:: makedirs(path[, mode])
.. function:: makedirs(path[, mode][, exist_ok=False])
.. index::
single: directory; creating
single: UNC paths; and os.makedirs()
Recursive directory creation function. Like :func:`mkdir`, but makes all
intermediate-level directories needed to contain the leaf directory. Raises
an :exc:`error` exception if the leaf directory already exists or cannot be
created. The default *mode* is ``0o777`` (octal). On some systems, *mode*
is ignored. Where it is used, the current umask value is first masked out.
intermediate-level directories needed to contain the leaf directory. If
the target directory with the same mode as we specified already exists,
raises an :exc:`OSError` exception if *exist_ok* is False, otherwise no
exception is raised. If the directory cannot be created in other cases,
raises an :exc:`OSError` exception. The default *mode* is ``0o777`` (octal).
On some systems, *mode* is ignored. Where it is used, the current umask
value is first masked out.
.. note::
@ -1162,6 +1165,9 @@ Files and Directories
This function handles UNC paths correctly.
.. versionadded:: 3.2
The *exist_ok* parameter.
.. function:: pathconf(path, name)

View File

@ -114,18 +114,26 @@ 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):
"""makedirs(path [, mode=0o777])
def makedirs(name, mode=0o777, exist_ok=False):
"""makedirs(path [, 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. This is
recursive.
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
raised. This is recursive.
"""
head, tail = path.split(name)
@ -133,14 +141,20 @@ def makedirs(name, mode=0o777):
head, tail = path.split(head)
if head and tail and not path.exists(head):
try:
makedirs(head, mode)
makedirs(head, mode, exist_ok)
except OSError as e:
# be happy if someone already created the path
if e.errno != errno.EEXIST:
raise
if tail == curdir: # xxx/newdir/. exists if xxx/newdir exists
return
mkdir(name, mode)
try:
mkdir(name, mode)
except OSError as e:
import stat as st
if not (e.errno == errno.EEXIST and exist_ok and path.isdir(name) and
st.S_IMODE(lstat(name).st_mode) == _get_masked_mode(mode)):
raise
def removedirs(name):
"""removedirs(path)

View File

@ -630,6 +630,28 @@ class MakedirTests(unittest.TestCase):
'dir5', 'dir6')
os.makedirs(path)
def test_exist_ok_existing_directory(self):
path = os.path.join(support.TESTFN, 'dir1')
mode = 0o777
old_mask = os.umask(0o022)
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, mode=mode, exist_ok=True)
os.umask(old_mask)
def test_exist_ok_existing_regular_file(self):
base = support.TESTFN
path = os.path.join(support.TESTFN, 'dir1')
f = open(path, 'w')
f.write('abc')
f.close()
self.assertRaises(OSError, os.makedirs, path)
self.assertRaises(OSError, os.makedirs, path, exist_ok=False)
self.assertRaises(OSError, os.makedirs, path, exist_ok=True)
os.remove(path)
def tearDown(self):
path = os.path.join(support.TESTFN, 'dir1', 'dir2', 'dir3',
'dir4', 'dir5', 'dir6')

View File

@ -18,6 +18,7 @@ Matthew Ahrens
Nir Aides
Yaniv Aknin
Jyrki Alakuijala
Ray Allen
Billy G. Allie
Kevin Altis
Joe Amenta

View File

@ -46,6 +46,10 @@ Core and Builtins
Library
-------
- Issue #9299: Add exist_ok parameter to os.makedirs to suppress the
'File exists' exception when a target directory already exists with the
specified mode. Patch by Ray Allen.
- Issue #9573: os.fork() now works correctly when triggered as a side effect
of a module import