Skip to content

Commit af7b9ec

Browse files
bpo-25803: Avoid incorrect errors raised by Path.mkdir(exist_ok=True) (#805)
when the OS gives priority to errors such as EACCES over EEXIST.
1 parent 8988945 commit af7b9ec

File tree

3 files changed

+23
-17
lines changed

3 files changed

+23
-17
lines changed

Lib/pathlib.py

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,25 +1220,23 @@ def touch(self, mode=0o666, exist_ok=True):
12201220
os.close(fd)
12211221

12221222
def mkdir(self, mode=0o777, parents=False, exist_ok=False):
1223+
"""
1224+
Create a new directory at this given path.
1225+
"""
12231226
if self._closed:
12241227
self._raise_closed()
1225-
if not parents:
1226-
try:
1227-
self._accessor.mkdir(self, mode)
1228-
except FileExistsError:
1229-
if not exist_ok or not self.is_dir():
1230-
raise
1231-
else:
1232-
try:
1233-
self._accessor.mkdir(self, mode)
1234-
except FileExistsError:
1235-
if not exist_ok or not self.is_dir():
1236-
raise
1237-
except OSError as e:
1238-
if e.errno != ENOENT or self.parent == self:
1239-
raise
1240-
self.parent.mkdir(parents=True)
1241-
self._accessor.mkdir(self, mode)
1228+
try:
1229+
self._accessor.mkdir(self, mode)
1230+
except FileNotFoundError:
1231+
if not parents or self.parent == self:
1232+
raise
1233+
self.parent.mkdir(parents=True)
1234+
self._accessor.mkdir(self, mode)
1235+
except OSError:
1236+
# Cannot rely on checking for EEXIST, since the operating system
1237+
# could give priority to other errors like EACCES or EROFS
1238+
if not exist_ok or not self.is_dir():
1239+
raise
12421240

12431241
def chmod(self, mode):
12441242
"""

Lib/test/test_pathlib.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,6 +1776,11 @@ def test_mkdir_exist_ok_with_parent(self):
17761776
self.assertTrue(p.exists())
17771777
self.assertEqual(p.stat().st_ctime, st_ctime_first)
17781778

1779+
def test_mkdir_exist_ok_root(self):
1780+
# Issue #25803: A drive root could raise PermissionError on Windows
1781+
self.cls('/').resolve().mkdir(exist_ok=True)
1782+
self.cls('/').resolve().mkdir(parents=True, exist_ok=True)
1783+
17791784
@only_nt # XXX: not sure how to test this on POSIX
17801785
def test_mkdir_with_unknown_drive(self):
17811786
for d in 'ZYXWVUTSRQPONMLKJIHGFEDCBA':

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,9 @@ Extension Modules
287287
Library
288288
-------
289289

290+
- bpo-25803: Avoid incorrect errors raised by Path.mkdir(exist_ok=True)
291+
when the OS gives priority to errors such as EACCES over EEXIST.
292+
290293
- bpo-29861: Release references to tasks, their arguments and their results
291294
as soon as they are finished in multiprocessing.Pool.
292295

0 commit comments

Comments
 (0)