Skip to content

Commit 1fc1f8d

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

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
@@ -1207,25 +1207,23 @@ def touch(self, mode=0o666, exist_ok=True):
12071207
os.close(fd)
12081208

12091209
def mkdir(self, mode=0o777, parents=False, exist_ok=False):
1210+
"""
1211+
Create a new directory at this given path.
1212+
"""
12101213
if self._closed:
12111214
self._raise_closed()
1212-
if not parents:
1213-
try:
1214-
self._accessor.mkdir(self, mode)
1215-
except FileExistsError:
1216-
if not exist_ok or not self.is_dir():
1217-
raise
1218-
else:
1219-
try:
1220-
self._accessor.mkdir(self, mode)
1221-
except FileExistsError:
1222-
if not exist_ok or not self.is_dir():
1223-
raise
1224-
except OSError as e:
1225-
if e.errno != ENOENT or self.parent == self:
1226-
raise
1227-
self.parent.mkdir(parents=True)
1228-
self._accessor.mkdir(self, mode)
1215+
try:
1216+
self._accessor.mkdir(self, mode)
1217+
except FileNotFoundError:
1218+
if not parents or self.parent == self:
1219+
raise
1220+
self.parent.mkdir(parents=True)
1221+
self._accessor.mkdir(self, mode)
1222+
except OSError:
1223+
# Cannot rely on checking for EEXIST, since the operating system
1224+
# could give priority to other errors like EACCES or EROFS
1225+
if not exist_ok or not self.is_dir():
1226+
raise
12291227

12301228
def chmod(self, mode):
12311229
"""

Lib/test/test_pathlib.py

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

1730+
def test_mkdir_exist_ok_root(self):
1731+
# Issue #25803: A drive root could raise PermissionError on Windows
1732+
self.cls('/').resolve().mkdir(exist_ok=True)
1733+
self.cls('/').resolve().mkdir(parents=True, exist_ok=True)
1734+
17301735
@only_nt # XXX: not sure how to test this on POSIX
17311736
def test_mkdir_with_unknown_drive(self):
17321737
for d in 'ZYXWVUTSRQPONMLKJIHGFEDCBA':

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ Extension Modules
4646
Library
4747
-------
4848

49+
- bpo-25803: Avoid incorrect errors raised by Path.mkdir(exist_ok=True)
50+
when the OS gives priority to errors such as EACCES over EEXIST.
51+
4952
- bpo-29861: Release references to tasks, their arguments and their results
5053
as soon as they are finished in multiprocessing.Pool.
5154

0 commit comments

Comments
 (0)