Skip to content

Commit

Permalink
Fix behavior of fake os.makedirs
Browse files Browse the repository at this point in the history
- use a similar implementation as the real fs
  • Loading branch information
mrbean-bremen committed Mar 20, 2024
1 parent 7285b67 commit 0805291
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ The released versions correspond to PyPI releases.
(see [#979](../../issues/979))
* fixed handling of errors on opening files via file descriptor (see [#967](../../issues/967))
* fixed handling of `umask` - it is now applied by default
* fixed behavior of `os.makedirs` (see [#987](../../issues/987))

### Infrastructure
* replace `undefined` by own minimal implementation to avoid importing it
Expand Down
22 changes: 21 additions & 1 deletion pyfakefs/fake_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,27 @@ def makedirs(
"""
if exist_ok is None:
exist_ok = False
self.filesystem.makedirs(name, mode, exist_ok)

# copied and adapted from real implementation in os.py (Python 3.12)
head, tail = self.filesystem.splitpath(name)
if not tail:
head, tail = self.filesystem.splitpath(head)
if head and tail and not self.filesystem.exists(head):
try:
self.makedirs(head, exist_ok=exist_ok)
except FileExistsError:
pass
cdir = self.filesystem.cwd
if isinstance(tail, bytes):
if tail == bytes(cdir, "ASCII"):
return
elif tail == cdir:
return
try:
self.mkdir(name, mode)
except OSError:
if not exist_ok or not self.filesystem.isdir(name):
raise

def _path_with_dir_fd(
self,
Expand Down
8 changes: 8 additions & 0 deletions pyfakefs/tests/fake_os_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1893,6 +1893,14 @@ def test_makedirs_raises_on_empty_path(self):
self.assert_raises_os_error(errno.ENOENT, self.os.makedirs, "", exist_ok=False)
self.assert_raises_os_error(errno.ENOENT, self.os.makedirs, "", exist_ok=True)

def test_makedirs_with_relative_paths(self):
# regression test for #987
path = self.make_path("base", "foo", "..", "bar")
self.os.makedirs(path)
self.assertTrue(self.os.path.isdir(self.make_path("base", "bar")))
self.assertTrue(self.os.path.isdir(self.make_path("base", "foo")))
self.assertFalse(self.os.path.isdir(self.make_path("base", "foo", "bar")))

# test fsync and fdatasync
def test_fsync_raises_on_non_int(self):
with self.assertRaises(TypeError):
Expand Down

0 comments on commit 0805291

Please sign in to comment.