Skip to content

Calling os.makedirs(..., exists_ok=True) on a directory that is not writable raises the wrong exception #507

Closed
@vtsatskin

Description

@vtsatskin

Describe the bug
When using os.makedirs(..., exists_ok=True) on a directory that does not have write permissions, the raised exception is not correct. FileNotFoundError is raised instead of an expected PermissionError. This is different from the expected behaviour when using real filesystem APIs.

How To Reproduce

import os
import pytest

def test_write_error_raises_permission_error(fs) -> None:
    fs.create_dir("/parent", perm_bits=0o555)

    with pytest.raises(PermissionError):
        os.makedirs("/parent/dir", exist_ok=True)

pytest will fail stating that FileNotFoundError was raised instead of PermissionError.

Here is a truncated output:

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/REDACTED/.venv/python-3.6.7/lib/python3.6/site-packages/pyfakefs/fake_filesystem.py:4334: in makedirs
    self.filesystem.makedirs(name, mode, exist_ok)
/REDACTED/.venv/python-3.6.7/lib/python3.6/site-packages/pyfakefs/fake_filesystem.py:2912: in makedirs
    not isinstance(self.resolve(dir_name), FakeDirectory)):
/REDACTED/.venv/python-3.6.7/lib/python3.6/site-packages/pyfakefs/fake_filesystem.py:2065: in resolve
    file_path, check_read_perm), check_read_perm)
/REDACTED/.venv/python-3.6.7/lib/python3.6/site-packages/pyfakefs/fake_filesystem.py:2016: in get_object_from_normpath
    self.raise_io_error(errno.ENOENT, file_path)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pyfakefs.fake_filesystem.FakeFilesystem object at 0x10d0894e0>
errno = 2, filename = '/parent/dir'

    def raise_io_error(self, errno, filename=None):
        """Raises IOError.
        The error message is constructed from the given error code and shall
        start with the error in the real system.
    
        Args:
            errno: A numeric error code from the C variable errno.
            filename: The name of the affected file, if any.
        """
>       raise IOError(errno, self._error_message(errno), filename)
E       FileNotFoundError: [Errno 2] No such file or directory in the fake filesystem: '/parent/dir'

/REDACTED/.venv/python-3.6.7/lib/python3.6/site-packages/pyfakefs/fake_filesystem.py:996: FileNotFoundError

If we attempt to do something similar with the real filesystem, the correct exception is raised and all the tests pass:

import os
import pytest

def test_real_write_error_raises_permission_error() -> None:
    os.mkdir("parent", mode=0o555)

    with pytest.raises(PermissionError):
        os.makedirs("parent/dir", exist_ok=True)

Your enviroment

Darwin-19.0.0-x86_64-i386-64bit
Python 3.6.7 (v3.6.7:6ec5cf24b7, Oct 20 2018, 03:02:14) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)]
pyfakefs 3.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions